Free cookie consent management tool by TermsFeed Policy Generator

Ignore:
Timestamp:
05/07/20 17:41:18 (5 years ago)
Author:
abeham
Message:

#2521: working on porting orienteering problem
Open points include:

  • Visualization of OrienteeringProblemData
  • Fix visualization of solution
  • Cleanup unused classes
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  
    2222using System.Collections.Generic;
    2323using System.Linq;
     24using HEAL.Attic;
    2425using HeuristicLab.Common;
    2526using HeuristicLab.Core;
     
    2728using HeuristicLab.Encodings.IntegerVectorEncoding;
    2829using HeuristicLab.Parameters;
    29 using HEAL.Attic;
    3030
    3131namespace HeuristicLab.Problems.Orienteering {
     
    4343    public override bool CanChangeName { get { return false; } }
    4444
    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"]; }
    4847    }
    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     #endregion
    6548
    6649    [StorableConstructor]
     
    7154    public GreedyOrienteeringTourCreator()
    7255      : 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."));
    7957    }
    8058
     
    8462
    8563    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;
    9365
    9466      // Find all points within the maximum distance allowed (ellipse)
    9567      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
    10174        orderby score descending
    10275        select point
     
    10578      // Add the starting and terminus point
    10679      var tour = new List<int> {
    107         startPoint,
    108         endPoint
     80        data.StartingPoint,
     81        data.TerminalPoint
    10982      };
    110       double tourLength = distances[startPoint, endPoint];
     83      double tourLength = data.RoutingData.GetDistance(data.StartingPoint, data.TerminalPoint);
    11184
    11285      // Add points in a greedy way
     
    11891          for (int insertPosition = 1; insertPosition < tour.Count; insertPosition++) {
    11992            // Create the candidate tour
    120             double detour = distances.CalculateInsertionCosts(tour, insertPosition, feasiblePoints[i], pointVisitingCosts);
     93            double detour = OrienteeringProblem.CalculateInsertionCosts(data, tour, insertPosition, feasiblePoints[i]);
    12194
    12295            // If the insertion would be feasible, perform it
    123             if (tourLength + detour <= maxDistance) {
     96            if (tourLength + detour <= data.MaximumTravelCosts) {
    12497              tour.Insert(insertPosition, feasiblePoints[i]);
    12598              tourLength += detour;
  • branches/2521_ProblemRefactoring/HeuristicLab.Problems.Orienteering/3.3/DistanceMatrix.cs

    r17226 r17525  
    2222using System;
    2323using System.Collections.Generic;
     24using HEAL.Attic;
    2425using HeuristicLab.Common;
    2526using HeuristicLab.Core;
    2627using HeuristicLab.Data;
    27 using HEAL.Attic;
    2828
    2929namespace HeuristicLab.Problems.Orienteering {
     
    6767      return detour;
    6868    }
    69     public double CalculateReplacementCosts(List<int> path, int replacePosition, int point) {
     69    public double CalculateReplacementCosts(IList<int> path, int replacePosition, int point) {
    7070      double detour = this[path[replacePosition - 1], point] + this[point, path[replacePosition + 1]];
    7171      detour -= this[path[replacePosition - 1], path[replacePosition]] + this[path[replacePosition], path[replacePosition + 1]];
    7272      return detour;
    7373    }
    74     public double CalculateRemovementSaving(List<int> path, int removePosition, double pointVisitingCosts) {
     74    public double CalculateRemovementSaving(IList<int> path, int removePosition, double pointVisitingCosts) {
    7575      double saving = this[path[removePosition - 1], path[removePosition]];
    7676      saving += this[path[removePosition], path[removePosition + 1]];
  • branches/2521_ProblemRefactoring/HeuristicLab.Problems.Orienteering/3.3/HeuristicLab.Problems.Orienteering-3.3.csproj

    r16723 r17525  
    8989  </ItemGroup>
    9090  <ItemGroup>
    91     <Compile Include="Analyzers\BestOrienteeringSolutionAnalyzer.cs" />
    9291    <Compile Include="Creators\GreedyOrienteeringTourCreator.cs" />
    9392    <Compile Include="DistanceMatrix.cs" />
    94     <Compile Include="OrienteeringEvaluationResult.cs" />
    9593    <Compile Include="Improvers\OrienteeringLocalImprovementOperator.cs" />
    96     <Compile Include="Interfaces\IOrienteeringEvaluator.cs" />
    97     <Compile Include="Evaluators\OrienteeringEvaluator.cs" />
    9894    <Compile Include="Interfaces\IOrienteeringSolutionCreator.cs" />
     95    <Compile Include="OrienteeringProblemData.cs" />
    9996    <Compile Include="OrienteeringProblem.cs" />
    10097    <Compile Include="OrienteeringSolution.cs" />
     
    144141      <Private>False</Private>
    145142    </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>
    146148    <ProjectReference Include="..\..\HeuristicLab.Operators\3.3\HeuristicLab.Operators-3.3.csproj">
    147149      <Project>{23DA7FF4-D5B8-41B6-AA96-F0561D24F3EE}</Project>
     
    179181      <Private>False</Private>
    180182    </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>
    181188    <ProjectReference Include="..\..\HeuristicLab.Random\3.3\HeuristicLab.Random-3.3.csproj">
    182189      <Project>{F4539FB6-4708-40C9-BE64-0A1390AEA197}</Project>
     
    197204    </Reference>
    198205  </ItemGroup>
     206  <ItemGroup />
    199207  <Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
    200208  <PropertyGroup>
  • branches/2521_ProblemRefactoring/HeuristicLab.Problems.Orienteering/3.3/Improvers/OrienteeringLocalImprovementOperator.cs

    r17226 r17525  
    2222using System.Collections.Generic;
    2323using System.Linq;
     24using HEAL.Attic;
    2425using HeuristicLab.Common;
    2526using HeuristicLab.Core;
     
    2930using HeuristicLab.Optimization;
    3031using HeuristicLab.Parameters;
    31 using HEAL.Attic;
    3232
    3333namespace HeuristicLab.Problems.Orienteering {
     
    4545      get { return (ILookupParameter<IntegerVector>)Parameters["OrienteeringSolution"]; }
    4646    }
    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
    6551    #region ILocalImprovementOperator Parameters
    6652    public IValueLookupParameter<IntValue> LocalIterationsParameter {
     
    9682      : base() {
    9783      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."));
    10485
    10586      Parameters.Add(new ValueLookupParameter<IntValue>("LocalIterations", "The number of iterations that have already been performed.", new IntValue(0)));
     
    11899
    119100    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;
    125102      int maxIterations = MaximumIterationsParameter.ActualValue.Value;
    126103      int maxBlockLength = MaximumBlockLengthParmeter.Value.Value;
     
    132109
    133110      double tourLength = 0;
    134       double tourScore = tour.Sum(point => scores[point]);
     111      double tourScore = tour.Sum(point => data.GetScore(point));
    135112
    136113      var localIterations = LocalIterationsParameter.ActualValue;
     
    143120
    144121        if (localIterations.Value == 0)
    145           tourLength = distances.CalculateTourLength(tour, pointVisitingCosts);
     122          tourLength = OrienteeringProblem.CalculateTravelCosts(data, tour);
    146123
    147124        // Try to shorten the path
    148         ShortenPath(tour, distances, maxBlockLength, useMaxBlockLength, ref tourLength, ref evaluations);
     125        ShortenPath(tour, data, maxBlockLength, useMaxBlockLength, ref tourLength, ref evaluations);
    149126
    150127        // 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();
    152129
    153130        // 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);
    157132
    158133        // 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);
    162135
    163136        localIterations.Value++;
     
    174147    }
    175148
    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) {
    177150      bool solutionChanged;
    178151      int pathSize = tour.Count;
     
    195168            double newLength = tourLength;
    196169            // Recalculate length of whole swapped part, in case distances are not symmetric
    197             for (int index = position - 1; index < position + blockLength; index++) newLength -= distances[tour[index], tour[index + 1]];
    198             for (int index = position + blockLength - 1; index > position; index--) newLength += distances[tour[index], tour[index - 1]];
    199             newLength += distances[tour[position - 1], tour[position + blockLength - 1]];
    200             newLength += distances[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]);
    201174
    202175            if (newLength < tourLength - 0.00001) {
     
    217190    }
    218191
    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,
    221193      ref double tourLength, ref double tourScore, ref int evaluations, ref bool solutionChanged) {
    222194
     
    231203          evaluations++;
    232204
    233           double detour = distances.CalculateInsertionCosts(tour, tourPosition, visitablePoints[i], pointVisitingCosts);
     205          double detour = OrienteeringProblem.CalculateInsertionCosts(data, tour, tourPosition, visitablePoints[i]);
    234206
    235207          // Determine if including the point does not violate any constraint
    236           if (tourLength + detour <= maxLength) {
     208          if (tourLength + detour <= data.MaximumTravelCosts) {
    237209            // Insert the new point at this position
    238210            tour.Insert(tourPosition, visitablePoints[i]);
     
    240212            // Update the overall tour tourLength and score
    241213            tourLength += detour;
    242             tourScore += scores[visitablePoints[i]];
     214            tourScore += data.GetScore(visitablePoints[i]);
    243215
    244216            // Re-run this optimization
     
    249221    }
    250222
    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,
    253224      ref double tourLength, ref double tourScore, ref int evaluations, ref bool solutionChanged) {
    254225
     
    263234          evaluations++;
    264235
    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)) {
    271242            // Replace the old point by the new one
    272243            tour[tourPosition] = visitablePoints[i];
  • branches/2521_ProblemRefactoring/HeuristicLab.Problems.Orienteering/3.3/Interfaces/IOrienteeringSolutionCreator.cs

    r17226 r17525  
    2020#endregion
    2121
     22using HEAL.Attic;
    2223using HeuristicLab.Core;
    23 using HeuristicLab.Data;
    2424using HeuristicLab.Encodings.IntegerVectorEncoding;
    25 using HEAL.Attic;
    2625
    2726namespace HeuristicLab.Problems.Orienteering {
    2827  [StorableType("7E0D4527-4D8C-4FBA-BB3A-26F20B6463ED")]
    2928  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; }
    3630  }
    3731}
  • branches/2521_ProblemRefactoring/HeuristicLab.Problems.Orienteering/3.3/OrienteeringProblem.cs

    r17226 r17525  
    2020#endregion
    2121
    22 using System;
     22using System.Collections.Generic;
    2323using System.IO;
    2424using System.Linq;
     25using System.Threading;
     26using HEAL.Attic;
    2527using HeuristicLab.Analysis;
    2628using HeuristicLab.Common;
    2729using HeuristicLab.Core;
    28 using HeuristicLab.Data;
    2930using HeuristicLab.Encodings.IntegerVectorEncoding;
    3031using HeuristicLab.Optimization;
    3132using HeuristicLab.Optimization.Operators;
    3233using HeuristicLab.Parameters;
    33 using HEAL.Attic;
    3434using HeuristicLab.Problems.Instances;
    3535using HeuristicLab.Problems.Instances.Types;
     36using HeuristicLab.Problems.TravelingSalesman;
    3637
    3738namespace HeuristicLab.Problems.Orienteering {
     
    3940  [Creatable(CreatableAttribute.Categories.CombinatorialProblems, Priority = 115)]
    4041  [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 {
    10655      get { return BestKnownSolutionParameter.Value; }
    10756      set { BestKnownSolutionParameter.Value = value; }
    10857    }
    109     private BestOrienteeringSolutionAnalyzer BestOrienteeringSolutionAnalyser {
    110       get { return Operators.OfType<BestOrienteeringSolutionAnalyzer>().SingleOrDefault(); }
    111     }
    112     #endregion
    11358
    11459    [StorableConstructor]
     
    11762    private OrienteeringProblem(OrienteeringProblem original, Cloner cloner)
    11863      : base(original, cloner) {
    119       RegisterEventHandlers();
     64      OrienteeringProblemDataParameter = cloner.Clone(original.OrienteeringProblemDataParameter);
     65      BestKnownSolutionParameter = cloner.Clone(original.BestKnownSolutionParameter);
     66      BestOrienteeringSolutionParameter = cloner.Clone(original.BestOrienteeringSolutionParameter);
    12067    }
    12168    public override IDeepCloneable Clone(Cloner cloner) {
     
    12370    }
    12471    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;
    14477
    14578      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();
    156157      ParameterizeOperators();
    157158    }
     159
    158160    protected override void OnEvaluatorChanged() {
    159161      base.OnEvaluatorChanged();
    160       ParameterizeEvaluator();
    161       ParameterizeAnalyzer();
    162     }
    163     private void SolutionCreator_IntegerVectorParameter_ActualNameChanged(object sender, EventArgs e) {
    164       ParameterizeEvaluator();
    165       ParameterizeAnalyzer();
    166162      ParameterizeOperators();
    167163    }
    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
    269165    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      });
    275176      Operators.Add(new QualitySimilarityCalculator());
    276177      Operators.Add(new PopulationSimilarityAnalyzer(Operators.OfType<ISolutionSimilarityCalculator>()));
     
    278179      ParameterizeOperators();
    279180    }
     181
    280182    private void ParameterizeOperators() {
    281183      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;
    289186      }
    290187      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;
    298189      }
    299190      foreach (var similarityCalculator in Operators.OfType<ISolutionSimilarityCalculator>()) {
    300         similarityCalculator.SolutionVariableName = SolutionCreator.IntegerVectorParameter.ActualName;
     191        similarityCalculator.SolutionVariableName = Encoding.Name;
    301192        similarityCalculator.QualityVariableName = Evaluator.QualityParameter.ActualName;
    302193      }
    303     }
    304     #endregion
    305 
    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 });
    357194    }
    358195
     
    370207      Description = data.Description;
    371208
    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);
    384211    }
    385212
     
    396223      Description = data.Description;
    397224
    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);
    410235    }
    411236
     
    422247      Description = data.Description;
    423248
    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);
    435253    }
    436254    #endregion
  • branches/2521_ProblemRefactoring/HeuristicLab.Problems.Orienteering/3.3/OrienteeringSolution.cs

    r17226 r17525  
    2020#endregion
    2121
    22 using System;
     22using System.ComponentModel;
    2323using System.Drawing;
     24using HEAL.Attic;
    2425using HeuristicLab.Common;
    2526using HeuristicLab.Core;
    2627using HeuristicLab.Data;
    2728using HeuristicLab.Encodings.IntegerVectorEncoding;
    28 using HEAL.Attic;
     29using HeuristicLab.Encodings.PermutationEncoding;
     30using HeuristicLab.Problems.TravelingSalesman;
    2931
    3032namespace HeuristicLab.Problems.Orienteering {
    3133  [Item("OrienteeringSolution", "Represents a Orienteering solution which can be visualized in the GUI.")]
    3234  [StorableType("BC58ED08-B9A7-40F3-B8E0-A6B33AA993F4")]
    33   public sealed class OrienteeringSolution : Item {
     35  public sealed class OrienteeringSolution : Item, ITSPSolution {
    3436    public static new Image StaticItemImage {
    3537      get { return HeuristicLab.Common.Resources.VSImageLibrary.Image; }
    3638    }
    3739
    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; }
    4244      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));
    4950      }
    5051    }
    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; }
    5555      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));
    10160      }
    10261    }
     
    10665      get { return quality; }
    10766      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));
    11470      }
    11571    }
    11672    [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; }
    12076      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));
    12780      }
    12881    }
    12982    [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; }
    13386      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));
    14091      }
    14192    }
     93
     94    ITSPData ITSPSolution.TSPData => OPData.RoutingData;
     95    Permutation ITSPSolution.Tour => routeAsPermutation;
     96    DoubleValue ITSPSolution.TourLength => TravelCosts;
    14297
    14398    [StorableConstructor]
     
    145100    private OrienteeringSolution(OrienteeringSolution original, Cloner cloner)
    146101      : 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);
    149104      this.quality = cloner.Clone(original.quality);
    150       this.penalty = cloner.Clone(original.penalty);
    151       Initialize();
     105      this.score = cloner.Clone(original.score);
    152106    }
    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)
    155110      : 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;
    161113      this.quality = quality;
    162       this.penalty = penalty;
    163       this.distance = distance;
    164       Initialize();
     114      this.score = score;
     115      this.travelCosts = distance;
    165116    }
    166117
     
    169120    }
    170121
    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));
    174125    }
    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 Events
    188     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     #endregion
    333126  }
    334127}
  • branches/2521_ProblemRefactoring/HeuristicLab.Problems.Orienteering/3.3/Shakers/OrienteeringShakingOperator.cs

    r17226 r17525  
    2222using System.Collections.Generic;
    2323using System.Linq;
     24using HEAL.Attic;
    2425using HeuristicLab.Common;
    2526using HeuristicLab.Core;
     
    2930using HeuristicLab.Optimization;
    3031using HeuristicLab.Parameters;
    31 using HEAL.Attic;
    3232
    3333namespace HeuristicLab.Problems.Orienteering {
     
    6464      get { return (ILookupParameter<IntegerVector>)Parameters["IntegerVector"]; }
    6565    }
    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"]; }
    8368    }
    8469
     
    9984
    10085      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."));
    10787
    10888      Parameters.Add(new LookupParameter<IRandom>("Random", "The random number generator that will be used."));
     
    11595    public override IOperation Apply() {
    11696      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;
    12499
    125100      if (NeighborhoodCountParameter.ActualValue == null)
     
    142117          from point in Enumerable.Range(0, numPoints)
    143118          // Calculate the distance when going from the starting point to this point and then to the end point
    144           let distance = distances[startingPoint, point] + distances[point, terminalPoint] + pointVisitingCosts
     119          let distance = data.RoutingData.GetDistance(data.StartingPoint, point) + data.RoutingData.GetDistance(point, data.TerminalPoint) + data.PointVisitingCosts
    145120          // If this distance is feasible and the point is neither starting nor ending point, check the point
    146           where distance < maxDistance && point != startingPoint && point != terminalPoint
     121          where distance < data.MaximumTravelCosts && point != data.StartingPoint && point != data.TerminalPoint
    147122          // The point was not yet visited, so add it to the candidate list
    148123          where !initialTour.Contains(point)
    149124          // Calculate the utility of the point at this position
    150           let utility = scores[point]
     125          let utility = data.GetScore(point)
    151126          orderby utility
    152127          select point
     
    154129
    155130        // Initialize the new tour
    156         var actualTour = new List<int> { startingPoint };
     131        var actualTour = new List<int> { data.StartingPoint };
    157132
    158133        // Perform the insertions according to the utility sorting
     
    160135
    161136        // Bring the tour back to be feasible
    162         CleanupTour(actualTour, distances, maxDistance, pointVisitingCosts);
     137        CleanupTour(actualTour, data);
    163138
    164139        // Set new Tour
     
    213188    }
    214189
    215     private void CleanupTour(List<int> actualTour, DistanceMatrix distances, double maxDistance, double pointVisitingCosts) {
     190    private void CleanupTour(List<int> actualTour, IOrienteeringProblemData data) {
    216191      // Sort the points on the tour according to their costs savings when removed
    217192      var distanceSavings = (
    218193        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)
    220195        orderby saving descending
    221196        select new SavingInfo { Index = removePosition, Saving = saving }
    222197      ).ToList();
    223198
    224       double tourLength = distances.CalculateTourLength(actualTour, pointVisitingCosts);
     199      double tourLength = OrienteeringProblem.CalculateTravelCosts(data, actualTour);
    225200
    226201      // As long as the created path is infeasible, remove elements
    227       while (tourLength > maxDistance) {
     202      while (tourLength > data.MaximumTravelCosts) {
    228203        // Remove the point that frees the largest distance
    229204        // 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);
    231206        actualTour.RemoveAt(distanceSavings[0].Index);
    232207
Note: See TracChangeset for help on using the changeset viewer.