- Timestamp:
- 09/16/19 16:12:21 (5 years ago)
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
branches/2521_ProblemRefactoring/HeuristicLab.Problems.PTSP/3.3/PTSP.cs
r17226 r17253 22 22 using System; 23 23 using System.Linq; 24 using H euristicLab.Analysis;24 using HEAL.Attic; 25 25 using HeuristicLab.Common; 26 26 using HeuristicLab.Core; … … 28 28 using HeuristicLab.Encodings.PermutationEncoding; 29 29 using HeuristicLab.Optimization; 30 using HeuristicLab.Optimization.Operators;31 30 using HeuristicLab.Parameters; 32 using HEAL.Attic;33 31 using HeuristicLab.Problems.Instances; 32 using HeuristicLab.Problems.TravelingSalesman; 33 using HeuristicLab.Random; 34 34 35 35 namespace HeuristicLab.Problems.PTSP { 36 [Item("Probabilistic T raveling Salesman Problem (PTSP)", "Represents a Probabilistic Traveling Salesman Problem.")]37 [StorableType(" 4CB8ACF3-C3D4-4CC6-BB1F-986BDE16B30A")]38 public abstract class ProbabilisticT ravelingSalesmanProblem : SingleObjectiveBasicProblem<PermutationEncoding>,39 IProblemInstanceConsumer<PTSPData> {36 [Item("Probabilistic TSP (p-TSP)", "Represents a Probabilistic Traveling Salesman Problem.")] 37 [StorableType("86041a8c-14e6-46e1-b20f-566892c871f6")] 38 public abstract class ProbabilisticTSP : PermutationProblem, 39 IProblemInstanceConsumer<PTSPData> { 40 40 protected bool SuppressEvents { get; set; } 41 41 42 p rivate static readonlyint DistanceMatrixSizeLimit = 1000;42 public static int DistanceMatrixSizeLimit = 1000; 43 43 44 44 #region Parameter Properties 45 public OptionalValueParameter<DoubleMatrix> CoordinatesParameter { 46 get { return (OptionalValueParameter<DoubleMatrix>)Parameters["Coordinates"]; } 47 } 48 public OptionalValueParameter<DistanceCalculator> DistanceCalculatorParameter { 49 get { return (OptionalValueParameter<DistanceCalculator>)Parameters["DistanceCalculator"]; } 50 } 51 public OptionalValueParameter<DistanceMatrix> DistanceMatrixParameter { 52 get { return (OptionalValueParameter<DistanceMatrix>)Parameters["DistanceMatrix"]; } 53 } 54 public IFixedValueParameter<BoolValue> UseDistanceMatrixParameter { 55 get { return (IFixedValueParameter<BoolValue>)Parameters["UseDistanceMatrix"]; } 56 } 57 public OptionalValueParameter<Permutation> BestKnownSolutionParameter { 58 get { return (OptionalValueParameter<Permutation>)Parameters["BestKnownSolution"]; } 59 } 60 public IValueParameter<DoubleArray> ProbabilitiesParameter { 61 get { return (IValueParameter<DoubleArray>)Parameters["Probabilities"]; } 62 } 45 [Storable] public ValueParameter<IProbabilisticTSPData> PTSPDataParameter { get; private set; } 46 [Storable] public OptionalValueParameter<ITSPSolution> BestKnownSolutionParameter { get; private set; } 63 47 #endregion 64 48 65 49 #region Properties 66 public DoubleMatrix Coordinates{67 get { return CoordinatesParameter.Value; }68 set { CoordinatesParameter.Value = value; }50 public IProbabilisticTSPData ProbabilisticTSPData { 51 get { return PTSPDataParameter.Value; } 52 set { PTSPDataParameter.Value = value; } 69 53 } 70 public DistanceCalculator DistanceCalculator { 71 get { return DistanceCalculatorParameter.Value; } 72 set { DistanceCalculatorParameter.Value = value; } 73 } 74 public DistanceMatrix DistanceMatrix { 75 get { return DistanceMatrixParameter.Value; } 76 set { DistanceMatrixParameter.Value = value; } 77 } 78 public bool UseDistanceMatrix { 79 get { return UseDistanceMatrixParameter.Value.Value; } 80 set { UseDistanceMatrixParameter.Value.Value = value; } 81 } 82 public Permutation BestKnownSolution { 54 public ITSPSolution BestKnownSolution { 83 55 get { return BestKnownSolutionParameter.Value; } 84 56 set { BestKnownSolutionParameter.Value = value; } 85 57 } 86 public DoubleArray Probabilities {87 get { return ProbabilitiesParameter.Value; }88 set { ProbabilitiesParameter.Value = value; }89 }90 91 58 #endregion 92 59 … … 96 63 97 64 [StorableConstructor] 98 protected ProbabilisticT ravelingSalesmanProblem(StorableConstructorFlag _) : base(_) { }99 protected ProbabilisticT ravelingSalesmanProblem(ProbabilisticTravelingSalesmanProblemoriginal, Cloner cloner)65 protected ProbabilisticTSP(StorableConstructorFlag _) : base(_) { } 66 protected ProbabilisticTSP(ProbabilisticTSP original, Cloner cloner) 100 67 : base(original, cloner) { 101 RegisterEventHandlers(); 68 PTSPDataParameter = cloner.Clone(original.PTSPDataParameter); 69 BestKnownSolutionParameter = cloner.Clone(original.BestKnownSolutionParameter); 102 70 } 103 protected ProbabilisticTravelingSalesmanProblem() { 104 Parameters.Add(new OptionalValueParameter<DoubleMatrix>("Coordinates", "The x- and y-Coordinates of the cities.")); 105 Parameters.Add(new OptionalValueParameter<DistanceCalculator>("DistanceCalculator", "Calculates the distance between two rows in the coordinates matrix.")); 106 Parameters.Add(new OptionalValueParameter<DistanceMatrix>("DistanceMatrix", "The matrix which contains the distances between the cities.")); 107 Parameters.Add(new FixedValueParameter<BoolValue>("UseDistanceMatrix", "True if the coordinates based evaluators should calculate the distance matrix from the coordinates and use it for evaluation similar to the distance matrix evaluator, otherwise false.", new BoolValue(true))); 108 Parameters.Add(new OptionalValueParameter<Permutation>("BestKnownSolution", "The best known solution of this TSP instance.")); 109 Parameters.Add(new ValueParameter<DoubleArray>("Probabilities", "This list describes for each city the probability of appearing in a realized instance.")); 71 protected ProbabilisticTSP() { 72 Parameters.Add(PTSPDataParameter = new ValueParameter<IProbabilisticTSPData>("PTSP Data", "The main parameters for the p-TSP.")); 73 Parameters.Add(BestKnownSolutionParameter = new OptionalValueParameter<ITSPSolution>("BestKnownSolution", "The best known solution of this p-TSP instance.")); 110 74 111 var coordinates = new DoubleMatrix(new double[,] { 112 { 100, 100 }, { 100, 200 }, { 100, 300 }, { 100, 400 }, 113 { 200, 100 }, { 200, 200 }, { 200, 300 }, { 200, 400 }, 114 { 300, 100 }, { 300, 200 }, { 300, 300 }, { 300, 400 }, 115 { 400, 100 }, { 400, 200 }, { 400, 300 }, { 400, 400 } 116 }); 117 Coordinates = coordinates; 118 Encoding.Length = coordinates.Rows; 119 DistanceCalculator = new EuclideanDistance(); 120 DistanceMatrix = new DistanceMatrix(CalculateDistances()); 121 Probabilities = new DoubleArray(Enumerable.Range(0, coordinates.Rows).Select(x => 0.5).ToArray()); 122 123 InitializeOperators(); 124 Parameterize(); 125 RegisterEventHandlers(); 126 } 127 128 private void InitializeOperators() { 129 Operators.Add(new HammingSimilarityCalculator()); 130 Operators.Add(new QualitySimilarityCalculator()); 131 Operators.Add(new PopulationSimilarityAnalyzer(Operators.OfType<ISolutionSimilarityCalculator>())); 132 } 133 134 [StorableHook(HookType.AfterDeserialization)] 135 private void AfterDeserialization() { 136 RegisterEventHandlers(); 75 ProbabilisticTSPData = new MatrixProbabilisticTSPData(); 76 Encoding.Length = ProbabilisticTSPData.Cities; 137 77 } 138 78 139 79 protected override void OnEncodingChanged() { 140 80 base.OnEncodingChanged(); 141 Encoding.Length = Coordinates.Rows; 142 Parameterize(); 81 Encoding.Length = ProbabilisticTSPData.Cities; 143 82 } 144 83 145 private void RegisterEventHandlers() { 146 CoordinatesParameter.ValueChanged += CoordinatesParameterOnValueChanged; 147 if (Coordinates != null) { 148 Coordinates.RowsChanged += CoordinatesOnChanged; 149 Coordinates.ItemChanged += CoordinatesOnChanged; 84 public override void Analyze(Permutation[] solutions, double[] qualities, ResultCollection results, IRandom random) { 85 base.Analyze(solutions, qualities, results, random); 86 var max = Maximization; 87 88 var i = !max ? qualities.Select((x, index) => new { index, x }).OrderBy(x => x).First().index 89 : qualities.Select((x, index) => new { index, x }).OrderByDescending(x => x).First().index; 90 91 if (double.IsNaN(BestKnownQuality) || 92 max && qualities[i] > BestKnownQuality || 93 !max && qualities[i] < BestKnownQuality) { 94 BestKnownQuality = qualities[i]; 95 BestKnownSolution = ProbabilisticTSPData.GetSolution((Permutation)solutions[i].Clone(), qualities[i]); 150 96 } 151 UseDistanceMatrixParameter.Value.ValueChanged += UseDistanceMatrixValueChanged;152 DistanceCalculatorParameter.ValueChanged += DistanceCalculatorParameterOnValueChanged;153 }154 97 155 private void CoordinatesParameterOnValueChanged(object sender, EventArgs eventArgs) { 156 if (Coordinates != null) { 157 Coordinates.RowsChanged += CoordinatesOnChanged; 158 Coordinates.ItemChanged += CoordinatesOnChanged; 159 } 160 if (SuppressEvents) return; 161 UpdateInstance(); 162 } 163 164 private void CoordinatesOnChanged(object sender, EventArgs eventArgs) { 165 if (SuppressEvents) return; 166 UpdateInstance(); 167 } 168 169 private void UseDistanceMatrixValueChanged(object sender, EventArgs eventArgs) { 170 if (SuppressEvents) return; 171 UpdateInstance(); 172 } 173 174 private void DistanceCalculatorParameterOnValueChanged(object sender, EventArgs eventArgs) { 175 if (SuppressEvents) return; 176 UpdateInstance(); 177 } 178 179 public override double Evaluate(Individual individual, IRandom random) { 180 return Evaluate(individual.Permutation(), random); 181 } 182 183 public abstract double Evaluate(Permutation tour, IRandom random); 184 185 public double[,] CalculateDistances() { 186 var coords = Coordinates; 187 var len = coords.Rows; 188 var dist = DistanceCalculator; 189 190 var matrix = new double[len, len]; 191 for (var i = 0; i < len - 1; i++) 192 for (var j = i + 1; j < len; j++) 193 matrix[i, j] = matrix[j, i] = dist.Calculate(i, j, coords); 194 195 return matrix; 98 IResult bestSolutionResult; 99 if (results.TryGetValue("Best p-TSP Solution", out bestSolutionResult)) { 100 var bestSolution = bestSolutionResult.Value as ITSPSolution; 101 if (bestSolution == null || Maximization && bestSolution.TourLength.Value < qualities[i] 102 || !Maximization && bestSolution.TourLength.Value > qualities[i]) { 103 bestSolutionResult.Value = ProbabilisticTSPData.GetSolution(solutions[i], qualities[i]); 104 } 105 } else results.Add(new Result("Best p-TSP Solution", ProbabilisticTSPData.GetSolution(solutions[i], qualities[i]))); 196 106 } 197 107 198 108 public virtual void Load(PTSPData data) { 199 try {200 SuppressEvents = true;201 if (data.Coordinates == null && data.Distances == null)202 throw new System.IO.InvalidDataException("The given instance specifies neither coordinates nor distances!");203 if (data.Dimension > DistanceMatrixSizeLimit && (data.Coordinates == null || data.Coordinates.GetLength(0) != data.Dimension || data.Coordinates.GetLength(1) != 2))204 throw new System.IO.InvalidDataException("The given instance is too large for using a distance matrix and there is a problem with the coordinates.");205 if (data.Coordinates != null && (data.Coordinates.GetLength(0) != data.Dimension || data.Coordinates.GetLength(1) != 2))206 throw new System.IO.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 respectively.");109 if (data.Coordinates == null && data.Distances == null) 110 throw new System.IO.InvalidDataException("The given instance specifies neither coordinates nor distances!"); 111 if (data.Dimension > DistanceMatrixSizeLimit && (data.DistanceMeasure == DistanceMeasure.Att 112 || data.DistanceMeasure == DistanceMeasure.Manhattan 113 || data.DistanceMeasure == DistanceMeasure.Maximum)) 114 throw new System.IO.InvalidDataException("The given instance uses an unsupported distance measure and is too large for using a distance matrix."); 115 if (data.Coordinates != null && data.Coordinates.GetLength(1) != 2) 116 throw new System.IO.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."); 207 117 118 Encoding.Length = data.Dimension; 119 Name = data.Name; 120 Description = data.Description; 121 122 if (data.Dimension <= DistanceMatrixSizeLimit) { 123 ProbabilisticTSPData = new MatrixProbabilisticTSPData(data.Name, data.GetDistanceMatrix(), data.Probabilities, data.Coordinates) { Description = data.Description }; 124 } else if (data.DistanceMeasure == DistanceMeasure.Direct && data.Distances != null) { 125 ProbabilisticTSPData = new MatrixProbabilisticTSPData(data.Name, data.Distances, data.Probabilities, data.Coordinates) { Description = data.Description }; 126 } else { 208 127 switch (data.DistanceMeasure) { 209 case DistanceMeasure.Direct: 210 DistanceCalculator = null; 211 if (data.Dimension > DistanceMatrixSizeLimit && Coordinates != null) { 212 DistanceCalculator = new EuclideanDistance(); 213 UseDistanceMatrix = false; 214 } else UseDistanceMatrix = true; 128 case DistanceMeasure.Att: 129 ProbabilisticTSPData = new AttPTSPData(data.Name, data.Coordinates, data.Probabilities) { Description = data.Description }; 215 130 break; 216 case DistanceMeasure.Att: DistanceCalculator = new AttDistance(); break; 217 case DistanceMeasure.Euclidean: DistanceCalculator = new EuclideanDistance(); break; 218 case DistanceMeasure.Geo: DistanceCalculator = new GeoDistance(); break; 219 case DistanceMeasure.Manhattan: DistanceCalculator = new ManhattanDistance(); break; 220 case DistanceMeasure.Maximum: DistanceCalculator = new MaximumDistance(); break; 221 case DistanceMeasure.RoundedEuclidean: DistanceCalculator = new RoundedEuclideanDistance(); break; 222 case DistanceMeasure.UpperEuclidean: DistanceCalculator = new UpperEuclideanDistance(); break; 223 default: throw new ArgumentException("Distance measure is unknown"); 131 case DistanceMeasure.Euclidean: 132 ProbabilisticTSPData = new EuclideanPTSPData(data.Name, data.Coordinates, data.Probabilities, EuclideanTSPData.DistanceRounding.None) { Description = data.Description }; 133 break; 134 case DistanceMeasure.RoundedEuclidean: 135 ProbabilisticTSPData = new EuclideanPTSPData(data.Name, data.Coordinates, data.Probabilities, EuclideanTSPData.DistanceRounding.Midpoint) { Description = data.Description }; 136 break; 137 case DistanceMeasure.UpperEuclidean: 138 ProbabilisticTSPData = new EuclideanPTSPData(data.Name, data.Coordinates, data.Probabilities, EuclideanTSPData.DistanceRounding.Ceiling) { Description = data.Description }; 139 break; 140 case DistanceMeasure.Geo: 141 ProbabilisticTSPData = new GeoPTSPData(data.Name, data.Coordinates, data.Probabilities) { Description = data.Description }; 142 break; 143 case DistanceMeasure.Manhattan: 144 ProbabilisticTSPData = new ManhattanPTSPData(data.Name, data.Coordinates, data.Probabilities) { Description = data.Description }; 145 break; 146 case DistanceMeasure.Maximum: 147 ProbabilisticTSPData = new MaximumPTSPData(data.Name, data.Coordinates, data.Probabilities) { Description = data.Description }; 148 break; 149 default: 150 throw new System.IO.InvalidDataException("An unknown distance measure is given in the instance!"); 224 151 } 152 } 153 BestKnownSolution = null; 154 BestKnownQuality = double.NaN; 225 155 226 Name = data.Name; 227 Description = data.Description; 228 229 Probabilities = new DoubleArray(data.Probabilities); 230 BestKnownSolution = data.BestKnownTour != null ? new Permutation(PermutationTypes.RelativeUndirected, data.BestKnownTour) : null; 231 Coordinates = data.Coordinates != null && data.Coordinates.GetLength(0) > 0 ? new DoubleMatrix(data.Coordinates) : null; 232 DistanceMatrix = data.Dimension <= DistanceMatrixSizeLimit && UseDistanceMatrix ? new DistanceMatrix(data.GetDistanceMatrix()) : null; 233 234 Encoding.Length = data.Dimension; 235 } finally { SuppressEvents = false; } 156 if (data.BestKnownTour != null) { 157 try { 158 var tour = new Permutation(PermutationTypes.RelativeUndirected, data.BestKnownTour); 159 var tourLength = Evaluate(tour, new FastRandom(1)); 160 BestKnownSolution = new TSPSolution(data.Coordinates != null ? new DoubleMatrix(data.Coordinates) : null, tour, new DoubleValue(tourLength)); 161 BestKnownQuality = tourLength; 162 } catch (InvalidOperationException) { 163 if (data.BestKnownQuality.HasValue) 164 BestKnownQuality = data.BestKnownQuality.Value; 165 } 166 } else if (data.BestKnownQuality.HasValue) { 167 BestKnownQuality = data.BestKnownQuality.Value; 168 } 236 169 OnReset(); 237 }238 239 private void UpdateInstance() {240 var len = GetProblemDimension();241 if (Coordinates != null && Coordinates.Rows <= DistanceMatrixSizeLimit242 && DistanceCalculator != null && UseDistanceMatrix)243 DistanceMatrix = new DistanceMatrix(CalculateDistances());244 if (!UseDistanceMatrix) DistanceMatrix = null;245 Encoding.Length = len;246 247 OnReset();248 }249 250 private int GetProblemDimension() {251 if (Coordinates == null && DistanceMatrix == null) throw new InvalidOperationException("Both coordinates and distance matrix are null, please specify at least one of them.");252 return Coordinates != null ? Coordinates.Rows : DistanceMatrix.Rows;253 }254 255 private void Parameterize() {256 foreach (var similarityCalculator in Operators.OfType<ISolutionSimilarityCalculator>()) {257 similarityCalculator.SolutionVariableName = Encoding.SolutionCreator.PermutationParameter.ActualName;258 similarityCalculator.QualityVariableName = Evaluator.QualityParameter.ActualName;259 }260 170 } 261 171 }
Note: See TracChangeset
for help on using the changeset viewer.