Free cookie consent management tool by TermsFeed Policy Generator

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

Last change on this file since 17253 was 17253, checked in by abeham, 5 years ago

#2521: worked on refactoring PTSP

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