public static void Improve(IRandom random, Permutation assignment, DoubleMatrix weights, DoubleMatrix distances, DoubleValue quality, IntValue localIterations, IntValue evaluatedSolutions, bool maximization, int maxIterations, int neighborhoodSize, CancellationToken cancellation) { for (int i = localIterations.Value; i < maxIterations; i++) { ScrambleMove bestMove = null; double bestQuality = 0; // we have to make an improvement, so 0 is the baseline double evaluations = 0.0; for (int j = 0; j < neighborhoodSize; j++) { var move = StochasticScrambleMultiMoveGenerator.GenerateRandomMove(assignment, random); double moveQuality = QAPScrambleMoveEvaluator.Apply(assignment, move, weights, distances); evaluations += 2.0 * move.ScrambledIndices.Length / assignment.Length; if (maximization && moveQuality > bestQuality || !maximization && moveQuality < bestQuality) { bestQuality = moveQuality; bestMove = move; } } evaluatedSolutions.Value += (int)Math.Ceiling(evaluations); if (bestMove == null) { break; } ScrambleManipulator.Apply(assignment, bestMove.StartIndex, bestMove.ScrambledIndices); quality.Value += bestQuality; localIterations.Value++; cancellation.ThrowIfCancellationRequested(); } }
public void ScrambleMoveEvaluatorTest() { for (int i = 0; i < 500; i++) { ScrambleMove scramble = StochasticScrambleMultiMoveGenerator.GenerateRandomMove(assignment, random); // SYMMETRIC MATRICES double before = QAPEvaluator.Apply(assignment, symmetricWeights, symmetricDistances); double move = QAPScrambleMoveEvaluator.Apply(assignment, scramble, symmetricWeights, symmetricDistances); ScrambleManipulator.Apply(assignment, scramble.StartIndex, scramble.ScrambledIndices); double after = QAPEvaluator.Apply(assignment, symmetricWeights, symmetricDistances); Assert.IsTrue(move.IsAlmost(after - before), "Failed on symmetric matrices"); // ASYMMETRIC MATRICES before = QAPEvaluator.Apply(assignment, asymmetricWeights, asymmetricDistances); move = QAPScrambleMoveEvaluator.Apply(assignment, scramble, asymmetricWeights, asymmetricDistances); ScrambleManipulator.Apply(assignment, scramble.StartIndex, scramble.ScrambledIndices); after = QAPEvaluator.Apply(assignment, asymmetricWeights, asymmetricDistances); Assert.IsTrue(move.IsAlmost(after - before), "Failed on asymmetric matrices"); // NON-ZERO DIAGONAL ASYMMETRIC MATRICES before = QAPEvaluator.Apply(assignment, nonZeroDiagonalWeights, nonZeroDiagonalDistances); move = QAPScrambleMoveEvaluator.Apply(assignment, scramble, nonZeroDiagonalWeights, nonZeroDiagonalDistances); ScrambleManipulator.Apply(assignment, scramble.StartIndex, scramble.ScrambledIndices); after = QAPEvaluator.Apply(assignment, nonZeroDiagonalWeights, nonZeroDiagonalDistances); Assert.IsTrue(move.IsAlmost(after - before), "Failed on non-zero diagonal matrices"); } }