Free cookie consent management tool by TermsFeed Policy Generator

source: branches/2521_ProblemRefactoring/HeuristicLab.Problems.TravelingSalesman/3.3/TSPData.cs @ 17525

Last change on this file since 17525 was 17525, checked in by abeham, 4 years ago

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

  • Visualization of OrienteeringProblemData
  • Fix visualization of solution
  • Cleanup unused classes
File size: 15.9 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 HEAL.Attic;
25using HeuristicLab.Common;
26using HeuristicLab.Core;
27using HeuristicLab.Data;
28using HeuristicLab.Encodings.PermutationEncoding;
29using HeuristicLab.Problems.Instances;
30
31namespace HeuristicLab.Problems.TravelingSalesman {
32  [StorableType("1a9bf60c-b6a6-4c95-8e99-5a2dec0ee892")]
33  public interface ITSPData : INamedItem {
34    int Cities { get; }
35
36    double GetDistance(int fromCity, int toCity);
37    double GetPathDistance(IEnumerable<int> path, bool closed = true);
38    ITSPSolution GetSolution(Permutation tspTour, double tourLength);
39    TSPData Export();
40  }
41
42  [Item("Matrix-based TSP Data", "TSP that is representd by a distance matrix.")]
43  [StorableType("4df58a35-679d-4414-b815-9450ae100823")]
44  public sealed class MatrixTSPData : NamedItem, ITSPData {
45    [Storable] public DoubleMatrix Matrix { get; private set; }
46    [Storable] public DoubleMatrix DisplayCoordinates { get; private set; }
47
48    public int Cities => Matrix.Rows;
49
50    [StorableConstructor]
51    private  MatrixTSPData(StorableConstructorFlag _) : base(_) { }
52    private MatrixTSPData(MatrixTSPData original, Cloner cloner) : base(original, cloner) {
53      Matrix = original.Matrix;
54      DisplayCoordinates = original.DisplayCoordinates;
55    }
56    public MatrixTSPData() {
57      Name = TSPDefaultInstance.Name;
58      Matrix = TSPDefaultInstance.Distances;
59      DisplayCoordinates = TSPDefaultInstance.Coordinates;
60    }
61    public MatrixTSPData(string name, double[,] matrix, double[,] coordinates = null) {
62      if (coordinates != null && coordinates.GetLength(1) != 2)
63        throw new ArgumentException("Argument must have exactly two columns.", nameof(coordinates));
64      if (coordinates != null && coordinates.GetLength(0) != matrix.GetLength(0))
65        throw new ArgumentException("Unequal number of rows in " + nameof(matrix) + " and " + nameof(coordinates) + ".");
66      Name = name;
67      Matrix = new DoubleMatrix(matrix, @readonly: true);
68      if (coordinates != null) DisplayCoordinates = new DoubleMatrix(coordinates, @readonly: true);
69    }
70    public MatrixTSPData(string name, DoubleMatrix matrix, DoubleMatrix coordinates = null) {
71      if (coordinates != null && coordinates.Columns != 2)
72        throw new ArgumentException("Argument must have exactly two columns.", nameof(coordinates));
73      if (coordinates != null && coordinates.Rows != matrix.Rows)
74        throw new ArgumentException("Unequal number of rows in " + nameof(matrix) + " and " + nameof(coordinates) + ".");
75      Name = name;
76      Matrix = matrix.AsReadOnly();
77      DisplayCoordinates = coordinates?.AsReadOnly();
78    }
79
80    public ITSPSolution GetSolution(Permutation tour, double tourLength) {
81      return new TSPSolution(this, tour, new DoubleValue(tourLength));
82    }
83
84    public override IDeepCloneable Clone(Cloner cloner) {
85      return new MatrixTSPData(this, cloner);
86    }
87
88    public double GetDistance(int fromCity, int toCity) => Matrix[fromCity, toCity];
89    public double GetPathDistance(IEnumerable<int> path, bool closed = true) {
90      var iter = path.GetEnumerator();
91      if (!iter.MoveNext()) return 0;
92      var start = iter.Current;
93      var prev = start;
94      var distance = 0.0;
95      while (iter.MoveNext()) {
96        var cur = iter.Current;
97        distance += Matrix[prev, cur];
98        prev = cur;
99      }
100      if (closed) distance += Matrix[prev, start];
101      return distance;
102    }
103    public TSPData Export() {
104      return new TSPData() {
105        Name = name,
106        Description = description,
107        Coordinates = DisplayCoordinates?.CloneAsMatrix(),
108        Dimension = Matrix.Rows,
109        DistanceMeasure = DistanceMeasure.Direct,
110        Distances = Matrix.CloneAsMatrix()
111      };
112    }
113  }
114
115  [Item("Coordinates-based TSP Data", "TSP that is represented by coordinates of locations.")]
116  [StorableType("3955d07a-d43c-4a01-9505-d2effb1ea865")]
117  public abstract class CoordinatesTSPData : NamedItem, ITSPData {
118    [Storable] public DoubleMatrix Coordinates { get; protected set; }
119
120    public int Cities => Coordinates.Rows;
121
122    [StorableConstructor]
123    protected CoordinatesTSPData(StorableConstructorFlag _) : base(_) { }
124    protected CoordinatesTSPData(CoordinatesTSPData original, Cloner cloner) : base(original, cloner) {
125      Coordinates = original.Coordinates;
126    }
127    protected CoordinatesTSPData() : base() {
128      Name = TSPDefaultInstance.Name;
129      Coordinates = TSPDefaultInstance.Coordinates;
130    }
131    protected CoordinatesTSPData(string name, double[,] coordinates) : base() {
132      if (coordinates == null) throw new ArgumentNullException(nameof(coordinates));
133      if (coordinates.GetLength(1) != 2) throw new ArgumentException("Argument must have exactly two columns.", nameof(coordinates));
134      Name = name;
135      Coordinates = new DoubleMatrix(coordinates, @readonly: true);
136    }
137    protected CoordinatesTSPData(string name, DoubleMatrix coordinates) : base() {
138      if (coordinates == null) throw new ArgumentNullException(nameof(coordinates));
139      if (coordinates.Columns != 2) throw new ArgumentException("Argument must have exactly two columns.", nameof(coordinates));
140      Name = name;
141      Coordinates = coordinates.AsReadOnly();
142    }
143
144    public double GetDistance(int fromCity, int toCity) {
145      return GetDistance(Coordinates[fromCity, 0], Coordinates[fromCity, 1],
146        Coordinates[toCity, 0], Coordinates[toCity, 1]);
147    }
148
149    public abstract double GetDistance(double fromX, double fromY, double toX, double toY);
150    public double GetPathDistance(IEnumerable<int> path, bool closed = true) {
151      var iter = path.GetEnumerator();
152      if (!iter.MoveNext()) return 0;
153      var start = iter.Current;
154      var prev = start;
155      var distance = 0.0;
156      while (iter.MoveNext()) {
157        var cur = iter.Current;
158        distance += GetDistance(prev, cur);
159        prev = cur;
160      }
161      if (closed) distance += GetDistance(prev, start);
162      return distance;
163    }
164
165    public virtual ITSPSolution GetSolution(Permutation tour, double tourLength) {
166      return new TSPSolution(this, tour, new DoubleValue(tourLength));
167    }
168
169    public abstract TSPData Export();
170  }
171
172  [Item("Euclidean TSP Data", "TSP that is represented by coordinates in an Euclidean plane.")]
173  [StorableType("4bf58348-cd98-46c5-a4c0-55f486ca88b4")]
174  public sealed class EuclideanTSPData : CoordinatesTSPData {
175    [StorableType("be274140-e289-4125-ae3e-8c2f1d942f94")]
176    public enum DistanceRounding { None, Midpoint, Ceiling }
177
178    [Storable] public DistanceRounding Rounding { get; private set; }
179
180    [StorableConstructor]
181    private EuclideanTSPData(StorableConstructorFlag _) : base(_) { }
182    private EuclideanTSPData(EuclideanTSPData original, Cloner cloner) : base(original, cloner) {
183      Rounding = original.Rounding;
184    }
185    public EuclideanTSPData()
186      : base() {
187      Rounding = DistanceRounding.Midpoint;
188    }
189    public EuclideanTSPData(string name, double[,] coordinates, DistanceRounding rounding = DistanceRounding.None)
190      : base(name, coordinates) {
191      Rounding = rounding;
192    }
193    public EuclideanTSPData(string name, DoubleMatrix coordinates, DistanceRounding rounding = DistanceRounding.None)
194      : base(name, coordinates) {
195      Rounding = rounding;
196    }
197
198    public override IDeepCloneable Clone(Cloner cloner) {
199      return new EuclideanTSPData(this, cloner);
200    }
201
202    public override double GetDistance(double fromX, double fromY, double toX, double toY) {
203      var dist = DistanceHelper.EuclideanDistance(fromX, fromY, toX, toY);
204      switch (Rounding) {
205        case DistanceRounding.None: return dist;
206        case DistanceRounding.Midpoint: return Math.Round(dist);
207        case DistanceRounding.Ceiling: return Math.Ceiling(dist);
208        default: throw new InvalidOperationException("Unknown rounding mode " + Rounding);
209      }
210    }
211
212    public override TSPData Export() {
213      var data = new TSPData() {
214        Name = name,
215        Description = description,
216        Coordinates = Coordinates.CloneAsMatrix(),
217        Dimension = Coordinates.Rows
218      };
219      switch (Rounding) {
220        case DistanceRounding.None: data.DistanceMeasure = DistanceMeasure.Euclidean; break;
221        case DistanceRounding.Midpoint: data.DistanceMeasure = DistanceMeasure.RoundedEuclidean; break;
222        case DistanceRounding.Ceiling: data.DistanceMeasure = DistanceMeasure.UpperEuclidean; break;
223      }
224      return data;
225    }
226  }
227
228  [Item("Geo TSP Data", "TSP that is represented by geo coordinates.")]
229  [StorableType("dc859a89-e6c2-4af3-a3b6-9aa3041b14a9")]
230  public sealed class GeoTSPData : CoordinatesTSPData {
231    [StorableConstructor]
232    private GeoTSPData(StorableConstructorFlag _) : base(_) { }
233    private GeoTSPData(GeoTSPData original, Cloner cloner) : base(original, cloner) { }
234    public GeoTSPData() : base() { }
235    public GeoTSPData(string name, double[,] coordinates) : base(name, coordinates) { }
236    public GeoTSPData(string name, DoubleMatrix coordinates) : base(name, coordinates) { }
237
238    public override IDeepCloneable Clone(Cloner cloner) {
239      return new GeoTSPData(this, cloner);
240    }
241
242    public override double GetDistance(double fromX, double fromY, double toX, double toY) {
243      return DistanceHelper.GeoDistance(fromX, fromY, toX, toY);
244    }
245
246    public override TSPData Export() {
247      return new TSPData() {
248        Name = name,
249        Description = description,
250        Coordinates = Coordinates.CloneAsMatrix(),
251        Dimension = Coordinates.Rows,
252        DistanceMeasure = DistanceMeasure.Geo
253      };
254    }
255  }
256
257  [Item("ATT TSP Data", "TSP that is represented by ATT coordinates.")]
258  [StorableType("d7a0add3-6ec1-42e0-b1d7-b6454694d485")]
259  public sealed class AttTSPData : CoordinatesTSPData {
260    [StorableConstructor]
261    private AttTSPData(StorableConstructorFlag _) : base(_) { }
262    private AttTSPData(AttTSPData original, Cloner cloner) : base(original, cloner) { }
263    public AttTSPData() : base() { }
264    public AttTSPData(string name, double[,] coordinates) : base(name, coordinates) { }
265    public AttTSPData(string name, DoubleMatrix coordinates) : base(name, coordinates) { }
266
267    public override IDeepCloneable Clone(Cloner cloner) {
268      return new AttTSPData(this, cloner);
269    }
270
271    public override double GetDistance(double fromX, double fromY, double toX, double toY) {
272      return DistanceHelper.AttDistance(fromX, fromY, toX, toY);
273    }
274
275    public override TSPData Export() {
276      return new TSPData() {
277        Name = name,
278        Description = description,
279        Coordinates = Coordinates.CloneAsMatrix(),
280        Dimension = Coordinates.Rows,
281        DistanceMeasure = DistanceMeasure.Att
282      };
283    }
284  }
285
286  [Item("Manhattan TSP Data", "TSP that is represented by Manhattan coordinates.")]
287  [StorableType("5f1ef9e2-cbd1-400e-8f87-6855f091fc9e")]
288  public sealed class ManhattanTSPData : CoordinatesTSPData {
289    [StorableConstructor]
290    private ManhattanTSPData(StorableConstructorFlag _) : base(_) { }
291    private ManhattanTSPData(ManhattanTSPData original, Cloner cloner) : base(original, cloner) { }
292    public ManhattanTSPData() : base() { }
293    public ManhattanTSPData(string name, double[,] coordinates) : base(name, coordinates) { }
294    public ManhattanTSPData(string name, DoubleMatrix coordinates) : base(name, coordinates) { }
295
296    public override IDeepCloneable Clone(Cloner cloner) {
297      return new ManhattanTSPData(this, cloner);
298    }
299
300    public override double GetDistance(double fromX, double fromY, double toX, double toY) {
301      return DistanceHelper.ManhattanDistance(fromX, fromY, toX, toY);
302    }
303
304    public override TSPData Export() {
305      return new TSPData() {
306        Name = name,
307        Description = description,
308        Coordinates = Coordinates.CloneAsMatrix(),
309        Dimension = Coordinates.Rows,
310        DistanceMeasure = DistanceMeasure.Manhattan
311      };
312    }
313  }
314
315  [Item("Manhattan TSP Data", "TSP that is represented by the maximum absolute distance in either x or y coordinates.")]
316  [StorableType("c6294a6c-fe62-4906-9765-4bc306d3e4a8")]
317  public sealed class MaximumTSPData : CoordinatesTSPData {
318    [StorableConstructor]
319    private MaximumTSPData(StorableConstructorFlag _) : base(_) { }
320    private MaximumTSPData(MaximumTSPData original, Cloner cloner) : base(original, cloner) { }
321    public MaximumTSPData() : base() { }
322    public MaximumTSPData(string name, double[,] coordinates) : base(name, coordinates) { }
323    public MaximumTSPData(string name, DoubleMatrix coordinates) : base(name, coordinates) { }
324
325    public override IDeepCloneable Clone(Cloner cloner) {
326      return new MaximumTSPData(this, cloner);
327    }
328
329    public override double GetDistance(double fromX, double fromY, double toX, double toY) {
330      return DistanceHelper.MaximumDistance(fromX, fromY, toX, toY);
331    }
332
333    public override TSPData Export() {
334      return new TSPData() {
335        Name = name,
336        Description = description,
337        Coordinates = Coordinates.CloneAsMatrix(),
338        Dimension = Coordinates.Rows,
339        DistanceMeasure = DistanceMeasure.Maximum
340      };
341    }
342  }
343
344  internal static class TSPDefaultInstance {
345    internal static readonly DoubleMatrix Distances = new DoubleMatrix(new double[,] {
346{ 0, 100, 200, 300, 100, 141, 224, 316, 200, 224, 283, 361, 300, 316, 361, 424 },
347{ 100, 0, 100, 200, 141, 100, 141, 224, 224, 200, 224, 283, 316, 300, 316, 361 },
348{ 200, 100, 0, 100, 224, 141, 100, 141, 283, 224, 200, 224, 361, 316, 300, 316 },
349{ 300, 200, 100, 0, 316, 224, 141, 100, 361, 283, 224, 200, 424, 361, 316, 300 },
350{ 100, 141, 224, 316, 0, 100, 200, 300, 100, 141, 224, 316, 200, 224, 283, 361 },
351{ 141, 100, 141, 224, 100, 0, 100, 200, 141, 100, 141, 224, 224, 200, 224, 283 },
352{ 224, 141, 100, 141, 200, 100, 0, 100, 224, 141, 100, 141, 283, 224, 200, 224 },
353{ 316, 224, 141, 100, 300, 200, 100, 0, 316, 224, 141, 100, 361, 283, 224, 200 },
354{ 200, 224, 283, 361, 100, 141, 224, 316, 0, 100, 200, 300, 100, 141, 224, 316 },
355{ 224, 200, 224, 283, 141, 100, 141, 224, 100, 0, 100, 200, 141, 100, 141, 224 },
356{ 283, 224, 200, 224, 224, 141, 100, 141, 200, 100, 0, 100, 224, 141, 100, 141 },
357{ 361, 283, 224, 200, 316, 224, 141, 100, 300, 200, 100, 0, 316, 224, 141, 100 },
358{ 300, 316, 361, 424, 200, 224, 283, 361, 100, 141, 224, 316, 0, 100, 200, 300 },
359{ 316, 300, 316, 361, 224, 200, 224, 283, 141, 100, 141, 224, 100, 0, 100, 200 },
360{ 361, 316, 300, 316, 283, 224, 200, 224, 224, 141, 100, 141, 200, 100, 0, 100 },
361{ 424, 361, 316, 300, 361, 283, 224, 200, 316, 224, 141, 100, 300, 200, 100, 0 },
362}, @readonly: true);
363    internal static readonly DoubleMatrix Coordinates = new DoubleMatrix(new double[,] {
364{ 100, 100 }, { 100, 200 }, { 100, 300 }, { 100, 400 },
365{ 200, 100 }, { 200, 200 }, { 200, 300 }, { 200, 400 },
366{ 300, 100 }, { 300, 200 }, { 300, 300 }, { 300, 400 },
367{ 400, 100 }, { 400, 200 }, { 400, 300 }, { 400, 400 }
368}, @readonly: true);
369    internal static readonly string Name = "HL TSP Default";
370  }
371}
Note: See TracBrowser for help on using the repository browser.