Free cookie consent management tool by TermsFeed Policy Generator

Ignore:
Timestamp:
11/28/15 23:38:51 (8 years ago)
Author:
abeham
Message:

#2221:

  • Completely refactored PTSP branch
    • Added two sets of problem instances based on TSPLIB: homogeneous and heterogeneous
    • Implemented missing EvaluateByCoordinates for 1-shift moves
    • Made it clear that move evaluators are for estimated PTSP only
    • Changed parameter realization from a rather strange list of list of ints to a list of bool arrays
    • Reusing code of the 2-opt and 1-shift move evaluators in 2.5 move evaluator
    • Introducing distance calculators to properly handle the case when no distance matrix is given (previous code only worked with distance matrix and without only with euclidean distance in some settings)
    • Fixed several smaller code issues: protected, static, method parameters, copy & paste, interfaces, naming, parameters, serialization hooks, license headers, doc comments, data types
File:
1 copied

Legend:

Unmodified
Added
Removed
  • branches/PTSP/HeuristicLab.Problems.PTSP/3.3/Moves/TwoPointFiveOpt/PTSPTwoPointFiveMoveEvaluator.cs

    r13408 r13412  
    2020#endregion
    2121
    22 using System;
    2322using HeuristicLab.Common;
    2423using HeuristicLab.Core;
     
    2726using HeuristicLab.Parameters;
    2827using HeuristicLab.Persistence.Default.CompositeSerializers.Storable;
    29 using HeuristicLab.Optimization;
    30 using HeuristicLab.Operators;
    3128
    3229namespace HeuristicLab.Problems.PTSP {
    33   /// <summary>
    34   /// A base class for operators which evaluate TSP solutions.
    35   /// </summary>
    36   [Item("PTSP25MoveEvaluator", "Operator that evaluates 2.5-p-opt moves of PTSP")]
     30  [Item("PTSP 2.5-MoveEvaluator", "Operator that evaluates 2.5-p-opt moves of PTSP")]
    3731  [StorableClass]
    38   public class PTSP25MoveEvaluator : SingleSuccessorOperator, I25MoveOperator, ISingleObjectiveMoveEvaluator {
    39     public ILookupParameter<Permutation> PermutationParameter {
    40       get { return (ILookupParameter<Permutation>)Parameters["Permutation"]; }
    41     }
    42     public ILookupParameter<DoubleMatrix> CoordinatesParameter {
    43       get { return (ILookupParameter<DoubleMatrix>)Parameters["Coordinates"]; }
    44     }
    45     public ILookupParameter<DistanceMatrix> DistanceMatrixParameter {
    46       get { return (ILookupParameter<DistanceMatrix>)Parameters["DistanceMatrix"]; }
    47     }
    48     public ILookupParameter<BoolValue> UseDistanceMatrixParameter {
    49       get { return (ILookupParameter<BoolValue>)Parameters["UseDistanceMatrix"]; }
    50     }
    51     public IValueParameter<ItemList<ItemList<IntValue>>> RealizationsParameter {
    52       get { return (IValueParameter<ItemList<ItemList<IntValue>>>)Parameters["Realizations"]; }
    53     }
     32  public class PTSPTwoPointFiveMoveEvaluator : EstimatedPTSPMoveEvaluator, ITwoPointFiveMoveOperator {
     33
    5434    public ILookupParameter<TwoPointFiveMove> TwoPointFiveMoveParameter {
    5535      get { return (ILookupParameter<TwoPointFiveMove>)Parameters["TwoPointFiveMove"]; }
    5636    }
    57     public ILookupParameter<DoubleValue> QualityParameter {
    58       get { return (ILookupParameter<DoubleValue>)Parameters["Quality"]; }
    59     }
    60     public ILookupParameter<DoubleValue> MoveQualityParameter {
    61       get { return (ILookupParameter<DoubleValue>)Parameters["MoveQuality"]; }
    62     }
    6337
    6438    [StorableConstructor]
    65     protected PTSP25MoveEvaluator(bool deserializing) : base(deserializing) { }
    66     protected PTSP25MoveEvaluator(PTSP25MoveEvaluator original, Cloner cloner) : base(original, cloner) { }
    67     public PTSP25MoveEvaluator()
     39    protected PTSPTwoPointFiveMoveEvaluator(bool deserializing) : base(deserializing) { }
     40    protected PTSPTwoPointFiveMoveEvaluator(PTSPTwoPointFiveMoveEvaluator original, Cloner cloner) : base(original, cloner) { }
     41    public PTSPTwoPointFiveMoveEvaluator()
    6842      : base() {
    69       Parameters.Add(new LookupParameter<Permutation>("Permutation", "The solution as permutation."));
    70       Parameters.Add(new LookupParameter<DoubleMatrix>("Coordinates", "The city's coordinates."));
    71       Parameters.Add(new LookupParameter<DistanceMatrix>("DistanceMatrix", "The matrix which contains the distances between the cities."));
    72       Parameters.Add(new LookupParameter<BoolValue>("UseDistanceMatrix", "True if a distance matrix should be calculated (if it does not exist already) and used for evaluation, otherwise false."));
    73       Parameters.Add(new ValueParameter<ItemList<ItemList<IntValue>>>("Realizations", "The concrete..."));
    7443      Parameters.Add(new LookupParameter<TwoPointFiveMove>("TwoPointFiveMove", "The move to evaluate."));
    75       Parameters.Add(new LookupParameter<DoubleValue>("Quality", "The quality of a TSP solution."));
    76       Parameters.Add(new LookupParameter<DoubleValue>("MoveQuality", "The evaluated quality of a move on a TSP solution."));
    7744    }
    7845
    7946    public override IDeepCloneable Clone(Cloner cloner) {
    80       return new PTSP25MoveEvaluator(this, cloner);
     47      return new PTSPTwoPointFiveMoveEvaluator(this, cloner);
    8148    }
    8249
    83     [StorableHook(HookType.AfterDeserialization)]
    84     private void AfterDeserialization() {
    85       // BackwardsCompatibility3.3
    86       #region Backwards compatible code (remove with 3.4)
    87       LookupParameter<DoubleMatrix> oldDistanceMatrixParameter = Parameters["DistanceMatrix"] as LookupParameter<DoubleMatrix>;
    88       if (oldDistanceMatrixParameter != null) {
    89         Parameters.Remove(oldDistanceMatrixParameter);
    90         Parameters.Add(new LookupParameter<DistanceMatrix>("DistanceMatrix", "The matrix which contains the distances between the cities."));
    91         DistanceMatrixParameter.ActualName = oldDistanceMatrixParameter.ActualName;
    92       }
    93       #endregion
     50    protected override double EvaluateByCoordinates(Permutation permutation, DoubleMatrix coordinates, DistanceCalculator distanceCalculator) {
     51      var move = TwoPointFiveMoveParameter.ActualValue;
     52      var realizations = RealizationsParameter.ActualValue;
     53      return EvaluateByCoordinates(permutation, coordinates, distanceCalculator, move, realizations);
    9454    }
    9555
    96     public override IOperation Apply() {
    97       Permutation permutation = PermutationParameter.ActualValue;
    98       DoubleMatrix coordinates = CoordinatesParameter.ActualValue;
    99       double relativeQualityDifference = 0;
    100       if (UseDistanceMatrixParameter.ActualValue.Value) {
    101         DistanceMatrix distanceMatrix = DistanceMatrixParameter.ActualValue;
    102         if (distanceMatrix == null) {
    103           if (coordinates == null) throw new InvalidOperationException("Neither a distance matrix nor coordinates were given.");
    104           distanceMatrix = CalculateDistanceMatrix(coordinates);
    105           DistanceMatrixParameter.ActualValue = distanceMatrix;
    106         }
    107         relativeQualityDifference = EvaluateByDistanceMatrix(permutation, distanceMatrix);
    108       }
    109       DoubleValue moveQuality = MoveQualityParameter.ActualValue;
    110       if (moveQuality == null) MoveQualityParameter.ActualValue = new DoubleValue(QualityParameter.ActualValue.Value + relativeQualityDifference);
    111       else moveQuality.Value = QualityParameter.ActualValue.Value + relativeQualityDifference;
    112       return base.Apply();
     56    public static double EvaluateByCoordinates(Permutation permutation, DoubleMatrix coordinates, DistanceCalculator distanceCalculator, TwoPointFiveMove move, ItemList<BoolArray> realizations) {
     57      if (move.IsInvert) {
     58        return PTSPEstimatedInversionMoveEvaluator.EvaluateByCoordinates(permutation,
     59          new InversionMove(move.Index1, move.Index2, move.Permutation),
     60          coordinates, distanceCalculator, realizations);
     61      } else {
     62        return PTSPEstimatedInsertionMoveEvaluator.EvaluateByCoordinates(permutation,
     63          new TranslocationMove(move.Index1, move.Index1, move.Index2),
     64          coordinates, distanceCalculator, realizations);
     65      }
    11366    }
    11467
    115     protected double CalculateDistance(double x1, double y1, double x2, double y2) {
    116       return Math.Round(Math.Sqrt((x1 - x2) * (x1 - x2) + (y1 - y2) * (y1 - y2)));
     68    protected override double EvaluateByDistanceMatrix(Permutation permutation, DistanceMatrix distanceMatrix) {
     69      var move = TwoPointFiveMoveParameter.ActualValue;
     70      var realizations = RealizationsParameter.ActualValue;
     71      return EvaluateByDistanceMatrix(permutation, distanceMatrix, move, realizations);
    11772    }
    11873
    119     private static int decreaseCircularIndex(int length, int index) {
    120       int result = index - 1;
    121       if (result == -1) {
    122         result = length - 1;
     74    public static double EvaluateByDistanceMatrix(Permutation permutation, DistanceMatrix distanceMatrix, TwoPointFiveMove move, ItemList<BoolArray> realizations) {
     75      if (move.IsInvert) {
     76        return PTSPEstimatedInversionMoveEvaluator.EvaluateByDistanceMatrix(permutation,
     77          new InversionMove(move.Index1, move.Index2, move.Permutation),
     78          distanceMatrix, realizations);
     79      } else {
     80        return PTSPEstimatedInsertionMoveEvaluator.EvaluateByDistanceMatrix(permutation,
     81          new TranslocationMove(move.Index1, move.Index1, move.Index2),
     82          distanceMatrix, realizations);
    12383      }
    124       return result;
    125     }
    126 
    127     private static int increaseCircularIndex(int length, int index) {
    128       int result = index + 1;
    129       if (result == length + 1) {
    130         result = 0;
    131       }
    132       return result;
    133     }
    134    
    135 
    136     public static double EvaluateInversionByDistanceMatrix(Permutation permutation, TwoPointFiveMove move, DistanceMatrix distanceMatrix, ItemList<ItemList<IntValue>> realizations) {
    137       double moveQuality = 0;
    138       int[] edges = new int[4];
    139       int[] indices = new int[4];
    140       edges[0] = permutation.GetCircular(move.Index1 - 1);
    141       indices[0] = decreaseCircularIndex(permutation.Length, move.Index1);
    142       edges[1] = permutation[move.Index1];
    143       indices[1] = move.Index1;
    144       edges[2] = permutation[move.Index2];
    145       indices[2] = move.Index2;
    146       edges[3] = permutation.GetCircular(move.Index2 + 1);
    147       indices[3] = increaseCircularIndex(permutation.Length, move.Index2);
    148       int[] aPosteriori = new int[4];
    149       foreach (ItemList<IntValue> realization in realizations) {
    150         for (int i = 0; i < edges.Length; i++) {
    151           if (realization[edges[i]].Value == 1) {
    152             aPosteriori[i] = edges[i];
    153           } else {
    154             int j = 1;
    155             if (i % 2 == 0) {
    156               // find nearest predecessor in realization if source edge
    157               while (realization[permutation.GetCircular(indices[i] - j)].Value == 0) {
    158                 j++;
    159               }
    160               aPosteriori[i] = permutation.GetCircular(indices[i] - j);
    161             } else {
    162               // find nearest successor in realization if target edge
    163               while (realization[permutation.GetCircular(indices[i] + j)].Value == 0) {
    164                 j++;
    165               }
    166               aPosteriori[i] = permutation.GetCircular(indices[i] + j);
    167             }
    168           }
    169         }
    170         // compute cost difference between the two a posteriori solutions
    171         if (!(aPosteriori[0] == aPosteriori[2] && aPosteriori[1] == aPosteriori[3])) {
    172           moveQuality = moveQuality + distanceMatrix[aPosteriori[0], aPosteriori[2]] + distanceMatrix[aPosteriori[1], aPosteriori[3]] - distanceMatrix[aPosteriori[0], aPosteriori[1]] - distanceMatrix[aPosteriori[2], aPosteriori[3]];
    173         }
    174         Array.Clear(aPosteriori, 0, aPosteriori.Length);
    175       }
    176       // return average of cost differences
    177       return moveQuality / realizations.Count;
    178     }
    179     public static double EvaluateInsertionByDistanceMatrix(Permutation permutation, TwoPointFiveMove move, DistanceMatrix distanceMatrix, ItemList<ItemList<IntValue>> realizations) {
    180       Permutation afterMove = new Permutation(PermutationTypes.RelativeUndirected, permutation);
    181       TranslocationManipulator.Apply(afterMove, move.Index1, move.Index1, move.Index2);
    182       double moveQuality = 0;
    183       int[] edges = new int[12];
    184       int[] indices = new int[12];
    185       edges[0] = permutation.GetCircular(move.Index1 - 1);
    186       indices[0] = decreaseCircularIndex(permutation.Length, move.Index1);
    187       edges[1] = permutation[move.Index1];
    188       indices[1] = move.Index1;
    189       edges[2] = permutation[move.Index1];
    190       indices[2] = move.Index1;
    191       edges[3] = permutation.GetCircular(move.Index1 + 1);
    192       indices[3] = increaseCircularIndex(permutation.Length, move.Index1);
    193 
    194       edges[6] = afterMove.GetCircular(move.Index2 - 1);
    195       indices[6] = decreaseCircularIndex(afterMove.Length, move.Index2);
    196       edges[7] = afterMove[move.Index2];
    197       indices[7] = move.Index2;
    198       edges[8] = afterMove[move.Index2];
    199       indices[8] = move.Index2;
    200       edges[9] = afterMove.GetCircular(move.Index2 + 1);
    201       indices[9] = increaseCircularIndex(afterMove.Length, move.Index2);
    202 
    203       if (move.Index2 > move.Index1) {
    204         edges[4] = permutation[move.Index2];
    205         indices[4] = move.Index2;
    206         edges[5] = permutation.GetCircular(move.Index2 + 1);
    207         indices[5] = indices[9];
    208         edges[10] = afterMove.GetCircular(move.Index1 - 1);
    209         indices[10] = indices[0];
    210         edges[11] = afterMove[move.Index1];
    211         indices[11] = move.Index1;
    212       } else {
    213         edges[4] = permutation.GetCircular(move.Index2 - 1);
    214         indices[4] = indices[6];
    215         edges[5] = permutation[move.Index2];
    216         indices[5] = move.Index2;
    217         edges[10] = afterMove[move.Index1];
    218         indices[10] = move.Index1;
    219         edges[11] = afterMove.GetCircular(move.Index1 + 1);
    220         indices[11] = indices[3];
    221       }
    222       int[] aPosteriori = new int[12];
    223       Permutation tempPermutation;
    224       foreach (ItemList<IntValue> realization in realizations) {
    225         for (int i = 0; i < edges.Length; i++) {
    226           if (i < 6) {
    227             tempPermutation = permutation;
    228           } else {
    229             tempPermutation = afterMove;
    230           }
    231           if (realization[edges[i]].Value == 1) {
    232             aPosteriori[i] = edges[i];
    233           } else {
    234             int j = 1;
    235             if (i % 2 == 0) {
    236               // find nearest predecessor in realization if source edge
    237               while (realization[tempPermutation.GetCircular(indices[i] - j)].Value == 0) {
    238                 j++;
    239               }
    240               aPosteriori[i] = tempPermutation.GetCircular(indices[i] - j);
    241             } else {
    242               // find nearest successor in realization if target edge
    243               while (realization[tempPermutation.GetCircular(indices[i] + j)].Value == 0) {
    244                 j++;
    245               }
    246               aPosteriori[i] = tempPermutation.GetCircular(indices[i] + j);
    247             }
    248           }
    249         }
    250         if (!(aPosteriori[0] == aPosteriori[2] && aPosteriori[1] == aPosteriori[3]) &&
    251           !(aPosteriori[0] == aPosteriori[4] && aPosteriori[1] == aPosteriori[5]) &&
    252           !(aPosteriori[2] == aPosteriori[4] && aPosteriori[3] == aPosteriori[5])) {
    253           // compute cost difference between the two a posteriori solutions
    254           moveQuality = moveQuality + distanceMatrix[aPosteriori[6], aPosteriori[7]] + distanceMatrix[aPosteriori[8], aPosteriori[9]] + distanceMatrix[aPosteriori[10], aPosteriori[11]];
    255           moveQuality = moveQuality - distanceMatrix[aPosteriori[0], aPosteriori[1]] - distanceMatrix[aPosteriori[2], aPosteriori[3]] - distanceMatrix[aPosteriori[4], aPosteriori[5]];
    256         }
    257         Array.Clear(aPosteriori, 0, aPosteriori.Length);
    258       }
    259       // return average of cost differences
    260       return moveQuality / realizations.Count;
    261     }
    262     protected double EvaluateByDistanceMatrix(Permutation permutation, DistanceMatrix distanceMatrix) {
    263       TwoPointFiveMove currentMove = TwoPointFiveMoveParameter.ActualValue;
    264       if (currentMove.IsInvert) {
    265         return EvaluateInversionByDistanceMatrix(permutation, currentMove, distanceMatrix, RealizationsParameter.Value);
    266       } else {
    267         return EvaluateInsertionByDistanceMatrix(permutation, currentMove, distanceMatrix, RealizationsParameter.Value);
    268       }
    269     }
    270 
    271     private DistanceMatrix CalculateDistanceMatrix(DoubleMatrix c) {
    272       DistanceMatrix distanceMatrix = new DistanceMatrix(c.Rows, c.Rows);
    273       for (int i = 0; i < distanceMatrix.Rows; i++) {
    274         for (int j = 0; j < distanceMatrix.Columns; j++)
    275           distanceMatrix[i, j] = CalculateDistance(c[i, 0], c[i, 1], c[j, 0], c[j, 1]);
    276       }
    277       return (DistanceMatrix)distanceMatrix.AsReadOnly();
    27884    }
    27985  }
Note: See TracChangeset for help on using the changeset viewer.