Free cookie consent management tool by TermsFeed Policy Generator

Ignore:
Timestamp:
07/22/11 12:03:36 (13 years ago)
Author:
abeham
Message:

#1541

  • Updated code to reflect what Eric Taillard's code does at http://mistic.heig-vd.ch/taillard/codes.dir/tabou_qap.cpp which is however not quite what is described in the paper.
  • Updated the swap2 move evaluator to perform move evaluations in O(1) for several cases by memorizing the move quality of the previous iteration
  • Added a unit test to test the new faster evaluation
  • Changed the robust taboo search to use this faster evaluation
  • Renamed some operators (dropping the QAP pre- and postfix)
Location:
branches/QAPAlgorithms/HeuristicLab.Problems.QuadraticAssignment/3.3
Files:
2 edited

Legend:

Unmodified
Added
Removed
  • branches/QAPAlgorithms/HeuristicLab.Problems.QuadraticAssignment/3.3/Evaluators/QAPSwap2MoveEvaluator.cs

    r5933 r6586  
    4949    }
    5050
     51    /// <summary>
     52    /// Calculates the quality of the move <paramref name="move"/> by evaluating the changes.
     53    /// The runtime complexity of this method is O(N) with N being the size of the permutation.
     54    /// </summary>
     55    /// <param name="assignment">The current permutation.</param>
     56    /// <param name="move">The move that is to be evaluated if it was applied to the current permutation.</param>
     57    /// <param name="weights">The weights matrix.</param>
     58    /// <param name="distances">The distances matrix.</param>
     59    /// <returns>The relative change in quality if <paramref name="move"/> was applied to <paramref name="assignment"/>.</returns>
    5160    public static double Apply(Permutation assignment, Swap2Move move, DoubleMatrix weights, DoubleMatrix distances) {
    5261      if (move.Index1 == move.Index2) return 0;
     
    7382    }
    7483
     84    /// <summary>
     85    /// Is able to compute the move qualities faster O(1) in some cases if it knows the quality of
     86    /// performing the move <paramref name="move"/> previously. In other cases it performs a
     87    /// standard move quality calculation with runtime complexity O(N).
     88    /// </summary>
     89    /// <remarks>
     90    /// The number of cases that the calculation can be performed faster grows with N^2
     91    /// while the number of cases which require a larger recalculation grows linearly with N.
     92    /// Larger problem instances thus benefit from this faster method to a larger degree.
     93    /// </remarks>
     94    /// <param name="assignment">The current permutation.</param>
     95    /// <param name="move">The current move that is to be evaluated.</param>
     96    /// <param name="previousQuality">The quality of that move as evaluated for the previous permutation.</param>
     97    /// <param name="weights">The weigths matrix.</param>
     98    /// <param name="distances">The distances matrix.</param>
     99    /// <param name="lastMove">The move that was applied to transform the permutation from the previous to the current one.</param>
     100    /// <returns>The relative change in quality if <paramref name="move"/> was applied to <paramref name="assignment"/>.</returns>
     101    public static double Apply(Permutation assignment, Swap2Move move, double previousQuality,
     102      DoubleMatrix weights, DoubleMatrix distances, Swap2Move lastMove) {
     103      bool overlapsLastMove = move.Index1 == lastMove.Index1
     104                           || move.Index2 == lastMove.Index1
     105                           || move.Index1 == lastMove.Index2
     106                           || move.Index2 == lastMove.Index2;
     107
     108      if (!overlapsLastMove) {
     109        int r = lastMove.Index1, u = move.Index1, s = lastMove.Index2, v = move.Index2;
     110        int pR = assignment[lastMove.Index1], pU = assignment[move.Index1], pS = assignment[lastMove.Index2], pV = assignment[move.Index2];
     111
     112        return previousQuality
     113          + (weights[r, u] - weights[r, v] + weights[s, v] - weights[s, u])
     114            * (distances[pS, pU] - distances[pS, pV] + distances[pR, pV] - distances[pR, pU])
     115          + (weights[u, r] - weights[v, r] + weights[v, s] - weights[u, s])
     116            * (distances[pU, pS] - distances[pV, pS] + distances[pV, pR] - distances[pU, pR]);
     117      } else {
     118        return Apply(assignment, move, weights, distances);
     119      }
     120    }
     121
    75122    public override IOperation Apply() {
    76123      Swap2Move move = Swap2MoveParameter.ActualValue;
  • branches/QAPAlgorithms/HeuristicLab.Problems.QuadraticAssignment/3.3/Tests/QAPMoveEvaluatorTest.cs

    r5933 r6586  
    6060      for (int i = 0; i < ProblemSize - 1; i++) {
    6161        for (int j = i + 1; j < ProblemSize; j++) {
    62           symmetricDistances[i, j] = random.Next(ProblemSize);
     62          symmetricDistances[i, j] = random.Next(ProblemSize * 100);
    6363          symmetricDistances[j, i] = symmetricDistances[i, j];
    64           symmetricWeights[i, j] = random.Next(ProblemSize);
     64          symmetricWeights[i, j] = random.Next(ProblemSize * 100);
    6565          symmetricWeights[j, i] = symmetricWeights[i, j];
    66           asymmetricDistances[i, j] = random.Next(ProblemSize);
    67           asymmetricDistances[j, i] = random.Next(ProblemSize);
    68           asymmetricWeights[i, j] = random.Next(ProblemSize);
    69           asymmetricWeights[j, i] = random.Next(ProblemSize);
    70           nonZeroDiagonalDistances[i, j] = random.Next(ProblemSize);
    71           nonZeroDiagonalDistances[j, i] = random.Next(ProblemSize);
    72           nonZeroDiagonalWeights[i, j] = random.Next(ProblemSize);
    73           nonZeroDiagonalWeights[j, i] = random.Next(ProblemSize);
     66          asymmetricDistances[i, j] = random.Next(ProblemSize * 100);
     67          asymmetricDistances[j, i] = random.Next(ProblemSize * 100);
     68          asymmetricWeights[i, j] = random.Next(ProblemSize * 100);
     69          asymmetricWeights[j, i] = random.Next(ProblemSize * 100);
     70          nonZeroDiagonalDistances[i, j] = random.Next(ProblemSize * 100);
     71          nonZeroDiagonalDistances[j, i] = random.Next(ProblemSize * 100);
     72          nonZeroDiagonalWeights[i, j] = random.Next(ProblemSize * 100);
     73          nonZeroDiagonalWeights[j, i] = random.Next(ProblemSize * 100);
    7474        }
    75         nonZeroDiagonalDistances[i, i] = random.Next(ProblemSize);
    76         nonZeroDiagonalWeights[i, i] = random.Next(ProblemSize);
     75        nonZeroDiagonalDistances[i, i] = random.Next(ProblemSize * 100);
     76        nonZeroDiagonalWeights[i, i] = random.Next(ProblemSize * 100);
    7777      }
    7878      int index = random.Next(ProblemSize);
    7979      if (nonZeroDiagonalDistances[index, index] == 0)
    80         nonZeroDiagonalDistances[index, index] = random.Next(1, ProblemSize);
     80        nonZeroDiagonalDistances[index, index] = random.Next(1, ProblemSize * 100);
    8181      index = random.Next(ProblemSize);
    8282      if (nonZeroDiagonalWeights[index, index] == 0)
    83         nonZeroDiagonalWeights[index, index] = random.Next(1, ProblemSize);
     83        nonZeroDiagonalWeights[index, index] = random.Next(1, ProblemSize * 100);
    8484      assignment = new Permutation(PermutationTypes.Absolute, ProblemSize, random);
     85    }
     86
     87    [TestMethod]
     88    public void Swap2MoveEvaluatorFastEvaluationTest() {
     89
     90      for (int i = 0; i < 500; i++) {
     91        Swap2Move lastMove = new Swap2Move(random.Next(ProblemSize), random.Next(ProblemSize));
     92        Permutation prevAssignment = (Permutation)assignment.Clone();
     93        Swap2Manipulator.Apply(assignment, lastMove.Index1, lastMove.Index2);
     94        Permutation nextAssignment = (Permutation)assignment.Clone();
     95        Swap2Move currentMove = new Swap2Move(random.Next(ProblemSize), random.Next(ProblemSize));
     96        Swap2Manipulator.Apply(nextAssignment, currentMove.Index1, currentMove.Index2);
     97
     98        double moveBefore = QAPSwap2MoveEvaluator.Apply(prevAssignment, currentMove, symmetricWeights, symmetricDistances);
     99        double moveAfter = QAPSwap2MoveEvaluator.Apply(assignment, currentMove,
     100                moveBefore, symmetricWeights, symmetricDistances, lastMove);
     101        double before = QAPEvaluator.Apply(assignment, symmetricWeights, symmetricDistances);
     102        double after = QAPEvaluator.Apply(nextAssignment, symmetricWeights, symmetricDistances);
     103
     104        Assert.IsTrue(moveAfter.IsAlmost(after - before), "Failed on symmetric matrices: " + Environment.NewLine
     105          + "Quality changed from " + before + " to " + after + " (" + (after - before).ToString() + "), but move quality change was " + moveAfter + ".");
     106
     107        moveBefore = QAPSwap2MoveEvaluator.Apply(prevAssignment, currentMove, asymmetricWeights, asymmetricDistances);
     108        moveAfter = QAPSwap2MoveEvaluator.Apply(assignment, currentMove,
     109                moveBefore, asymmetricWeights, asymmetricDistances, lastMove);
     110        before = QAPEvaluator.Apply(assignment, asymmetricWeights, asymmetricDistances);
     111        after = QAPEvaluator.Apply(nextAssignment, asymmetricWeights, asymmetricDistances);
     112
     113        Assert.IsTrue(moveAfter.IsAlmost(after - before), "Failed on asymmetric matrices: " + Environment.NewLine
     114          + "Quality changed from " + before + " to " + after + " (" + (after - before).ToString() + "), but move quality change was " + moveAfter + ".");
     115
     116        moveBefore = QAPSwap2MoveEvaluator.Apply(prevAssignment, currentMove, nonZeroDiagonalWeights, nonZeroDiagonalDistances);
     117        moveAfter = QAPSwap2MoveEvaluator.Apply(assignment, currentMove,
     118                moveBefore, nonZeroDiagonalWeights, nonZeroDiagonalDistances, lastMove);
     119        before = QAPEvaluator.Apply(assignment, nonZeroDiagonalWeights, nonZeroDiagonalDistances);
     120        after = QAPEvaluator.Apply(nextAssignment, nonZeroDiagonalWeights, nonZeroDiagonalDistances);
     121
     122        Assert.IsTrue(moveAfter.IsAlmost(after - before), "Failed on non-zero diagonal matrices: " + Environment.NewLine
     123          + "Quality changed from " + before + " to " + after + " (" + (after - before).ToString() + "), but move quality change was " + moveAfter + ".");
     124      }
    85125    }
    86126
Note: See TracChangeset for help on using the changeset viewer.