Free cookie consent management tool by TermsFeed Policy Generator

source: branches/2521_ProblemRefactoring/HeuristicLab.Problems.Orienteering/3.3/OrienteeringProblem.cs @ 17612

Last change on this file since 17612 was 17612, checked in by mkommend, 4 years ago

#2521: Added first version of problem results.

File size: 12.3 KB
Line 
1#region License Information
2/* HeuristicLab
3 * Copyright (C) Heuristic and Evolutionary Algorithms Laboratory (HEAL)
4 *
5 * This file is part of HeuristicLab.
6 *
7 * HeuristicLab is free software: you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation, either version 3 of the License, or
10 * (at your option) any later version.
11 *
12 * HeuristicLab is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15 * GNU General Public License for more details.
16 *
17 * You should have received a copy of the GNU General Public License
18 * along with HeuristicLab. If not, see <http://www.gnu.org/licenses/>.
19 */
20#endregion
21
22using System;
23using System.Collections.Generic;
24using System.IO;
25using System.Linq;
26using System.Threading;
27using HEAL.Attic;
28using HeuristicLab.Analysis;
29using HeuristicLab.Common;
30using HeuristicLab.Core;
31using HeuristicLab.Encodings.IntegerVectorEncoding;
32using HeuristicLab.Optimization;
33using HeuristicLab.Optimization.Operators;
34using HeuristicLab.Parameters;
35using HeuristicLab.Problems.Instances;
36using HeuristicLab.Problems.Instances.Types;
37using HeuristicLab.Problems.TravelingSalesman;
38
39namespace HeuristicLab.Problems.Orienteering {
40  [Item("Orienteering Problem (OP)", "Represents a single-objective Orienteering Problem.")]
41  [Creatable(CreatableAttribute.Categories.CombinatorialProblems, Priority = 115)]
42  [StorableType("0B8DB4A4-F183-4368-86C6-C51289B183D2")]
43  public sealed class OrienteeringProblem : IntegerVectorProblem,
44      IProblemInstanceConsumer<OPData>, IProblemInstanceConsumer<TSPData>, IProblemInstanceConsumer<CVRPData> {
45
46    [Storable] public ValueParameter<IOrienteeringProblemData> OrienteeringProblemDataParameter { get; private set; }
47    [Storable] public OptionalValueParameter<OrienteeringSolution> BestKnownSolutionParameter { get; private set; }
48    [Storable] private IResultParameter<OrienteeringSolution> BestOrienteeringSolutionParameter { get; set; }
49
50    public IOrienteeringProblemData OrienteeringProblemData {
51      get { return OrienteeringProblemDataParameter.Value; }
52      set { OrienteeringProblemDataParameter.Value = value; }
53    }
54    public OrienteeringSolution BestKnownSolution {
55      get { return BestKnownSolutionParameter.Value; }
56      set { BestKnownSolutionParameter.Value = value; }
57    }
58
59    [StorableConstructor]
60    private OrienteeringProblem(StorableConstructorFlag _) : base(_) {
61    }
62    private OrienteeringProblem(OrienteeringProblem original, Cloner cloner)
63      : base(original, cloner) {
64      OrienteeringProblemDataParameter = cloner.Clone(original.OrienteeringProblemDataParameter);
65      BestKnownSolutionParameter = cloner.Clone(original.BestKnownSolutionParameter);
66      BestOrienteeringSolutionParameter = cloner.Clone(original.BestOrienteeringSolutionParameter);
67    }
68    public override IDeepCloneable Clone(Cloner cloner) {
69      return new OrienteeringProblem(this, cloner);
70    }
71    public OrienteeringProblem()
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;
77      Dimension = OrienteeringProblemData.Cities;
78
79      InitializeOperators();
80    }
81
82    public override ISingleObjectiveEvaluationResult Evaluate(IntegerVector solution, IRandom random, CancellationToken cancellationToken) {
83      var data = OrienteeringProblemData;
84      var score = CalculateScore(data, solution);
85      var travelCosts = CalculateTravelCosts(data, solution);
86      var quality = CalculateQuality(data, score, travelCosts);
87
88      return new SingleObjectiveEvaluationResult(quality);
89    }
90
91    public static double CalculateQuality(IOrienteeringProblemData data, double score, double travelCosts) {
92      if (travelCosts > data.MaximumTravelCosts) return data.MaximumTravelCosts - travelCosts; // negative excessive distance
93      return score;
94    }
95    public static double CalculateScore(IOrienteeringProblemData data, IEnumerable<int> solution) {
96      return solution.Sum(t => data.GetScore(t));
97    }
98    public static double CalculateTravelCosts(IOrienteeringProblemData data, IntegerVector solution) {
99      var distance = data.GetPathDistance(solution, closed: false);
100      distance += (solution.Length - 2) * data.PointVisitingCosts;
101      return distance;
102    }
103    public static double CalculateTravelCosts(IOrienteeringProblemData data, IList<int> solution) {
104      var distance = data.GetPathDistance(solution, closed: false);
105      distance += (solution.Count - 2) * data.PointVisitingCosts;
106      return distance;
107    }
108
109    public override void Analyze(IntegerVector[] vectors, double[] qualities, ResultCollection results, IRandom random) {
110      base.Analyze(vectors, qualities, results, random);
111      var data = OrienteeringProblemData;
112
113      var best = GetBestSolution(vectors, qualities).Item1;
114      var score = CalculateScore(OrienteeringProblemData, best);
115      var travelCosts = CalculateTravelCosts(OrienteeringProblemData, best);
116      var quality = CalculateQuality(OrienteeringProblemData, score, travelCosts);
117
118      if (double.IsNaN(BestKnownQuality) || IsBetter(quality, BestKnownQuality)) {
119        BestKnownQuality = quality;
120        BestKnownSolutionParameter.ActualValue = data.GetSolution((IntegerVector)best.Clone(), quality, score, travelCosts);
121      }
122      var bestSoFar = BestOrienteeringSolutionParameter.ActualValue;
123
124      if (bestSoFar == null || IsBetter(quality, bestSoFar.Quality.Value)) {
125        bestSoFar = data.GetSolution((IntegerVector)best.Clone(), quality, score, travelCosts);
126        BestOrienteeringSolutionParameter.ActualValue = bestSoFar;
127      }
128    }
129    public static double CalculateInsertionCosts(IOrienteeringProblemData data, IList<int> path, int insertPosition, int point) {
130      double detour = data.GetDistance(path[insertPosition - 1], point) + data.GetDistance(point, path[insertPosition]);
131      detour += data.PointVisitingCosts;
132      detour -= data.GetDistance(path[insertPosition - 1], path[insertPosition]);
133      return detour;
134    }
135    public static double CalculateReplacementCosts(IOrienteeringProblemData data, IList<int> path, int replacePosition, int point) {
136      double detour = data.GetDistance(path[replacePosition - 1], point) + data.GetDistance(point, path[replacePosition + 1]);
137      detour -= data.GetDistance(path[replacePosition - 1], path[replacePosition]) + data.GetDistance(path[replacePosition], path[replacePosition + 1]);
138      return detour;
139    }
140    public static double CalculateRemovementSaving(IOrienteeringProblemData data, IList<int> path, int removePosition) {
141      double saving = data.GetDistance(path[removePosition - 1], path[removePosition]);
142      saving += data.GetDistance(path[removePosition], path[removePosition + 1]);
143      saving -= data.GetDistance(path[removePosition - 1], path[removePosition + 1]);
144      saving += data.PointVisitingCosts;
145      return saving;
146    }
147
148    private void RegisterEventHandlers() {
149      OrienteeringProblemDataParameter.ValueChanged += OrienteeringProblemDataParameterOnValueChanged;
150    }
151
152    private void OrienteeringProblemDataParameterOnValueChanged(object sender, EventArgs e) {
153      Dimension = OrienteeringProblemData.Cities;
154    }
155
156    protected override void OnEvaluatorChanged() {
157      base.OnEvaluatorChanged();
158      ParameterizeOperators();
159    }
160    protected override void DimensionOnChanged() {
161      base.DimensionOnChanged();
162      if (Dimension != OrienteeringProblemData.Cities)
163        Dimension = OrienteeringProblemData.Cities;
164    }
165
166    private void InitializeOperators() {
167      Encoding.SolutionCreator = new GreedyOrienteeringTourCreator() {
168        OrienteeringProblemDataParameter = { ActualName = OrienteeringProblemDataParameter.Name }
169      };
170      Operators.Add(new OrienteeringLocalImprovementOperator() {
171        OrienteeringProblemDataParameter = { ActualName = OrienteeringProblemDataParameter.Name }
172      });
173      Operators.Add(new OrienteeringShakingOperator() {
174        OrienteeringProblemDataParameter = { ActualName = OrienteeringProblemDataParameter.Name }
175      });
176      Operators.Add(new QualitySimilarityCalculator());
177      Operators.Add(new PopulationSimilarityAnalyzer(Operators.OfType<ISolutionSimilarityCalculator>()));
178
179      ParameterizeOperators();
180    }
181
182    private void ParameterizeOperators() {
183      foreach (var op in Operators.OfType<OrienteeringLocalImprovementOperator>()) {
184        op.IntegerVectorParameter.ActualName = Encoding.Name;
185        op.QualityParameter.ActualName = Evaluator.QualityParameter.ActualName;
186      }
187      foreach (var op in Operators.OfType<OrienteeringShakingOperator>()) {
188        op.IntegerVectorParameter.ActualName = Encoding.Name;
189      }
190      foreach (var similarityCalculator in Operators.OfType<ISolutionSimilarityCalculator>()) {
191        similarityCalculator.SolutionVariableName = Encoding.Name;
192        similarityCalculator.QualityVariableName = Evaluator.QualityParameter.ActualName;
193      }
194    }
195
196    #region Instance consuming
197    public void Load(OPData data) {
198      if (data.Coordinates == null && data.Distances == null)
199        throw new InvalidDataException("The given instance specifies no coordinates or distance matrix!");
200      if (data.Coordinates != null && data.Coordinates.GetLength(1) != 2)
201        throw new InvalidDataException("The coordinates of the given instance are not in the right format, there need to be one row for each customer and two columns for the x and y coordinates.");
202
203      // Clear old solutions
204      BestKnownSolution = null;
205
206      Name = data.Name;
207      Description = data.Description;
208
209      var tsp = TSP.GetDataFromInstance(data);
210      OrienteeringProblemData = new OrienteeringProblemData(tsp, data.StartingPoint, data.TerminalPoint, data.Scores, data.MaximumDistance, data.PointVisitingCosts);
211    }
212
213    public void Load(TSPData data) {
214      if (data.Coordinates == null && data.Distances == null)
215        throw new InvalidDataException("The given instance specifies no coordinates or distance matrix!");
216      if (data.Coordinates != null && data.Coordinates.GetLength(1) != 2)
217        throw new InvalidDataException("The coordinates of the given instance are not in the right format, there need to be one row for each customer and two columns for the x and y coordinates.");
218
219      // Clear old solutions
220      BestKnownSolution = null;
221
222      Name = data.Name;
223      Description = data.Description;
224
225
226      var tsp = TSP.GetDataFromInstance(data);
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);
235    }
236
237    public void Load(CVRPData data) {
238      if (data.Coordinates == null && data.Distances == null)
239        throw new InvalidDataException("The given instance specifies no coordinates or distance matrix!");
240      if (data.Coordinates != null && data.Coordinates.GetLength(1) != 2)
241        throw new InvalidDataException("The coordinates of the given instance are not in the right format, there need to be one row for each customer and two columns for the x and y coordinates.");
242
243      // Clear old solutions
244      BestKnownSolution = null;
245
246      Name = data.Name;
247      Description = data.Description;
248
249      var tsp = TSP.GetDataFromInstance(data);
250      OrienteeringProblemData = new OrienteeringProblemData(tsp, 0, 0, data.Demands, data.Capacity * 2, 0);
251    }
252    #endregion
253  }
254}
Note: See TracBrowser for help on using the repository browser.