- Timestamp:
- 05/07/20 17:41:18 (5 years ago)
- Location:
- branches/2521_ProblemRefactoring/HeuristicLab.Problems.Orienteering/3.3
- Files:
-
- 1 added
- 4 deleted
- 8 edited
Legend:
- Unmodified
- Added
- Removed
-
branches/2521_ProblemRefactoring/HeuristicLab.Problems.Orienteering/3.3/Creators/GreedyOrienteeringTourCreator.cs
r17226 r17525 22 22 using System.Collections.Generic; 23 23 using System.Linq; 24 using HEAL.Attic; 24 25 using HeuristicLab.Common; 25 26 using HeuristicLab.Core; … … 27 28 using HeuristicLab.Encodings.IntegerVectorEncoding; 28 29 using HeuristicLab.Parameters; 29 using HEAL.Attic;30 30 31 31 namespace HeuristicLab.Problems.Orienteering { … … 43 43 public override bool CanChangeName { get { return false; } } 44 44 45 #region Parameter Properties 46 public ILookupParameter<DistanceMatrix> DistanceMatrixParameter { 47 get { return (ILookupParameter<DistanceMatrix>)Parameters["DistanceMatrix"]; } 45 public ILookupParameter<IOrienteeringProblemData> OrienteeringProblemDataParameter { 46 get { return (ILookupParameter<IOrienteeringProblemData>)Parameters["OrienteeringProblemData"]; } 48 47 } 49 public ILookupParameter<DoubleArray> ScoresParameter {50 get { return (ILookupParameter<DoubleArray>)Parameters["Scores"]; }51 }52 public ILookupParameter<DoubleValue> MaximumDistanceParameter {53 get { return (ILookupParameter<DoubleValue>)Parameters["MaximumDistance"]; }54 }55 public ILookupParameter<IntValue> StartingPointParameter {56 get { return (ILookupParameter<IntValue>)Parameters["StartingPoint"]; }57 }58 public ILookupParameter<IntValue> TerminalPointParameter {59 get { return (ILookupParameter<IntValue>)Parameters["TerminalPoint"]; }60 }61 public ILookupParameter<DoubleValue> PointVisitingCostsParameter {62 get { return (ILookupParameter<DoubleValue>)Parameters["PointVisitingCosts"]; }63 }64 #endregion65 48 66 49 [StorableConstructor] … … 71 54 public GreedyOrienteeringTourCreator() 72 55 : base() { 73 Parameters.Add(new LookupParameter<DistanceMatrix>("DistanceMatrix", "The matrix which contains the distances between the points.")); 74 Parameters.Add(new LookupParameter<DoubleArray>("Scores", "The scores of the points.")); 75 Parameters.Add(new LookupParameter<DoubleValue>("MaximumDistance", "The maximum distance constraint for a Orienteering solution.")); 76 Parameters.Add(new LookupParameter<IntValue>("StartingPoint", "Index of the starting point.")); 77 Parameters.Add(new LookupParameter<IntValue>("TerminalPoint", "Index of the ending point.")); 78 Parameters.Add(new LookupParameter<DoubleValue>("PointVisitingCosts", "The costs for visiting a point.")); 56 Parameters.Add(new LookupParameter<IOrienteeringProblemData>("OrienteeringProblemData", "The main data that comprises the orienteering problem.")); 79 57 } 80 58 … … 84 62 85 63 protected override IntegerVector Create(IRandom random, IntValue length, IntMatrix bounds) { 86 int startPoint = StartingPointParameter.ActualValue.Value; 87 int endPoint = TerminalPointParameter.ActualValue.Value; 88 int numPoints = ScoresParameter.ActualValue.Length; 89 var distances = DistanceMatrixParameter.ActualValue; 90 double pointVisitingCosts = PointVisitingCostsParameter.ActualValue.Value; 91 double maxDistance = MaximumDistanceParameter.ActualValue.Value; 92 var scores = ScoresParameter.ActualValue; 64 var data = OrienteeringProblemDataParameter.ActualValue; 93 65 94 66 // Find all points within the maximum distance allowed (ellipse) 95 67 var feasiblePoints = ( 96 from point in Enumerable.Range(0, numPoints) 97 let distance = distances[startPoint, point] + distances[point, endPoint] + pointVisitingCosts 98 let score = scores[point] 99 where distance <= maxDistance 100 where point != startPoint && point != endPoint 68 from point in Enumerable.Range(0, data.RoutingData.Cities) 69 let travelCosts = data.RoutingData.GetDistance(data.StartingPoint, point) 70 + data.RoutingData.GetDistance(point, data.TerminalPoint) + data.PointVisitingCosts 71 let score = data.GetScore(point) 72 where travelCosts <= data.MaximumTravelCosts 73 where point != data.StartingPoint && point != data.TerminalPoint 101 74 orderby score descending 102 75 select point … … 105 78 // Add the starting and terminus point 106 79 var tour = new List<int> { 107 startPoint,108 endPoint80 data.StartingPoint, 81 data.TerminalPoint 109 82 }; 110 double tourLength = d istances[startPoint, endPoint];83 double tourLength = data.RoutingData.GetDistance(data.StartingPoint, data.TerminalPoint); 111 84 112 85 // Add points in a greedy way … … 118 91 for (int insertPosition = 1; insertPosition < tour.Count; insertPosition++) { 119 92 // Create the candidate tour 120 double detour = distances.CalculateInsertionCosts(tour, insertPosition, feasiblePoints[i], pointVisitingCosts);93 double detour = OrienteeringProblem.CalculateInsertionCosts(data, tour, insertPosition, feasiblePoints[i]); 121 94 122 95 // If the insertion would be feasible, perform it 123 if (tourLength + detour <= maxDistance) {96 if (tourLength + detour <= data.MaximumTravelCosts) { 124 97 tour.Insert(insertPosition, feasiblePoints[i]); 125 98 tourLength += detour; -
branches/2521_ProblemRefactoring/HeuristicLab.Problems.Orienteering/3.3/DistanceMatrix.cs
r17226 r17525 22 22 using System; 23 23 using System.Collections.Generic; 24 using HEAL.Attic; 24 25 using HeuristicLab.Common; 25 26 using HeuristicLab.Core; 26 27 using HeuristicLab.Data; 27 using HEAL.Attic;28 28 29 29 namespace HeuristicLab.Problems.Orienteering { … … 67 67 return detour; 68 68 } 69 public double CalculateReplacementCosts( List<int> path, int replacePosition, int point) {69 public double CalculateReplacementCosts(IList<int> path, int replacePosition, int point) { 70 70 double detour = this[path[replacePosition - 1], point] + this[point, path[replacePosition + 1]]; 71 71 detour -= this[path[replacePosition - 1], path[replacePosition]] + this[path[replacePosition], path[replacePosition + 1]]; 72 72 return detour; 73 73 } 74 public double CalculateRemovementSaving( List<int> path, int removePosition, double pointVisitingCosts) {74 public double CalculateRemovementSaving(IList<int> path, int removePosition, double pointVisitingCosts) { 75 75 double saving = this[path[removePosition - 1], path[removePosition]]; 76 76 saving += this[path[removePosition], path[removePosition + 1]]; -
branches/2521_ProblemRefactoring/HeuristicLab.Problems.Orienteering/3.3/HeuristicLab.Problems.Orienteering-3.3.csproj
r16723 r17525 89 89 </ItemGroup> 90 90 <ItemGroup> 91 <Compile Include="Analyzers\BestOrienteeringSolutionAnalyzer.cs" />92 91 <Compile Include="Creators\GreedyOrienteeringTourCreator.cs" /> 93 92 <Compile Include="DistanceMatrix.cs" /> 94 <Compile Include="OrienteeringEvaluationResult.cs" />95 93 <Compile Include="Improvers\OrienteeringLocalImprovementOperator.cs" /> 96 <Compile Include="Interfaces\IOrienteeringEvaluator.cs" />97 <Compile Include="Evaluators\OrienteeringEvaluator.cs" />98 94 <Compile Include="Interfaces\IOrienteeringSolutionCreator.cs" /> 95 <Compile Include="OrienteeringProblemData.cs" /> 99 96 <Compile Include="OrienteeringProblem.cs" /> 100 97 <Compile Include="OrienteeringSolution.cs" /> … … 144 141 <Private>False</Private> 145 142 </ProjectReference> 143 <ProjectReference Include="..\..\HeuristicLab.Encodings.PermutationEncoding\3.3\HeuristicLab.Encodings.PermutationEncoding-3.3.csproj"> 144 <Project>{DBECB8B0-B166-4133-BAF1-ED67C3FD7FCA}</Project> 145 <Name>HeuristicLab.Encodings.PermutationEncoding-3.3</Name> 146 <Private>False</Private> 147 </ProjectReference> 146 148 <ProjectReference Include="..\..\HeuristicLab.Operators\3.3\HeuristicLab.Operators-3.3.csproj"> 147 149 <Project>{23DA7FF4-D5B8-41B6-AA96-F0561D24F3EE}</Project> … … 179 181 <Private>False</Private> 180 182 </ProjectReference> 183 <ProjectReference Include="..\..\HeuristicLab.Problems.TravelingSalesman\3.3\HeuristicLab.Problems.TravelingSalesman-3.3.csproj"> 184 <Project>{d767c38d-8014-46b0-9a32-03a3aecce34a}</Project> 185 <Name>HeuristicLab.Problems.TravelingSalesman-3.3</Name> 186 <Private>False</Private> 187 </ProjectReference> 181 188 <ProjectReference Include="..\..\HeuristicLab.Random\3.3\HeuristicLab.Random-3.3.csproj"> 182 189 <Project>{F4539FB6-4708-40C9-BE64-0A1390AEA197}</Project> … … 197 204 </Reference> 198 205 </ItemGroup> 206 <ItemGroup /> 199 207 <Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" /> 200 208 <PropertyGroup> -
branches/2521_ProblemRefactoring/HeuristicLab.Problems.Orienteering/3.3/Improvers/OrienteeringLocalImprovementOperator.cs
r17226 r17525 22 22 using System.Collections.Generic; 23 23 using System.Linq; 24 using HEAL.Attic; 24 25 using HeuristicLab.Common; 25 26 using HeuristicLab.Core; … … 29 30 using HeuristicLab.Optimization; 30 31 using HeuristicLab.Parameters; 31 using HEAL.Attic;32 32 33 33 namespace HeuristicLab.Problems.Orienteering { … … 45 45 get { return (ILookupParameter<IntegerVector>)Parameters["OrienteeringSolution"]; } 46 46 } 47 public ILookupParameter<DistanceMatrix> DistanceMatrixParameter { 48 get { return (ILookupParameter<DistanceMatrix>)Parameters["DistanceMatrix"]; } 49 } 50 public ILookupParameter<DoubleArray> ScoresParameter { 51 get { return (ILookupParameter<DoubleArray>)Parameters["Scores"]; } 52 } 53 public ILookupParameter<DoubleValue> MaximumDistanceParameter { 54 get { return (ILookupParameter<DoubleValue>)Parameters["MaximumDistance"]; } 55 } 56 public ILookupParameter<IntValue> StartingPointParameter { 57 get { return (ILookupParameter<IntValue>)Parameters["StartingPoint"]; } 58 } 59 public ILookupParameter<IntValue> TerminalPointParameter { 60 get { return (ILookupParameter<IntValue>)Parameters["TerminalPoint"]; } 61 } 62 public ILookupParameter<DoubleValue> PointVisitingCostsParameter { 63 get { return (ILookupParameter<DoubleValue>)Parameters["PointVisitingCosts"]; } 64 } 47 public ILookupParameter<IOrienteeringProblemData> OrienteeringProblemDataParameter { 48 get { return (ILookupParameter<IOrienteeringProblemData>)Parameters["OrienteeringProblemData"]; } 49 } 50 65 51 #region ILocalImprovementOperator Parameters 66 52 public IValueLookupParameter<IntValue> LocalIterationsParameter { … … 96 82 : base() { 97 83 Parameters.Add(new LookupParameter<IntegerVector>("OrienteeringSolution", "The Orienteering Solution given in path representation.")); 98 Parameters.Add(new LookupParameter<DistanceMatrix>("DistanceMatrix", "The matrix which contains the distances between the points.")); 99 Parameters.Add(new LookupParameter<DoubleArray>("Scores", "The scores of the points.")); 100 Parameters.Add(new LookupParameter<DoubleValue>("MaximumDistance", "The maximum distance constraint for a Orienteering solution.")); 101 Parameters.Add(new LookupParameter<IntValue>("StartingPoint", "Index of the starting point.")); 102 Parameters.Add(new LookupParameter<IntValue>("TerminalPoint", "Index of the ending point.")); 103 Parameters.Add(new LookupParameter<DoubleValue>("PointVisitingCosts", "The costs for visiting a point.")); 84 Parameters.Add(new LookupParameter<IOrienteeringProblemData>("OrienteeringProblemData", "The main data that comprises the orienteering problem.")); 104 85 105 86 Parameters.Add(new ValueLookupParameter<IntValue>("LocalIterations", "The number of iterations that have already been performed.", new IntValue(0))); … … 118 99 119 100 public override IOperation Apply() { 120 int numPoints = ScoresParameter.ActualValue.Length; 121 var distances = DistanceMatrixParameter.ActualValue; 122 var scores = ScoresParameter.ActualValue; 123 double pointVisitingCosts = PointVisitingCostsParameter.ActualValue.Value; 124 double maxLength = MaximumDistanceParameter.ActualValue.Value; 101 var data = OrienteeringProblemDataParameter.ActualValue; 125 102 int maxIterations = MaximumIterationsParameter.ActualValue.Value; 126 103 int maxBlockLength = MaximumBlockLengthParmeter.Value.Value; … … 132 109 133 110 double tourLength = 0; 134 double tourScore = tour.Sum(point => scores[point]);111 double tourScore = tour.Sum(point => data.GetScore(point)); 135 112 136 113 var localIterations = LocalIterationsParameter.ActualValue; … … 143 120 144 121 if (localIterations.Value == 0) 145 tourLength = distances.CalculateTourLength(tour, pointVisitingCosts);122 tourLength = OrienteeringProblem.CalculateTravelCosts(data, tour); 146 123 147 124 // Try to shorten the path 148 ShortenPath(tour, d istances, maxBlockLength, useMaxBlockLength, ref tourLength, ref evaluations);125 ShortenPath(tour, data, maxBlockLength, useMaxBlockLength, ref tourLength, ref evaluations); 149 126 150 127 // Determine all points that have not yet been visited by this tour 151 var visitablePoints = Enumerable.Range(0, numPoints).Except(tour).ToList();128 var visitablePoints = Enumerable.Range(0, data.RoutingData.Cities).Except(tour).ToList(); 152 129 153 130 // Determine if any of the visitable points can be included at any position within the tour 154 IncludeNewPoints(tour, visitablePoints, 155 distances, pointVisitingCosts, maxLength, scores, 156 ref tourLength, ref tourScore, ref evaluations, ref solutionChanged); 131 IncludeNewPoints(tour, visitablePoints, data, ref tourLength, ref tourScore, ref evaluations, ref solutionChanged); 157 132 158 133 // Determine if any of the visitable points can take the place of an already visited point in the tour to improve the scores 159 ReplacePoints(tour, visitablePoints, 160 distances, maxLength, scores, 161 ref tourLength, ref tourScore, ref evaluations, ref solutionChanged); 134 ReplacePoints(tour, visitablePoints, data, ref tourLength, ref tourScore, ref evaluations, ref solutionChanged); 162 135 163 136 localIterations.Value++; … … 174 147 } 175 148 176 private void ShortenPath(List<int> tour, DistanceMatrix distances, int maxBlockLength, bool useMaxBlockLength, ref double tourLength, ref int evaluations) {149 private void ShortenPath(List<int> tour, IOrienteeringProblemData data, int maxBlockLength, bool useMaxBlockLength, ref double tourLength, ref int evaluations) { 177 150 bool solutionChanged; 178 151 int pathSize = tour.Count; … … 195 168 double newLength = tourLength; 196 169 // Recalculate length of whole swapped part, in case distances are not symmetric 197 for (int index = position - 1; index < position + blockLength; index++) newLength -= d istances[tour[index], tour[index + 1]];198 for (int index = position + blockLength - 1; index > position; index--) newLength += d istances[tour[index], tour[index - 1]];199 newLength += d istances[tour[position - 1], tour[position + blockLength - 1]];200 newLength += d istances[tour[position], tour[position + blockLength]];170 for (int index = position - 1; index < position + blockLength; index++) newLength -= data.RoutingData.GetDistance(tour[index], tour[index + 1]); 171 for (int index = position + blockLength - 1; index > position; index--) newLength += data.RoutingData.GetDistance(tour[index], tour[index - 1]); 172 newLength += data.RoutingData.GetDistance(tour[position - 1], tour[position + blockLength - 1]); 173 newLength += data.RoutingData.GetDistance(tour[position], tour[position + blockLength]); 201 174 202 175 if (newLength < tourLength - 0.00001) { … … 217 190 } 218 191 219 private void IncludeNewPoints(List<int> tour, List<int> visitablePoints, 220 DistanceMatrix distances, double pointVisitingCosts, double maxLength, DoubleArray scores, 192 private void IncludeNewPoints(List<int> tour, List<int> visitablePoints, IOrienteeringProblemData data, 221 193 ref double tourLength, ref double tourScore, ref int evaluations, ref bool solutionChanged) { 222 194 … … 231 203 evaluations++; 232 204 233 double detour = distances.CalculateInsertionCosts(tour, tourPosition, visitablePoints[i], pointVisitingCosts);205 double detour = OrienteeringProblem.CalculateInsertionCosts(data, tour, tourPosition, visitablePoints[i]); 234 206 235 207 // Determine if including the point does not violate any constraint 236 if (tourLength + detour <= maxLength) {208 if (tourLength + detour <= data.MaximumTravelCosts) { 237 209 // Insert the new point at this position 238 210 tour.Insert(tourPosition, visitablePoints[i]); … … 240 212 // Update the overall tour tourLength and score 241 213 tourLength += detour; 242 tourScore += scores[visitablePoints[i]];214 tourScore += data.GetScore(visitablePoints[i]); 243 215 244 216 // Re-run this optimization … … 249 221 } 250 222 251 private void ReplacePoints(List<int> tour, List<int> visitablePoints, 252 DistanceMatrix distances, double maxLength, DoubleArray scores, 223 private void ReplacePoints(List<int> tour, List<int> visitablePoints, IOrienteeringProblemData data, 253 224 ref double tourLength, ref double tourScore, ref int evaluations, ref bool solutionChanged) { 254 225 … … 263 234 evaluations++; 264 235 265 double detour = distances.CalculateReplacementCosts(tour, tourPosition, visitablePoints[i]);266 267 double oldPointScore = scores[tour[tourPosition]];268 double newPointScore = scores[visitablePoints[i]];269 270 if ((tourLength + detour <= maxLength) && (newPointScore > oldPointScore)) {236 double detour = OrienteeringProblem.CalculateReplacementCosts(data, tour, tourPosition, visitablePoints[i]); 237 238 double oldPointScore = data.GetScore(tour[tourPosition]); 239 double newPointScore = data.GetScore(visitablePoints[i]); 240 241 if ((tourLength + detour <= data.MaximumTravelCosts) && (newPointScore > oldPointScore)) { 271 242 // Replace the old point by the new one 272 243 tour[tourPosition] = visitablePoints[i]; -
branches/2521_ProblemRefactoring/HeuristicLab.Problems.Orienteering/3.3/Interfaces/IOrienteeringSolutionCreator.cs
r17226 r17525 20 20 #endregion 21 21 22 using HEAL.Attic; 22 23 using HeuristicLab.Core; 23 using HeuristicLab.Data;24 24 using HeuristicLab.Encodings.IntegerVectorEncoding; 25 using HEAL.Attic;26 25 27 26 namespace HeuristicLab.Problems.Orienteering { 28 27 [StorableType("7E0D4527-4D8C-4FBA-BB3A-26F20B6463ED")] 29 28 public interface IOrienteeringSolutionCreator : IIntegerVectorCreator { 30 ILookupParameter<DistanceMatrix> DistanceMatrixParameter { get; } 31 ILookupParameter<DoubleArray> ScoresParameter { get; } 32 ILookupParameter<DoubleValue> MaximumDistanceParameter { get; } 33 ILookupParameter<IntValue> StartingPointParameter { get; } 34 ILookupParameter<IntValue> TerminalPointParameter { get; } 35 ILookupParameter<DoubleValue> PointVisitingCostsParameter { get; } 29 ILookupParameter<IOrienteeringProblemData> OrienteeringProblemDataParameter { get; } 36 30 } 37 31 } -
branches/2521_ProblemRefactoring/HeuristicLab.Problems.Orienteering/3.3/OrienteeringProblem.cs
r17226 r17525 20 20 #endregion 21 21 22 using System ;22 using System.Collections.Generic; 23 23 using System.IO; 24 24 using System.Linq; 25 using System.Threading; 26 using HEAL.Attic; 25 27 using HeuristicLab.Analysis; 26 28 using HeuristicLab.Common; 27 29 using HeuristicLab.Core; 28 using HeuristicLab.Data;29 30 using HeuristicLab.Encodings.IntegerVectorEncoding; 30 31 using HeuristicLab.Optimization; 31 32 using HeuristicLab.Optimization.Operators; 32 33 using HeuristicLab.Parameters; 33 using HEAL.Attic;34 34 using HeuristicLab.Problems.Instances; 35 35 using HeuristicLab.Problems.Instances.Types; 36 using HeuristicLab.Problems.TravelingSalesman; 36 37 37 38 namespace HeuristicLab.Problems.Orienteering { … … 39 40 [Creatable(CreatableAttribute.Categories.CombinatorialProblems, Priority = 115)] 40 41 [StorableType("0B8DB4A4-F183-4368-86C6-C51289B183D2")] 41 public sealed class OrienteeringProblem 42 : SingleObjectiveHeuristicOptimizationProblem<IOrienteeringEvaluator, IOrienteeringSolutionCreator>, 43 IStorableContent, IProblemInstanceConsumer<OPData>, IProblemInstanceConsumer<TSPData>, IProblemInstanceConsumer<CVRPData> { 44 45 public string Filename { get; set; } 46 47 #region Parameter Properties 48 public OptionalValueParameter<DoubleMatrix> CoordinatesParameter { 49 get { return (OptionalValueParameter<DoubleMatrix>)Parameters["Coordinates"]; } 50 } 51 public IValueParameter<DistanceMatrix> DistanceMatrixParameter { 52 get { return (IValueParameter<DistanceMatrix>)Parameters["DistanceMatrix"]; } 53 } 54 55 public IFixedValueParameter<IntValue> StartingPointParameter { 56 get { return (IFixedValueParameter<IntValue>)Parameters["StartingPoint"]; } 57 } 58 public IFixedValueParameter<IntValue> TerminalPointParameter { 59 get { return (IFixedValueParameter<IntValue>)Parameters["TerminalPoint"]; } 60 } 61 public IFixedValueParameter<DoubleValue> MaximumDistanceParameter { 62 get { return (IFixedValueParameter<DoubleValue>)Parameters["MaximumDistance"]; } 63 } 64 public IValueParameter<DoubleArray> ScoresParameter { 65 get { return (IValueParameter<DoubleArray>)Parameters["Scores"]; } 66 } 67 public IFixedValueParameter<DoubleValue> PointVisitingCostsParameter { 68 get { return (IFixedValueParameter<DoubleValue>)Parameters["PointVisitingCosts"]; } 69 } 70 71 public OptionalValueParameter<IntegerVector> BestKnownSolutionParameter { 72 get { return (OptionalValueParameter<IntegerVector>)Parameters["BestKnownSolution"]; } 73 } 74 #endregion 75 76 #region Properties 77 public DoubleMatrix Coordinates { 78 get { return CoordinatesParameter.Value; } 79 set { CoordinatesParameter.Value = value; } 80 } 81 public DistanceMatrix DistanceMatrix { 82 get { return DistanceMatrixParameter.Value; } 83 set { DistanceMatrixParameter.Value = value; } 84 } 85 public int StartingPoint { 86 get { return StartingPointParameter.Value.Value; } 87 set { StartingPointParameter.Value.Value = value; } 88 } 89 public int TerminalPoint { 90 get { return TerminalPointParameter.Value.Value; } 91 set { TerminalPointParameter.Value.Value = value; } 92 } 93 public double MaximumDistance { 94 get { return MaximumDistanceParameter.Value.Value; } 95 set { MaximumDistanceParameter.Value.Value = value; } 96 } 97 public DoubleArray Scores { 98 get { return ScoresParameter.Value; } 99 set { ScoresParameter.Value = value; } 100 } 101 public double PointVisitingCosts { 102 get { return PointVisitingCostsParameter.Value.Value; } 103 set { PointVisitingCostsParameter.Value.Value = value; } 104 } 105 public IntegerVector BestKnownSolution { 42 public sealed class OrienteeringProblem : IntegerVectorProblem, 43 IProblemInstanceConsumer<OPData>, IProblemInstanceConsumer<TSPData>, IProblemInstanceConsumer<CVRPData> { 44 45 [Storable] public ValueParameter<IOrienteeringProblemData> OrienteeringProblemDataParameter { get; private set; } 46 [Storable] public OptionalValueParameter<OrienteeringSolution> BestKnownSolutionParameter { get; private set; } 47 [Storable] private IResultParameter<OrienteeringSolution> BestOrienteeringSolutionParameter { get; set; } 48 public IResultDefinition<OrienteeringSolution> BestOrienteeringSolution => BestOrienteeringSolutionParameter; 49 50 public IOrienteeringProblemData OrienteeringProblemData { 51 get { return OrienteeringProblemDataParameter.Value; } 52 set { OrienteeringProblemDataParameter.Value = value; } 53 } 54 public OrienteeringSolution BestKnownSolution { 106 55 get { return BestKnownSolutionParameter.Value; } 107 56 set { BestKnownSolutionParameter.Value = value; } 108 57 } 109 private BestOrienteeringSolutionAnalyzer BestOrienteeringSolutionAnalyser {110 get { return Operators.OfType<BestOrienteeringSolutionAnalyzer>().SingleOrDefault(); }111 }112 #endregion113 58 114 59 [StorableConstructor] … … 117 62 private OrienteeringProblem(OrienteeringProblem original, Cloner cloner) 118 63 : base(original, cloner) { 119 RegisterEventHandlers(); 64 OrienteeringProblemDataParameter = cloner.Clone(original.OrienteeringProblemDataParameter); 65 BestKnownSolutionParameter = cloner.Clone(original.BestKnownSolutionParameter); 66 BestOrienteeringSolutionParameter = cloner.Clone(original.BestOrienteeringSolutionParameter); 120 67 } 121 68 public override IDeepCloneable Clone(Cloner cloner) { … … 123 70 } 124 71 public OrienteeringProblem() 125 : base(new OrienteeringEvaluator(), new GreedyOrienteeringTourCreator()) { 126 Parameters.Add(new OptionalValueParameter<DoubleMatrix>("Coordinates", "The x- and y-Coordinates of the points.")); 127 Parameters.Add(new ValueParameter<DistanceMatrix>("DistanceMatrix", "The matrix which contains the distances between the points.")); 128 Parameters.Add(new FixedValueParameter<IntValue>("StartingPoint", "Index of the starting point.", new IntValue(0))); 129 Parameters.Add(new FixedValueParameter<IntValue>("TerminalPoint", "Index of the ending point.", new IntValue(0))); 130 Parameters.Add(new FixedValueParameter<DoubleValue>("MaximumDistance", "The maximum distance constraint for a Orienteering solution.")); 131 Parameters.Add(new ValueParameter<DoubleArray>("Scores", "The scores of the points.")); 132 Parameters.Add(new FixedValueParameter<DoubleValue>("PointVisitingCosts", "The costs for visiting a point.")); 133 Parameters.Add(new OptionalValueParameter<IntegerVector>("BestKnownSolution", "The best known solution of this Orienteering instance.")); 134 135 Maximization.Value = true; 136 MaximizationParameter.Hidden = true; 137 138 SolutionCreator.IntegerVectorParameter.ActualName = "OrienteeringSolution"; 139 140 InitializeInitialOrienteeringInstance(); 141 142 ParameterizeSolutionCreator(); 143 ParameterizeEvaluator(); 72 : base(new IntegerVectorEncoding("Route")) { 73 Parameters.Add(OrienteeringProblemDataParameter = new ValueParameter<IOrienteeringProblemData>("OP Data", "The main parameters for the orienteering problem.", new OrienteeringProblemData())); 74 Parameters.Add(BestKnownSolutionParameter = new OptionalValueParameter<OrienteeringSolution>("BestKnownSolution", "The best known solution of this Orienteering instance.")); 75 Parameters.Add(BestOrienteeringSolutionParameter = new ResultParameter<OrienteeringSolution>("Best Orienteering Solution", "The best so far solution found.")); 76 Maximization = true; 144 77 145 78 InitializeOperators(); 146 RegisterEventHandlers(); 147 } 148 149 #region Events 150 protected override void OnSolutionCreatorChanged() { 151 base.OnSolutionCreatorChanged(); 152 SolutionCreator.IntegerVectorParameter.ActualNameChanged += SolutionCreator_IntegerVectorParameter_ActualNameChanged; 153 ParameterizeSolutionCreator(); 154 ParameterizeEvaluator(); 155 ParameterizeAnalyzer(); 79 } 80 81 public override ISingleObjectiveEvaluationResult Evaluate(IntegerVector solution, IRandom random, CancellationToken cancellationToken) { 82 var data = OrienteeringProblemData; 83 var score = CalculateScore(data, solution); 84 var travelCosts = CalculateTravelCosts(data, solution); 85 var quality = CalculateQuality(data, score, travelCosts); 86 87 return new SingleObjectiveEvaluationResult(quality); 88 } 89 90 public static double CalculateQuality(IOrienteeringProblemData data, double score, double travelCosts) { 91 if (travelCosts > data.MaximumTravelCosts) return data.MaximumTravelCosts - travelCosts; // negative excessive distance 92 return score; 93 } 94 public static double CalculateScore(IOrienteeringProblemData data, IEnumerable<int> solution) { 95 return solution.Sum(t => data.GetScore(t)); 96 } 97 public static double CalculateTravelCosts(IOrienteeringProblemData data, IntegerVector solution) { 98 var distance = data.RoutingData.GetPathDistance(solution, closed: false); 99 distance += (solution.Length - 2) * data.PointVisitingCosts; 100 return distance; 101 } 102 public static double CalculateTravelCosts(IOrienteeringProblemData data, IList<int> solution) { 103 var distance = data.RoutingData.GetPathDistance(solution, closed: false); 104 distance += (solution.Count - 2) * data.PointVisitingCosts; 105 return distance; 106 } 107 108 public override void Analyze(IntegerVector[] vectors, double[] qualities, ResultCollection results, IRandom random) { 109 base.Analyze(vectors, qualities, results, random); 110 var data = OrienteeringProblemData; 111 112 var best = GetBestSolution(vectors, qualities); 113 var score = CalculateScore(OrienteeringProblemData, best.Item1); 114 var travelCosts = CalculateTravelCosts(OrienteeringProblemData, best.Item1); 115 var quality = CalculateQuality(OrienteeringProblemData, score, travelCosts); 116 117 if (BestKnownQuality == double.NaN || best.Item2 > BestKnownQuality) { 118 BestKnownQuality = best.Item2; 119 BestKnownSolutionParameter.ActualValue = data.GetSolution((IntegerVector)best.Item1.Clone(), quality, score, travelCosts); 120 } 121 122 var bestSoFar = BestOrienteeringSolutionParameter.ActualValue; 123 124 if (bestSoFar == null) { 125 bestSoFar = data.GetSolution((IntegerVector)best.Item1.Clone(), quality, score, travelCosts); 126 BestOrienteeringSolutionParameter.ActualValue = bestSoFar; 127 } else { 128 if (IsBetter(best.Item2, bestSoFar.Quality.Value)) { 129 bestSoFar.Route = (IntegerVector)best.Item1.Clone(); 130 bestSoFar.Quality.Value = quality; 131 bestSoFar.Score.Value = score; 132 bestSoFar.TravelCosts.Value = travelCosts; 133 } 134 } 135 } 136 public static double CalculateInsertionCosts(IOrienteeringProblemData data, IList<int> path, int insertPosition, int point) { 137 double detour = data.RoutingData.GetDistance(path[insertPosition - 1], point) + data.RoutingData.GetDistance(point, path[insertPosition]); 138 detour += data.PointVisitingCosts; 139 detour -= data.RoutingData.GetDistance(path[insertPosition - 1], path[insertPosition]); 140 return detour; 141 } 142 public static double CalculateReplacementCosts(IOrienteeringProblemData data, IList<int> path, int replacePosition, int point) { 143 double detour = data.RoutingData.GetDistance(path[replacePosition - 1], point) + data.RoutingData.GetDistance(point, path[replacePosition + 1]); 144 detour -= data.RoutingData.GetDistance(path[replacePosition - 1], path[replacePosition]) + data.RoutingData.GetDistance(path[replacePosition], path[replacePosition + 1]); 145 return detour; 146 } 147 public static double CalculateRemovementSaving(IOrienteeringProblemData data, IList<int> path, int removePosition) { 148 double saving = data.RoutingData.GetDistance(path[removePosition - 1], path[removePosition]); 149 saving += data.RoutingData.GetDistance(path[removePosition], path[removePosition + 1]); 150 saving -= data.RoutingData.GetDistance(path[removePosition - 1], path[removePosition + 1]); 151 saving += data.PointVisitingCosts; 152 return saving; 153 } 154 155 protected override void OnEncodingChanged() { 156 base.OnEncodingChanged(); 156 157 ParameterizeOperators(); 157 158 } 159 158 160 protected override void OnEvaluatorChanged() { 159 161 base.OnEvaluatorChanged(); 160 ParameterizeEvaluator();161 ParameterizeAnalyzer();162 }163 private void SolutionCreator_IntegerVectorParameter_ActualNameChanged(object sender, EventArgs e) {164 ParameterizeEvaluator();165 ParameterizeAnalyzer();166 162 ParameterizeOperators(); 167 163 } 168 private void CoordinatesParameter_ValueChanged(object sender, EventArgs e) { 169 if (Coordinates != null) { 170 Coordinates.ItemChanged += new EventHandler<EventArgs<int, int>>(CoordinatesValue_ItemChanged); 171 Coordinates.Reset += new EventHandler(CoordinatesValue_Reset); 172 } 173 ParameterizeSolutionCreator(); 174 UpdateDistanceMatrix(); 175 CheckStartingIndex(); 176 CheckTerminalIndex(); 177 } 178 private void CoordinatesValue_ItemChanged(object sender, EventArgs<int, int> e) { 179 UpdateDistanceMatrix(); 180 CheckStartingIndex(); 181 CheckTerminalIndex(); 182 } 183 private void CoordinatesValue_Reset(object sender, EventArgs e) { 184 ParameterizeSolutionCreator(); 185 UpdateDistanceMatrix(); 186 CheckStartingIndex(); 187 CheckTerminalIndex(); 188 } 189 private void StartingPointParameterValue_ValueChanged(object sender, EventArgs e) { 190 CheckStartingIndex(); 191 } 192 193 private void TerminalPointParameterValue_ValueChanged(object sender, EventArgs e) { 194 CheckTerminalIndex(); 195 } 196 private void MaximumDistanceParameterValue_ValueChanged(object sender, EventArgs e) { } 197 private void ScoresParameter_ValueChanged(object sender, EventArgs e) { 198 ParameterizeEvaluator(); 199 ParameterizeAnalyzer(); 200 ParameterizeSolutionCreator(); 201 202 ScoresParameter.Value.Reset += new EventHandler(ScoresValue_Reset); 203 } 204 private void ScoresValue_Reset(object sender, EventArgs e) { 205 ParameterizeSolutionCreator(); 206 } 207 private void PointVisitingCostsParameterValue_ValueChanged(object sender, EventArgs e) { } 208 209 private void BestKnownSolutionParameter_ValueChanged(object sender, EventArgs e) { 210 if (BestKnownSolution == null) 211 BestKnownQuality = null; 212 } 213 #endregion 214 215 #region Helpers 216 [StorableHook(HookType.AfterDeserialization)] 217 private void AfterDeserialization() { 218 RegisterEventHandlers(); 219 } 220 221 private void RegisterEventHandlers() { 222 SolutionCreator.IntegerVectorParameter.ActualNameChanged += SolutionCreator_IntegerVectorParameter_ActualNameChanged; 223 224 CoordinatesParameter.ValueChanged += CoordinatesParameter_ValueChanged; 225 if (CoordinatesParameter.Value != null) { 226 CoordinatesParameter.Value.ItemChanged += CoordinatesValue_ItemChanged; 227 CoordinatesParameter.Value.Reset += CoordinatesValue_Reset; 228 } 229 230 StartingPointParameter.Value.ValueChanged += StartingPointParameterValue_ValueChanged; 231 TerminalPointParameter.Value.ValueChanged += TerminalPointParameterValue_ValueChanged; 232 MaximumDistanceParameter.Value.ValueChanged += MaximumDistanceParameterValue_ValueChanged; 233 PointVisitingCostsParameter.Value.ValueChanged += PointVisitingCostsParameterValue_ValueChanged; 234 235 ScoresParameter.ValueChanged += ScoresParameter_ValueChanged; 236 ScoresParameter.Value.Reset += ScoresValue_Reset; 237 238 BestKnownSolutionParameter.ValueChanged += BestKnownSolutionParameter_ValueChanged; 239 } 240 241 private void ParameterizeSolutionCreator() { 242 SolutionCreator.DistanceMatrixParameter.ActualName = DistanceMatrixParameter.Name; 243 SolutionCreator.ScoresParameter.ActualName = ScoresParameter.Name; 244 SolutionCreator.MaximumDistanceParameter.ActualName = MaximumDistanceParameter.Name; 245 SolutionCreator.StartingPointParameter.ActualName = StartingPointParameter.Name; 246 SolutionCreator.TerminalPointParameter.ActualName = TerminalPointParameter.Name; 247 SolutionCreator.PointVisitingCostsParameter.ActualName = PointVisitingCostsParameter.Name; 248 } 249 private void ParameterizeEvaluator() { 250 Evaluator.IntegerVectorParameter.ActualName = SolutionCreator.IntegerVectorParameter.ActualName; 251 Evaluator.ScoresParameter.ActualName = ScoresParameter.Name; 252 Evaluator.DistanceMatrixParameter.ActualName = DistanceMatrixParameter.Name; 253 Evaluator.MaximumDistanceParameter.ActualName = MaximumDistanceParameter.Name; 254 Evaluator.PointVisitingCostsParameter.ActualName = PointVisitingCostsParameter.Name; 255 } 256 private void ParameterizeAnalyzer() { 257 if (BestOrienteeringSolutionAnalyser != null) { 258 BestOrienteeringSolutionAnalyser.QualityParameter.ActualName = Evaluator.QualityParameter.ActualName; 259 260 BestOrienteeringSolutionAnalyser.IntegerVector.ActualName = SolutionCreator.IntegerVectorParameter.ActualName; 261 BestOrienteeringSolutionAnalyser.CoordinatesParameter.ActualName = CoordinatesParameter.Name; 262 BestOrienteeringSolutionAnalyser.ScoresParameter.ActualName = ScoresParameter.Name; 263 264 BestOrienteeringSolutionAnalyser.ResultsParameter.ActualName = "Results"; 265 BestOrienteeringSolutionAnalyser.BestKnownQualityParameter.ActualName = BestKnownQualityParameter.Name; 266 BestOrienteeringSolutionAnalyser.BestKnownSolutionParameter.ActualName = BestKnownSolutionParameter.Name; 267 } 268 } 164 269 165 private void InitializeOperators() { 270 Operators.Add(new BestOrienteeringSolutionAnalyzer()); 271 ParameterizeAnalyzer(); 272 273 Operators.Add(new OrienteeringLocalImprovementOperator()); 274 Operators.Add(new OrienteeringShakingOperator()); 166 Encoding.SolutionCreator = new GreedyOrienteeringTourCreator() { 167 OrienteeringProblemDataParameter = { ActualName = OrienteeringProblemDataParameter.Name } 168 }; 169 170 Operators.Add(new OrienteeringLocalImprovementOperator() { 171 OrienteeringProblemDataParameter = { ActualName = OrienteeringProblemDataParameter.Name } 172 }); 173 Operators.Add(new OrienteeringShakingOperator() { 174 OrienteeringProblemDataParameter = { ActualName = OrienteeringProblemDataParameter.Name } 175 }); 275 176 Operators.Add(new QualitySimilarityCalculator()); 276 177 Operators.Add(new PopulationSimilarityAnalyzer(Operators.OfType<ISolutionSimilarityCalculator>())); … … 278 179 ParameterizeOperators(); 279 180 } 181 280 182 private void ParameterizeOperators() { 281 183 foreach (var op in Operators.OfType<OrienteeringLocalImprovementOperator>()) { 282 op.IntegerVectorParameter.ActualName = SolutionCreator.IntegerVectorParameter.ActualName; 283 op.DistanceMatrixParameter.ActualName = DistanceMatrixParameter.Name; 284 op.ScoresParameter.ActualName = ScoresParameter.Name; 285 op.MaximumDistanceParameter.ActualName = MaximumDistanceParameter.Name; 286 op.StartingPointParameter.ActualName = StartingPointParameter.Name; 287 op.TerminalPointParameter.ActualName = TerminalPointParameter.Name; 288 op.PointVisitingCostsParameter.ActualName = PointVisitingCostsParameter.Name; 184 op.IntegerVectorParameter.ActualName = Encoding.Name; 185 op.QualityParameter.ActualName = Evaluator.QualityParameter.ActualName; 289 186 } 290 187 foreach (var op in Operators.OfType<OrienteeringShakingOperator>()) { 291 op.IntegerVectorParameter.ActualName = SolutionCreator.IntegerVectorParameter.ActualName; 292 op.DistanceMatrixParameter.ActualName = DistanceMatrixParameter.Name; 293 op.ScoresParameter.ActualName = ScoresParameter.Name; 294 op.MaximumDistanceParameter.ActualName = MaximumDistanceParameter.Name; 295 op.StartingPointParameter.ActualName = StartingPointParameter.Name; 296 op.TerminalPointParameter.ActualName = TerminalPointParameter.Name; 297 op.PointVisitingCostsParameter.ActualName = PointVisitingCostsParameter.Name; 188 op.IntegerVectorParameter.ActualName = Encoding.Name; 298 189 } 299 190 foreach (var similarityCalculator in Operators.OfType<ISolutionSimilarityCalculator>()) { 300 similarityCalculator.SolutionVariableName = SolutionCreator.IntegerVectorParameter.ActualName;191 similarityCalculator.SolutionVariableName = Encoding.Name; 301 192 similarityCalculator.QualityVariableName = Evaluator.QualityParameter.ActualName; 302 193 } 303 }304 #endregion305 306 private DistanceMatrix CalculateDistanceMatrix(double[,] coordinates) {307 var distances = DistanceHelper.GetDistanceMatrix(DistanceMeasure.Euclidean, coordinates, null, coordinates.GetLength(0));308 309 return new DistanceMatrix(distances);310 }311 private void UpdateDistanceMatrix() {312 if (Coordinates == null) {313 DistanceMatrix = new DistanceMatrix(0, 0);314 return;315 }316 317 var coordinates = Coordinates;318 int dimension = coordinates.Rows;319 var distances = new double[dimension, dimension];320 for (int i = 0; i < dimension - 1; i++) {321 for (int j = i + 1; j < dimension; j++) {322 double x1 = coordinates[i, 0];323 double y1 = coordinates[i, 1];324 double x2 = coordinates[j, 0];325 double y2 = coordinates[j, 1];326 distances[i, j] = Math.Sqrt((x1 - x2) * (x1 - x2) + (y1 - y2) * (y1 - y2));327 distances[j, i] = distances[i, j];328 }329 }330 DistanceMatrix = new DistanceMatrix(distances);331 }332 private void CheckStartingIndex() {333 if (StartingPoint < 0) StartingPoint = 0;334 if (StartingPoint >= DistanceMatrix.Rows) StartingPoint = DistanceMatrix.Rows - 1;335 }336 private void CheckTerminalIndex() {337 if (TerminalPoint < 0) TerminalPoint = 0;338 if (TerminalPoint >= DistanceMatrix.Rows) TerminalPoint = DistanceMatrix.Rows - 1;339 }340 341 private void InitializeInitialOrienteeringInstance() {342 var coordinates = new double[21, 2] {343 { 4.60, 7.10 }, { 5.70, 11.40 }, { 4.40, 12.30 }, { 2.80, 14.30 }, { 3.20, 10.30 },344 { 3.50, 9.80 }, { 4.40, 8.40 }, { 7.80, 11.00 }, { 8.80, 9.80 }, { 7.70, 8.20 },345 { 6.30, 7.90 }, { 5.40, 8.20 }, { 5.80, 6.80 }, { 6.70, 5.80 }, { 13.80, 13.10 },346 { 14.10, 14.20 }, { 11.20, 13.60 }, { 9.70, 16.40 }, { 9.50, 18.80 }, { 4.70, 16.80 },347 { 5.00, 5.60 }348 };349 Coordinates = new DoubleMatrix(coordinates);350 DistanceMatrix = CalculateDistanceMatrix(coordinates);351 352 StartingPoint = 0;353 TerminalPoint = 20;354 MaximumDistance = 30;355 356 Scores = new DoubleArray(new double[21] { 0, 20, 20, 30, 15, 15, 10, 20, 20, 20, 15, 10, 10, 25, 40, 40, 30, 30, 50, 30, 0 });357 194 } 358 195 … … 370 207 Description = data.Description; 371 208 372 Coordinates = data.Coordinates != null ? new DoubleMatrix(data.Coordinates) : null; 373 if (data.Distances != null) 374 DistanceMatrix = new DistanceMatrix(data.Distances); 375 else 376 DistanceMatrix = new DistanceMatrix(data.GetDistanceMatrix()); 377 378 StartingPoint = data.StartingPoint; 379 TerminalPoint = data.TerminalPoint; 380 381 PointVisitingCosts = data.PointVisitingCosts; 382 MaximumDistance = data.MaximumDistance; 383 Scores = new DoubleArray(data.Scores); 209 var tsp = data.Coordinates != null ? (ITSPData)new EuclideanTSPData(Name, data.Coordinates) : new MatrixTSPData(Name, data.Distances ?? data.GetDistanceMatrix(), data.Coordinates); 210 OrienteeringProblemData = new OrienteeringProblemData(tsp, data.StartingPoint, data.TerminalPoint, data.Scores, data.MaximumDistance, data.PointVisitingCosts); 384 211 } 385 212 … … 396 223 Description = data.Description; 397 224 398 Coordinates = data.Coordinates != null ? new DoubleMatrix(data.Coordinates) : null; 399 if (data.Distances != null) 400 DistanceMatrix = new DistanceMatrix(data.Distances); 401 else 402 DistanceMatrix = new DistanceMatrix(data.GetDistanceMatrix()); 403 404 StartingPoint = 0; // First city is interpreted as start point 405 TerminalPoint = data.Dimension - 1; // Last city is interpreted als end point 406 407 PointVisitingCosts = 0; 408 MaximumDistance = DistanceMatrix.Average() * 5.0; // distance from start to end first to last city is interpreted as maximum distance 409 Scores = new DoubleArray(Enumerable.Repeat(1.0, data.Dimension).ToArray()); // all scores are 1 225 226 var tsp = data.Coordinates != null ? (ITSPData)new EuclideanTSPData(Name, data.Coordinates) : new MatrixTSPData(Name, data.Distances ?? data.GetDistanceMatrix(), data.Coordinates); 227 var avgDist = 0.0; 228 for (var i = 0; i < data.Dimension - 1; i++) 229 for (var j = i + 1; i < data.Dimension; j++) 230 avgDist += tsp.GetDistance(i, j); 231 avgDist /= (data.Dimension - 1) * data.Dimension / 2.0; 232 233 OrienteeringProblemData = new OrienteeringProblemData(tsp, 0, data.Dimension - 1, 234 Enumerable.Repeat(1.0, data.Dimension).ToArray(), 5 * avgDist, 0); 410 235 } 411 236 … … 422 247 Description = data.Description; 423 248 424 Coordinates = data.Coordinates != null ? new DoubleMatrix(data.Coordinates) : null; 425 DistanceMatrix = data.Distances != null 426 ? new DistanceMatrix(data.Distances) 427 : CalculateDistanceMatrix(data.Coordinates); 428 429 StartingPoint = 0; // Depot is interpreted as start point 430 TerminalPoint = 0; // Depot is interpreted als end point 431 432 PointVisitingCosts = 0; 433 MaximumDistance = data.Capacity * 2; // capacity is interpreted as max distance 434 Scores = new DoubleArray(data.Demands); // demands are interpreted as scores 249 var tsp = data.Coordinates != null ? (ITSPData)new EuclideanTSPData(Name, data.Coordinates) : new MatrixTSPData(Name, data.Distances ?? data.GetDistanceMatrix(), data.Coordinates); 250 251 OrienteeringProblemData = new OrienteeringProblemData(tsp, 0, 0, 252 data.Demands, data.Capacity * 2, 0); 435 253 } 436 254 #endregion -
branches/2521_ProblemRefactoring/HeuristicLab.Problems.Orienteering/3.3/OrienteeringSolution.cs
r17226 r17525 20 20 #endregion 21 21 22 using System ;22 using System.ComponentModel; 23 23 using System.Drawing; 24 using HEAL.Attic; 24 25 using HeuristicLab.Common; 25 26 using HeuristicLab.Core; 26 27 using HeuristicLab.Data; 27 28 using HeuristicLab.Encodings.IntegerVectorEncoding; 28 using HEAL.Attic; 29 using HeuristicLab.Encodings.PermutationEncoding; 30 using HeuristicLab.Problems.TravelingSalesman; 29 31 30 32 namespace HeuristicLab.Problems.Orienteering { 31 33 [Item("OrienteeringSolution", "Represents a Orienteering solution which can be visualized in the GUI.")] 32 34 [StorableType("BC58ED08-B9A7-40F3-B8E0-A6B33AA993F4")] 33 public sealed class OrienteeringSolution : Item {35 public sealed class OrienteeringSolution : Item, ITSPSolution { 34 36 public static new Image StaticItemImage { 35 37 get { return HeuristicLab.Common.Resources.VSImageLibrary.Image; } 36 38 } 37 39 38 [Storable] 39 private IntegerVector integerVector;40 public IntegerVector IntegerVector{41 get { return integerVector; }40 [Storable] private Permutation routeAsPermutation; 41 [Storable] private IntegerVector route; 42 public IntegerVector Route { 43 get { return route; } 42 44 set { 43 if (integerVector != value) { 44 if (integerVector != null) DeregisterIntegerVectorEvents(); 45 integerVector = value; 46 if (integerVector != null) RegisterIntegerVectorEvents(); 47 OnIntegerVectorChanged(); 48 } 45 if (route == value) return; 46 route = value; 47 routeAsPermutation = new Permutation(PermutationTypes.RelativeDirected, value); 48 OnPropertyChanged(nameof(Route)); 49 OnPropertyChanged(nameof(ITSPSolution.Tour)); 49 50 } 50 51 } 51 [Storable] 52 private DoubleMatrix coordinates; 53 public DoubleMatrix Coordinates { 54 get { return coordinates; } 52 [Storable] private IOrienteeringProblemData opData; 53 public IOrienteeringProblemData OPData { 54 get { return opData; } 55 55 set { 56 if (coordinates != value) { 57 if (coordinates != null) DeregisterCoordinatesEvents(); 58 coordinates = value; 59 if (coordinates != null) RegisterCoordinatesEvents(); 60 OnCoordinatesChanged(); 61 } 62 } 63 } 64 [Storable] 65 private IntValue startingPoint; 66 public IntValue StartingPoint { 67 get { return startingPoint; } 68 set { 69 if (startingPoint != value) { 70 if (startingPoint != null) DeregisterStartingPointEvents(); 71 startingPoint = value; 72 if (startingPoint != null) RegisterStartingPointEvents(); 73 OnStartingPointChanged(); 74 } 75 } 76 } 77 [Storable] 78 private IntValue terminalPoint; 79 public IntValue TerminalPoint { 80 get { return terminalPoint; } 81 set { 82 if (terminalPoint != value) { 83 if (terminalPoint != null) DeregisterTerminalPointEvents(); 84 terminalPoint = value; 85 if (terminalPoint != null) RegisterTerminalPointEvents(); 86 OnTerminalPointChanged(); 87 } 88 } 89 } 90 [Storable] 91 private DoubleArray scores; 92 public DoubleArray Scores { 93 get { return scores; } 94 set { 95 if (scores != value) { 96 if (scores != null) DeregisterScoresEvents(); 97 scores = value; 98 if (scores != null) RegisterScoresEvents(); 99 OnScoresChanged(); 100 } 56 if (opData == value) return; 57 opData = value; 58 OnPropertyChanged(nameof(OPData)); 59 OnPropertyChanged(nameof(ITSPSolution.TSPData)); 101 60 } 102 61 } … … 106 65 get { return quality; } 107 66 set { 108 if (quality != value) { 109 if (quality != null) DeregisterQualityEvents(); 110 quality = value; 111 if (quality != null) RegisterQualityEvents(); 112 OnQualityChanged(); 113 } 67 if (quality == value) return; 68 quality = value; 69 OnPropertyChanged(nameof(Quality)); 114 70 } 115 71 } 116 72 [Storable] 117 private DoubleValue penalty;118 public DoubleValue Penalty{119 get { return penalty; }73 private DoubleValue score; 74 public DoubleValue Score { 75 get { return score; } 120 76 set { 121 if (penalty != value) { 122 if (penalty != null) DeregisterPenaltyEvents(); 123 penalty = value; 124 if (penalty != null) RegisterPenaltyEvents(); 125 OnPenaltyChanged(); 126 } 77 if (score == value) return; 78 score = value; 79 OnPropertyChanged(nameof(Score)); 127 80 } 128 81 } 129 82 [Storable] 130 private DoubleValue distance;131 public DoubleValue Distance{132 get { return distance; }83 private DoubleValue travelCosts; 84 public DoubleValue TravelCosts { 85 get { return travelCosts; } 133 86 set { 134 if (distance != value) { 135 if (distance != null) DeregisterDistanceEvents(); 136 distance = value; 137 if (distance != null) RegisterDistanceEvents(); 138 OnDistanceChanged(); 139 } 87 if (travelCosts == value) return; 88 travelCosts = value; 89 OnPropertyChanged(nameof(TravelCosts)); 90 OnPropertyChanged(nameof(ITSPSolution.TourLength)); 140 91 } 141 92 } 93 94 ITSPData ITSPSolution.TSPData => OPData.RoutingData; 95 Permutation ITSPSolution.Tour => routeAsPermutation; 96 DoubleValue ITSPSolution.TourLength => TravelCosts; 142 97 143 98 [StorableConstructor] … … 145 100 private OrienteeringSolution(OrienteeringSolution original, Cloner cloner) 146 101 : base(original, cloner) { 147 this. integerVector = cloner.Clone(original.integerVector);148 this. coordinates = cloner.Clone(original.coordinates);102 this.route = cloner.Clone(original.route); 103 this.opData = cloner.Clone(original.opData); 149 104 this.quality = cloner.Clone(original.quality); 150 this.penalty = cloner.Clone(original.penalty); 151 Initialize(); 105 this.score = cloner.Clone(original.score); 152 106 } 153 public OrienteeringSolution(IntegerVector integerVector, DoubleMatrix coordinates, IntValue startingPoint, IntValue terminalPoint, 154 DoubleArray scores, DoubleValue quality = null, DoubleValue penalty = null, DoubleValue distance = null) 107 public OrienteeringSolution(IntegerVector route, IOrienteeringProblemData opData, double quality, double score, double travelCosts) 108 : this(route, opData, new DoubleValue(quality), new DoubleValue(score), new DoubleValue(travelCosts)) { } 109 public OrienteeringSolution(IntegerVector route, IOrienteeringProblemData opData, DoubleValue quality = null, DoubleValue score = null, DoubleValue distance = null) 155 110 : base() { 156 this.integerVector = integerVector; 157 this.coordinates = coordinates; 158 this.startingPoint = startingPoint; 159 this.terminalPoint = terminalPoint; 160 this.scores = scores; 111 this.route = route; 112 this.opData = opData; 161 113 this.quality = quality; 162 this.penalty = penalty; 163 this.distance = distance; 164 Initialize(); 114 this.score = score; 115 this.travelCosts = distance; 165 116 } 166 117 … … 169 120 } 170 121 171 [StorableHook(HookType.AfterDeserialization)]172 private void AfterDeserialization() {173 Initialize();122 public event PropertyChangedEventHandler PropertyChanged; 123 private void OnPropertyChanged(string property) { 124 PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(property)); 174 125 } 175 176 private void Initialize() {177 if (integerVector != null) RegisterIntegerVectorEvents();178 if (coordinates != null) RegisterCoordinatesEvents();179 if (startingPoint != null) RegisterStartingPointEvents();180 if (terminalPoint != null) RegisterTerminalPointEvents();181 if (scores != null) RegisterScoresEvents();182 if (quality != null) RegisterQualityEvents();183 if (penalty != null) RegisterPenaltyEvents();184 if (distance != null) RegisterDistanceEvents();185 }186 187 #region Events188 public event EventHandler IntegerVectorChanged;189 private void OnIntegerVectorChanged() {190 var changed = IntegerVectorChanged;191 if (changed != null)192 changed(this, EventArgs.Empty);193 }194 195 public event EventHandler CoordinatesChanged;196 private void OnCoordinatesChanged() {197 var changed = CoordinatesChanged;198 if (changed != null)199 changed(this, EventArgs.Empty);200 }201 202 public event EventHandler StartingPointChanged;203 private void OnStartingPointChanged() {204 var changed = StartingPointChanged;205 if (changed != null)206 changed(this, EventArgs.Empty);207 }208 209 public event EventHandler TerminalPointChanged;210 private void OnTerminalPointChanged() {211 var changed = TerminalPointChanged;212 if (changed != null)213 changed(this, EventArgs.Empty);214 }215 216 public event EventHandler ScoresChanged;217 private void OnScoresChanged() {218 var changed = ScoresChanged;219 if (changed != null)220 changed(this, EventArgs.Empty);221 }222 223 public event EventHandler QualityChanged;224 private void OnQualityChanged() {225 var changed = QualityChanged;226 if (changed != null)227 changed(this, EventArgs.Empty);228 }229 230 public event EventHandler PenaltyChanged;231 private void OnPenaltyChanged() {232 var changed = PenaltyChanged;233 if (changed != null)234 changed(this, EventArgs.Empty);235 }236 237 public event EventHandler DistanceChanged;238 private void OnDistanceChanged() {239 var changed = DistanceChanged;240 if (changed != null)241 changed(this, EventArgs.Empty);242 }243 244 private void RegisterIntegerVectorEvents() {245 IntegerVector.ItemChanged += new EventHandler<EventArgs<int>>(IntegerVector_ItemChanged);246 IntegerVector.Reset += new EventHandler(IntegerVector_Reset);247 }248 private void DeregisterIntegerVectorEvents() {249 IntegerVector.ItemChanged -= new EventHandler<EventArgs<int>>(IntegerVector_ItemChanged);250 IntegerVector.Reset -= new EventHandler(IntegerVector_Reset);251 }252 private void RegisterCoordinatesEvents() {253 Coordinates.ItemChanged += new EventHandler<EventArgs<int, int>>(Coordinates_ItemChanged);254 Coordinates.Reset += new EventHandler(Coordinates_Reset);255 }256 private void DeregisterCoordinatesEvents() {257 Coordinates.ItemChanged -= new EventHandler<EventArgs<int, int>>(Coordinates_ItemChanged);258 Coordinates.Reset -= new EventHandler(Coordinates_Reset);259 }260 private void RegisterStartingPointEvents() {261 StartingPoint.ValueChanged += new EventHandler(StartingPoint_ValueChanged);262 }263 private void DeregisterStartingPointEvents() {264 StartingPoint.ValueChanged -= new EventHandler(StartingPoint_ValueChanged);265 }266 private void RegisterTerminalPointEvents() {267 TerminalPoint.ValueChanged += new EventHandler(TerminalPoint_ValueChanged);268 }269 private void DeregisterTerminalPointEvents() {270 TerminalPoint.ValueChanged -= new EventHandler(TerminalPoint_ValueChanged);271 }272 private void RegisterScoresEvents() {273 Scores.ItemChanged += new EventHandler<EventArgs<int>>(Scores_ItemChanged);274 Scores.Reset += new EventHandler(Scores_Reset);275 }276 private void DeregisterScoresEvents() {277 Scores.ItemChanged -= new EventHandler<EventArgs<int>>(Scores_ItemChanged);278 Scores.Reset -= new EventHandler(Scores_Reset);279 }280 private void RegisterQualityEvents() {281 Quality.ValueChanged += new EventHandler(Quality_ValueChanged);282 }283 private void DeregisterQualityEvents() {284 Quality.ValueChanged -= new EventHandler(Quality_ValueChanged);285 }286 private void RegisterPenaltyEvents() {287 Penalty.ValueChanged += new EventHandler(Penalty_ValueChanged);288 }289 private void DeregisterPenaltyEvents() {290 Penalty.ValueChanged -= new EventHandler(Penalty_ValueChanged);291 }292 private void RegisterDistanceEvents() {293 Distance.ValueChanged += new EventHandler(Distance_ValueChanged);294 }295 private void DeregisterDistanceEvents() {296 Distance.ValueChanged -= new EventHandler(Distance_ValueChanged);297 }298 299 private void IntegerVector_ItemChanged(object sender, EventArgs<int> e) {300 OnIntegerVectorChanged();301 }302 private void IntegerVector_Reset(object sender, EventArgs e) {303 OnIntegerVectorChanged();304 }305 private void Coordinates_ItemChanged(object sender, EventArgs<int, int> e) {306 OnCoordinatesChanged();307 }308 private void Coordinates_Reset(object sender, EventArgs e) {309 OnCoordinatesChanged();310 }311 private void StartingPoint_ValueChanged(object sender, EventArgs e) {312 OnStartingPointChanged();313 }314 private void TerminalPoint_ValueChanged(object sender, EventArgs e) {315 OnTerminalPointChanged();316 }317 private void Scores_ItemChanged(object sender, EventArgs<int> e) {318 OnCoordinatesChanged();319 }320 private void Scores_Reset(object sender, EventArgs e) {321 OnCoordinatesChanged();322 }323 private void Quality_ValueChanged(object sender, EventArgs e) {324 OnQualityChanged();325 }326 private void Penalty_ValueChanged(object sender, EventArgs e) {327 OnPenaltyChanged();328 }329 private void Distance_ValueChanged(object sender, EventArgs e) {330 OnDistanceChanged();331 }332 #endregion333 126 } 334 127 } -
branches/2521_ProblemRefactoring/HeuristicLab.Problems.Orienteering/3.3/Shakers/OrienteeringShakingOperator.cs
r17226 r17525 22 22 using System.Collections.Generic; 23 23 using System.Linq; 24 using HEAL.Attic; 24 25 using HeuristicLab.Common; 25 26 using HeuristicLab.Core; … … 29 30 using HeuristicLab.Optimization; 30 31 using HeuristicLab.Parameters; 31 using HEAL.Attic;32 32 33 33 namespace HeuristicLab.Problems.Orienteering { … … 64 64 get { return (ILookupParameter<IntegerVector>)Parameters["IntegerVector"]; } 65 65 } 66 public ILookupParameter<DoubleValue> MaximumDistanceParameter { 67 get { return (ILookupParameter<DoubleValue>)Parameters["MaximumDistance"]; } 68 } 69 public ILookupParameter<IntValue> StartingPointParameter { 70 get { return (ILookupParameter<IntValue>)Parameters["StartingPoint"]; } 71 } 72 public ILookupParameter<IntValue> TerminalPointParameter { 73 get { return (ILookupParameter<IntValue>)Parameters["TerminalPoint"]; } 74 } 75 public ILookupParameter<DistanceMatrix> DistanceMatrixParameter { 76 get { return (ILookupParameter<DistanceMatrix>)Parameters["DistanceMatrix"]; } 77 } 78 public ILookupParameter<DoubleArray> ScoresParameter { 79 get { return (ILookupParameter<DoubleArray>)Parameters["Scores"]; } 80 } 81 public ILookupParameter<DoubleValue> PointVisitingCostsParameter { 82 get { return (ILookupParameter<DoubleValue>)Parameters["PointVisitingCosts"]; } 66 public ILookupParameter<IOrienteeringProblemData> OrienteeringProblemDataParameter { 67 get { return (ILookupParameter<IOrienteeringProblemData>)Parameters["OrienteeringProblemData"]; } 83 68 } 84 69 … … 99 84 100 85 Parameters.Add(new LookupParameter<IntegerVector>("IntegerVector", "The Orienteering Solution given in path representation.")); 101 Parameters.Add(new LookupParameter<DoubleValue>("MaximumDistance", "The maximum distance constraint for a Orienteering solution.")); 102 Parameters.Add(new LookupParameter<IntValue>("StartingPoint", "Index of the starting point.")); 103 Parameters.Add(new LookupParameter<IntValue>("TerminalPoint", "Index of the ending point.")); 104 Parameters.Add(new LookupParameter<DistanceMatrix>("DistanceMatrix", "The matrix which contains the distances between the points.")); 105 Parameters.Add(new LookupParameter<DoubleArray>("Scores", "The scores of the points.")); 106 Parameters.Add(new LookupParameter<DoubleValue>("PointVisitingCosts", "The costs for visiting a point.")); 86 Parameters.Add(new LookupParameter<IOrienteeringProblemData>("OrienteeringProblemData", "The main data that comprises the orienteering problem.")); 107 87 108 88 Parameters.Add(new LookupParameter<IRandom>("Random", "The random number generator that will be used.")); … … 115 95 public override IOperation Apply() { 116 96 var initialTour = IntegerVectorParameter.ActualValue; 117 var distances = DistanceMatrixParameter.ActualValue; 118 var scores = ScoresParameter.ActualValue; 119 var startingPoint = StartingPointParameter.ActualValue.Value; 120 var terminalPoint = TerminalPointParameter.ActualValue.Value; 121 var pointVisitingCosts = PointVisitingCostsParameter.ActualValue.Value; 122 double maxDistance = MaximumDistanceParameter.ActualValue.Value; 123 int numPoints = scores.Length; 97 var data = OrienteeringProblemDataParameter.ActualValue; 98 int numPoints = data.RoutingData.Cities; 124 99 125 100 if (NeighborhoodCountParameter.ActualValue == null) … … 142 117 from point in Enumerable.Range(0, numPoints) 143 118 // Calculate the distance when going from the starting point to this point and then to the end point 144 let distance = d istances[startingPoint, point] + distances[point, terminalPoint] + pointVisitingCosts119 let distance = data.RoutingData.GetDistance(data.StartingPoint, point) + data.RoutingData.GetDistance(point, data.TerminalPoint) + data.PointVisitingCosts 145 120 // If this distance is feasible and the point is neither starting nor ending point, check the point 146 where distance < maxDistance && point != startingPoint && point != terminalPoint121 where distance < data.MaximumTravelCosts && point != data.StartingPoint && point != data.TerminalPoint 147 122 // The point was not yet visited, so add it to the candidate list 148 123 where !initialTour.Contains(point) 149 124 // Calculate the utility of the point at this position 150 let utility = scores[point]125 let utility = data.GetScore(point) 151 126 orderby utility 152 127 select point … … 154 129 155 130 // Initialize the new tour 156 var actualTour = new List<int> { startingPoint };131 var actualTour = new List<int> { data.StartingPoint }; 157 132 158 133 // Perform the insertions according to the utility sorting … … 160 135 161 136 // Bring the tour back to be feasible 162 CleanupTour(actualTour, d istances, maxDistance, pointVisitingCosts);137 CleanupTour(actualTour, data); 163 138 164 139 // Set new Tour … … 213 188 } 214 189 215 private void CleanupTour(List<int> actualTour, DistanceMatrix distances, double maxDistance, double pointVisitingCosts) {190 private void CleanupTour(List<int> actualTour, IOrienteeringProblemData data) { 216 191 // Sort the points on the tour according to their costs savings when removed 217 192 var distanceSavings = ( 218 193 from removePosition in Enumerable.Range(1, actualTour.Count - 2) 219 let saving = distances.CalculateRemovementSaving(actualTour, removePosition, pointVisitingCosts)194 let saving = OrienteeringProblem.CalculateRemovementSaving(data, actualTour, removePosition) 220 195 orderby saving descending 221 196 select new SavingInfo { Index = removePosition, Saving = saving } 222 197 ).ToList(); 223 198 224 double tourLength = distances.CalculateTourLength(actualTour, pointVisitingCosts);199 double tourLength = OrienteeringProblem.CalculateTravelCosts(data, actualTour); 225 200 226 201 // As long as the created path is infeasible, remove elements 227 while (tourLength > maxDistance) {202 while (tourLength > data.MaximumTravelCosts) { 228 203 // Remove the point that frees the largest distance 229 204 // Note, distance savings are not updated after removal 230 tourLength -= distances.CalculateRemovementSaving(actualTour, distanceSavings[0].Index, pointVisitingCosts);205 tourLength -= OrienteeringProblem.CalculateRemovementSaving(data, actualTour, distanceSavings[0].Index); 231 206 actualTour.RemoveAt(distanceSavings[0].Index); 232 207
Note: See TracChangeset
for help on using the changeset viewer.