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"); } }
public void ScrambleManipulatorApplyTest() { TestRandom random = new TestRandom(); Permutation parent, expected; // The following test is based on an example from Larranaga, P. et al. 1999. Genetic Algorithms for the Travelling Salesman Problem: A Review of Representations and Operators. Artificial Intelligence Review, 13 random.Reset(); random.IntNumbers = new int[] { 3, 6, 1, 1, 1, 0 }; parent = new Permutation(PermutationTypes.RelativeUndirected, new int[] { 0, 1, 2, 3, 4, 5, 6, 7 }); Assert.IsTrue(parent.Validate()); expected = new Permutation(PermutationTypes.RelativeUndirected, new int[] { 0, 1, 2, 4, 5, 6, 3, 7 }); Assert.IsTrue(expected.Validate()); ScrambleManipulator.Apply(random, parent); Assert.IsTrue(parent.Validate()); Assert.IsTrue(Auxiliary.PermutationIsEqualByPosition(expected, parent)); }