Free cookie consent management tool by TermsFeed Policy Generator

Ignore:
Timestamp:
09/16/19 16:12:21 (5 years ago)
Author:
abeham
Message:

#2521: worked on refactoring PTSP

File:
1 edited

Legend:

Unmodified
Added
Removed
  • branches/2521_ProblemRefactoring/HeuristicLab.Problems.PTSP/3.3/PTSP.cs

    r17226 r17253  
    2222using System;
    2323using System.Linq;
    24 using HeuristicLab.Analysis;
     24using HEAL.Attic;
    2525using HeuristicLab.Common;
    2626using HeuristicLab.Core;
     
    2828using HeuristicLab.Encodings.PermutationEncoding;
    2929using HeuristicLab.Optimization;
    30 using HeuristicLab.Optimization.Operators;
    3130using HeuristicLab.Parameters;
    32 using HEAL.Attic;
    3331using HeuristicLab.Problems.Instances;
     32using HeuristicLab.Problems.TravelingSalesman;
     33using HeuristicLab.Random;
    3434
    3535namespace HeuristicLab.Problems.PTSP {
    36   [Item("Probabilistic Traveling Salesman Problem (PTSP)", "Represents a Probabilistic Traveling Salesman Problem.")]
    37   [StorableType("4CB8ACF3-C3D4-4CC6-BB1F-986BDE16B30A")]
    38   public abstract class ProbabilisticTravelingSalesmanProblem : 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> {
    4040    protected bool SuppressEvents { get; set; }
    4141
    42     private static readonly int DistanceMatrixSizeLimit = 1000;
     42    public static int DistanceMatrixSizeLimit = 1000;
    4343
    4444    #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; }
    6347    #endregion
    6448
    6549    #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; }
    6953    }
    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 {
    8355      get { return BestKnownSolutionParameter.Value; }
    8456      set { BestKnownSolutionParameter.Value = value; }
    8557    }
    86     public DoubleArray Probabilities {
    87       get { return ProbabilitiesParameter.Value; }
    88       set { ProbabilitiesParameter.Value = value; }
    89     }
    90 
    9158    #endregion
    9259
     
    9663
    9764    [StorableConstructor]
    98     protected ProbabilisticTravelingSalesmanProblem(StorableConstructorFlag _) : base(_) { }
    99     protected ProbabilisticTravelingSalesmanProblem(ProbabilisticTravelingSalesmanProblem original, Cloner cloner)
     65    protected ProbabilisticTSP(StorableConstructorFlag _) : base(_) { }
     66    protected ProbabilisticTSP(ProbabilisticTSP original, Cloner cloner)
    10067      : base(original, cloner) {
    101       RegisterEventHandlers();
     68      PTSPDataParameter = cloner.Clone(original.PTSPDataParameter);
     69      BestKnownSolutionParameter = cloner.Clone(original.BestKnownSolutionParameter);
    10270    }
    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."));
    11074
    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;
    13777    }
    13878
    13979    protected override void OnEncodingChanged() {
    14080      base.OnEncodingChanged();
    141       Encoding.Length = Coordinates.Rows;
    142       Parameterize();
     81      Encoding.Length = ProbabilisticTSPData.Cities;
    14382    }
    14483
    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]);
    15096      }
    151       UseDistanceMatrixParameter.Value.ValueChanged += UseDistanceMatrixValueChanged;
    152       DistanceCalculatorParameter.ValueChanged += DistanceCalculatorParameterOnValueChanged;
    153     }
    15497
    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])));
    196106    }
    197107
    198108    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.");
    207117
     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 {
    208127        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 };
    215130            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!");
    224151        }
     152      }
     153      BestKnownSolution = null;
     154      BestKnownQuality = double.NaN;
    225155
    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      }
    236169      OnReset();
    237     }
    238 
    239     private void UpdateInstance() {
    240       var len = GetProblemDimension();
    241       if (Coordinates != null && Coordinates.Rows <= DistanceMatrixSizeLimit
    242         && 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       }
    260170    }
    261171  }
Note: See TracChangeset for help on using the changeset viewer.