public void Swap2MoveEvaluatorTest() { for (int i = 0; i < 500; i++) { int index1 = random.Next(ProblemSize); int index2 = random.Next(ProblemSize); // SYMMETRIC MATRICES double before = QAPEvaluator.Apply(assignment, symmetricWeights, symmetricDistances); Swap2Manipulator.Apply(assignment, index1, index2); double after = QAPEvaluator.Apply(assignment, symmetricWeights, symmetricDistances); double move = QAPSwap2MoveEvaluator.Apply(assignment, new Swap2Move(index1, index2, assignment), symmetricWeights, symmetricDistances); Assert.IsTrue(move.IsAlmost(before - after), "Failed on symmetric matrices"); // ASYMMETRIC MATRICES before = QAPEvaluator.Apply(assignment, asymmetricWeights, asymmetricDistances); Permutation clone = (Permutation)assignment.Clone(); Swap2Manipulator.Apply(assignment, index1, index2); after = QAPEvaluator.Apply(assignment, asymmetricWeights, asymmetricDistances); move = QAPSwap2MoveEvaluator.Apply(clone, new Swap2Move(index1, index2), asymmetricWeights, asymmetricDistances); Assert.IsTrue(move.IsAlmost(after - before), "Failed on asymmetric matrices"); // NON-ZERO DIAGONAL ASSYMETRIC MATRICES before = QAPEvaluator.Apply(assignment, nonZeroDiagonalWeights, nonZeroDiagonalDistances); clone = (Permutation)assignment.Clone(); Swap2Manipulator.Apply(assignment, index1, index2); after = QAPEvaluator.Apply(assignment, nonZeroDiagonalWeights, nonZeroDiagonalDistances); move = QAPSwap2MoveEvaluator.Apply(clone, new Swap2Move(index1, index2), nonZeroDiagonalWeights, nonZeroDiagonalDistances); Assert.IsTrue(move.IsAlmost(after - before), "Failed on non-zero diagonal matrices"); } }
public void Swap2MoveEvaluatorFastEvaluationTest() { for (int i = 0; i < 500; i++) { Swap2Move lastMove = new Swap2Move(random.Next(ProblemSize), random.Next(ProblemSize)); Permutation prevAssignment = (Permutation)assignment.Clone(); Swap2Manipulator.Apply(assignment, lastMove.Index1, lastMove.Index2); Permutation nextAssignment = (Permutation)assignment.Clone(); Swap2Move currentMove = new Swap2Move(random.Next(ProblemSize), random.Next(ProblemSize)); Swap2Manipulator.Apply(nextAssignment, currentMove.Index1, currentMove.Index2); double moveBefore = QAPSwap2MoveEvaluator.Apply(prevAssignment, currentMove, symmetricWeights, symmetricDistances); double moveAfter = QAPSwap2MoveEvaluator.Apply(assignment, currentMove, moveBefore, symmetricWeights, symmetricDistances, lastMove); double before = QAPEvaluator.Apply(assignment, symmetricWeights, symmetricDistances); double after = QAPEvaluator.Apply(nextAssignment, symmetricWeights, symmetricDistances); Assert.IsTrue(moveAfter.IsAlmost(after - before), "Failed on symmetric matrices: " + Environment.NewLine + "Quality changed from " + before + " to " + after + " (" + (after - before).ToString() + "), but move quality change was " + moveAfter + "."); moveBefore = QAPSwap2MoveEvaluator.Apply(prevAssignment, currentMove, asymmetricWeights, asymmetricDistances); moveAfter = QAPSwap2MoveEvaluator.Apply(assignment, currentMove, moveBefore, asymmetricWeights, asymmetricDistances, lastMove); before = QAPEvaluator.Apply(assignment, asymmetricWeights, asymmetricDistances); after = QAPEvaluator.Apply(nextAssignment, asymmetricWeights, asymmetricDistances); Assert.IsTrue(moveAfter.IsAlmost(after - before), "Failed on asymmetric matrices: " + Environment.NewLine + "Quality changed from " + before + " to " + after + " (" + (after - before).ToString() + "), but move quality change was " + moveAfter + "."); moveBefore = QAPSwap2MoveEvaluator.Apply(prevAssignment, currentMove, nonZeroDiagonalWeights, nonZeroDiagonalDistances); moveAfter = QAPSwap2MoveEvaluator.Apply(assignment, currentMove, moveBefore, nonZeroDiagonalWeights, nonZeroDiagonalDistances, lastMove); before = QAPEvaluator.Apply(assignment, nonZeroDiagonalWeights, nonZeroDiagonalDistances); after = QAPEvaluator.Apply(nextAssignment, nonZeroDiagonalWeights, nonZeroDiagonalDistances); Assert.IsTrue(moveAfter.IsAlmost(after - before), "Failed on non-zero diagonal matrices: " + Environment.NewLine + "Quality changed from " + before + " to " + after + " (" + (after - before).ToString() + "), but move quality change was " + moveAfter + "."); } }
public override IOperation Apply() { IRandom random = RandomParameter.ActualValue; int iteration = IterationsParameter.ActualValue.Value; IntMatrix shortTermMemory = ShortTermMemoryParameter.ActualValue; DoubleMatrix weights = WeightsParameter.ActualValue; DoubleMatrix distances = DistancesParameter.ActualValue; DoubleMatrix moveQualityMatrix = MoveQualityMatrixParameter.ActualValue; DoubleValue quality = QualityParameter.ActualValue; DoubleValue bestQuality = BestQualityParameter.ActualValue; if (bestQuality == null) { BestQualityParameter.ActualValue = (DoubleValue)quality.Clone(); bestQuality = BestQualityParameter.ActualValue; } bool allMovesTabu = false; if (AllMovesTabuParameter.ActualValue == null) { AllMovesTabuParameter.ActualValue = new BoolValue(false); } else { allMovesTabu = AllMovesTabuParameter.ActualValue.Value; } int minTenure = MinimumTabuTenureParameter.ActualValue.Value; int maxTenure = MaximumTabuTenureParameter.ActualValue.Value; int alternativeAspirationTenure = AlternativeAspirationTenureParameter.ActualValue.Value; bool useAlternativeAspiration = UseAlternativeAspirationParameter.ActualValue.Value; Permutation solution = PermutationParameter.ActualValue; Swap2Move lastMove = LastMoveParameter.ActualValue; double bestMoveQuality = double.MaxValue; Swap2Move bestMove = null; bool already_aspired = false; double evaluations = EvaluatedSolutionEquivalentsParameter.ActualValue.Value; foreach (Swap2Move move in ExhaustiveSwap2MoveGenerator.Generate(solution)) { double moveQuality; if (lastMove == null) { moveQuality = QAPSwap2MoveEvaluator.Apply(solution, move, weights, distances); evaluations += 4.0 / solution.Length; } else if (allMovesTabu) { moveQuality = moveQualityMatrix[move.Index1, move.Index2]; } else { moveQuality = QAPSwap2MoveEvaluator.Apply(solution, move, moveQualityMatrix[move.Index1, move.Index2], weights, distances, lastMove); if (move.Index1 == lastMove.Index1 || move.Index2 == lastMove.Index1 || move.Index1 == lastMove.Index2 || move.Index2 == lastMove.Index2) { evaluations += 4.0 / solution.Length; } else { evaluations += 2.0 / (solution.Length * solution.Length); } } moveQualityMatrix[move.Index1, move.Index2] = moveQuality; moveQualityMatrix[move.Index2, move.Index1] = moveQuality; bool autorized = shortTermMemory[move.Index1, solution[move.Index2]] < iteration || shortTermMemory[move.Index2, solution[move.Index1]] < iteration; bool aspired = (shortTermMemory[move.Index1, solution[move.Index2]] < iteration - alternativeAspirationTenure && shortTermMemory[move.Index2, solution[move.Index1]] < iteration - alternativeAspirationTenure) || quality.Value + moveQuality < bestQuality.Value; if ((aspired && !already_aspired) || // the first alternative move is aspired (aspired && already_aspired && moveQuality < bestMoveQuality) || // an alternative move was already aspired, but this is better (autorized && !aspired && !already_aspired && moveQuality < bestMoveQuality)) // a regular better move is found { bestMove = move; bestMoveQuality = moveQuality; if (aspired) { already_aspired = true; } } } ResultCollection results = ResultsParameter.ActualValue; if (results != null) { IntValue aspiredMoves = null; if (!results.ContainsKey("AspiredMoves")) { aspiredMoves = new IntValue(already_aspired ? 1 : 0); results.Add(new Result("AspiredMoves", "Counts the number of moves that were selected because of the aspiration criteria.", aspiredMoves)); } else if (already_aspired) { aspiredMoves = (IntValue)results["AspiredMoves"].Value; aspiredMoves.Value++; } } EvaluatedSolutionEquivalentsParameter.ActualValue.Value = evaluations; EvaluatedSolutionsParameter.ActualValue.Value = (int)Math.Ceiling(evaluations); allMovesTabu = bestMove == null; if (!allMovesTabu) { LastMoveParameter.ActualValue = bestMove; } AllMovesTabuParameter.ActualValue.Value = allMovesTabu; if (allMovesTabu) { return(base.Apply()); } bool useNewAdaptionScheme = UseNewTabuTenureAdaptionSchemeParameter.ActualValue.Value; if (useNewAdaptionScheme) { double r = random.NextDouble(); if (r == 0) { r = 1; // transform to (0;1] } shortTermMemory[bestMove.Index1, solution[bestMove.Index1]] = (int)(iteration + r * r * r * maxTenure); r = random.NextDouble(); if (r == 0) { r = 1; // transform to (0;1] } shortTermMemory[bestMove.Index2, solution[bestMove.Index2]] = (int)(iteration + r * r * r * maxTenure); } else { shortTermMemory[bestMove.Index1, solution[bestMove.Index1]] = iteration + random.Next(minTenure, maxTenure); shortTermMemory[bestMove.Index2, solution[bestMove.Index2]] = iteration + random.Next(minTenure, maxTenure); } Swap2Manipulator.Apply(solution, bestMove.Index1, bestMove.Index2); quality.Value += bestMoveQuality; if (quality.Value < bestQuality.Value) { bestQuality.Value = quality.Value; } return(base.Apply()); }