public override IOperation Apply() { var solution = CurrentScope.Variables[SolutionParameter.ActualName].Value as Permutation; if (solution == null) { throw new ArgumentException("Cannot improve solution because it has the wrong type."); } if (solution.PermutationType != PermutationTypes.RelativeUndirected) { throw new ArgumentException("Cannot improve solution because the permutation type is not supported."); } for (int i = 0; i < ImprovementAttempts.Value; i++) { var move = StochasticInversionSingleMoveGenerator.Apply(solution, Random); double moveQualtiy = TSPInversionMovePathEvaluator.EvaluateByDistanceMatrix(solution, move, DistanceMatrix); if (moveQualtiy < 0) { InversionManipulator.Apply(solution, move.Index1, move.Index2); } } CurrentScope.Variables.Add(new Variable("LocalEvaluatedSolutions", ImprovementAttempts)); return(base.Apply()); }
public static void Improve(Permutation assignment, DoubleMatrix distances, DoubleValue quality, IntValue localIterations, IntValue evaluatedSolutions, bool maximization, int maxIterations, DoubleArray probabilities, CancellationToken cancellation) { var distanceM = (DistanceMatrix)distances; Func <int, int, double> distance = (a, b) => distanceM[a, b]; for (var i = localIterations.Value; i < maxIterations; i++) { InversionMove bestMove = null; var bestQuality = quality.Value; // we have to make an improvement, so current quality is the baseline var evaluations = 0.0; foreach (var move in ExhaustiveInversionMoveGenerator.Generate(assignment)) { var moveQuality = PTSPAnalyticalInversionMoveEvaluator.EvaluateMove(assignment, move, distance, probabilities); evaluations++; if (maximization && moveQuality > bestQuality || !maximization && moveQuality < bestQuality) { bestQuality = moveQuality; bestMove = move; } } evaluatedSolutions.Value += (int)Math.Ceiling(evaluations); if (bestMove == null) { break; } InversionManipulator.Apply(assignment, bestMove.Index1, bestMove.Index2); quality.Value = bestQuality; localIterations.Value++; cancellation.ThrowIfCancellationRequested(); } }
public void InversionMoveEvaluatorTest() { for (int i = 0; i < 500; i++) { int index1 = random.Next(ProblemSize); int index2 = random.Next(ProblemSize); if (index1 > index2) { int h = index1; index1 = index2; index2 = h; } // SYMMETRIC MATRICES double before = QAPEvaluator.Apply(assignment, symmetricWeights, symmetricDistances); InversionManipulator.Apply(assignment, Math.Min(index1, index2), Math.Max(index1, index2)); double after = QAPEvaluator.Apply(assignment, symmetricWeights, symmetricDistances); double move = QAPInversionMoveEvaluator.Apply(assignment, new InversionMove(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(); InversionManipulator.Apply(assignment, index1, index2); after = QAPEvaluator.Apply(assignment, asymmetricWeights, asymmetricDistances); move = QAPInversionMoveEvaluator.Apply(clone, new InversionMove(index1, index2), asymmetricWeights, asymmetricDistances); Assert.IsTrue(move.IsAlmost(after - before), "Failed on asymmetric matrices"); // NON-ZERO DIAGONAL ASYMMETRIC MATRICES before = QAPEvaluator.Apply(assignment, nonZeroDiagonalWeights, nonZeroDiagonalDistances); clone = (Permutation)assignment.Clone(); InversionManipulator.Apply(assignment, index1, index2); after = QAPEvaluator.Apply(assignment, nonZeroDiagonalWeights, nonZeroDiagonalDistances); move = QAPInversionMoveEvaluator.Apply(clone, new InversionMove(index1, index2), nonZeroDiagonalWeights, nonZeroDiagonalDistances); Assert.IsTrue(move.IsAlmost(after - before), "Failed on non-zero diagonal matrices"); } }
public static double EvaluateMove(Permutation tour, InversionMove move, Func <int, int, double> distance, DoubleArray probabilities) { var afterMove = (Permutation)tour.Clone(); InversionManipulator.Apply(afterMove, move.Index1, move.Index2); return(AnalyticalProbabilisticTravelingSalesmanProblem.Evaluate(afterMove, distance, probabilities)); }
public static void Improve(Permutation assignment, DoubleMatrix weights, DoubleMatrix distances, DoubleValue quality, IntValue localIterations, IntValue evaluatedSolutions, bool maximization, int maxIterations, CancellationToken cancellation) { for (int i = localIterations.Value; i < maxIterations; i++) { InversionMove bestMove = null; double bestQuality = 0; // we have to make an improvement, so 0 is the baseline double evaluations = 0.0; foreach (var move in ExhaustiveInversionMoveGenerator.Generate(assignment)) { double moveQuality = QAPInversionMoveEvaluator.Apply(assignment, move, weights, distances); evaluations += 2 * (move.Index2 - move.Index1 + 1) / (double)assignment.Length; if (maximization && moveQuality > bestQuality || !maximization && moveQuality < bestQuality) { bestQuality = moveQuality; bestMove = move; } } evaluatedSolutions.Value += (int)Math.Ceiling(evaluations); if (bestMove == null) { break; } InversionManipulator.Apply(assignment, bestMove.Index1, bestMove.Index2); quality.Value += bestQuality; localIterations.Value++; cancellation.ThrowIfCancellationRequested(); } }
public void InversionMoveEvaluatorTest() { var evaluator = new TSPRoundedEuclideanPathEvaluator(); var moveEvaluator = new TSPInversionMoveRoundedEuclideanPathEvaluator(); double beforeMatrix = TSPDistanceMatrixEvaluator.Apply(distances, tour); double beforeCoordinates = TSPCoordinatesPathEvaluator.Apply(evaluator, coordinates, tour); Assert.IsTrue(beforeMatrix.IsAlmost(beforeCoordinates), "Evaluation differs between using the coordinates and using the distance matrix."); for (int i = 0; i < 500; i++) { var move = StochasticInversionSingleMoveGenerator.Apply(tour, random); double moveMatrix = TSPInversionMovePathEvaluator.EvaluateByDistanceMatrix(tour, move, distances); double moveCoordinates = TSPInversionMovePathEvaluator.EvaluateByCoordinates(tour, move, coordinates, moveEvaluator); Assert.IsTrue(moveMatrix.IsAlmost(moveCoordinates), "Evaluation differs between using the coordinates and using the distance matrix."); string failureString = string.Format(@"Inversion move is calculated with quality {0}, but actual difference is {4}. The move would invert the tour {1} between values {2} and {3}.", moveMatrix.ToString(), tour.ToString(), tour[move.Index1].ToString(), tour[move.Index2].ToString(), "{0}"); InversionManipulator.Apply(tour, move.Index1, move.Index2); double afterMatrix = TSPDistanceMatrixEvaluator.Apply(distances, tour); double afterCoordinates = TSPCoordinatesPathEvaluator.Apply(evaluator, coordinates, tour); Assert.IsTrue(afterMatrix.IsAlmost(afterCoordinates), "Evaluation differs between using the coordinates and using the distance matrix."); Assert.IsTrue(moveMatrix.IsAlmost(afterMatrix - beforeMatrix), string.Format(failureString, (afterMatrix - beforeMatrix).ToString())); beforeMatrix = afterMatrix; beforeCoordinates = afterCoordinates; } }
public static void Improve(Permutation assignment, DoubleMatrix distances, DoubleValue quality, IntValue localIterations, IntValue evaluatedSolutions, bool maximization, int maxIterations, ItemList <BoolArray> realizations, CancellationToken cancellation) { var distanceM = (DistanceMatrix)distances; Func <int, int, double> distance = (a, b) => distanceM[a, b]; for (var i = localIterations.Value; i < maxIterations; i++) { InversionMove bestMove = null; double bestQuality = 0; // we have to make an improvement, so 0 is the baseline double evaluations = 0.0; foreach (var move in ExhaustiveInversionMoveGenerator.Generate(assignment)) { double moveQuality = PTSPEstimatedInversionMoveEvaluator.EvaluateMove(assignment, move, distance, realizations); evaluations += realizations.Count * 4.0 / (assignment.Length * assignment.Length); if (maximization && moveQuality > bestQuality || !maximization && moveQuality < bestQuality) { bestQuality = moveQuality; bestMove = move; } } evaluatedSolutions.Value += (int)Math.Ceiling(evaluations); if (bestMove == null) { break; } InversionManipulator.Apply(assignment, bestMove.Index1, bestMove.Index2); quality.Value += bestQuality; localIterations.Value++; cancellation.ThrowIfCancellationRequested(); } }
public static void Apply(Permutation permutation, TwoPointFiveMove move) { if (move.IsInvert) { InversionManipulator.Apply(permutation, move.Index1, move.Index2); } else { TranslocationManipulator.Apply(permutation, move.Index1, move.Index1, move.Index2); } }
public void InversionManipulatorApplyTest() { TestRandom random = new TestRandom(); Permutation parent, expected; // The following test is based on an example from Eiben, A.E. and Smith, J.E. 2003. Introduction to Evolutionary Computation. Natural Computing Series, Springer-Verlag Berlin Heidelberg, pp. 46-47 random.Reset(); random.IntNumbers = new int[] { 1, 4 }; parent = new Permutation(PermutationTypes.RelativeUndirected, new int[] { 0, 1, 2, 3, 4, 5, 6, 7, 8 }); Assert.IsTrue(parent.Validate()); expected = new Permutation(PermutationTypes.RelativeUndirected, new int[] { 0, 4, 3, 2, 1, 5, 6, 7, 8 }); Assert.IsTrue(expected.Validate()); InversionManipulator.Apply(random, parent); Assert.IsTrue(parent.Validate()); Assert.IsTrue(Auxiliary.PermutationIsEqualByPosition(expected, parent)); }
public void InversionMoveEvaluatorTest() { Func <int, int, double> distance = (a, b) => distances[a, b]; double variance; var beforeMatrix = EstimatedProbabilisticTravelingSalesmanProblem.Evaluate(tour, distance, realizations, out variance); for (var i = 0; i < 500; i++) { var move = StochasticInversionSingleMoveGenerator.Apply(tour, random); var moveMatrix = PTSPEstimatedInversionMoveEvaluator.EvaluateMove(tour, move, distance, realizations); InversionManipulator.Apply(tour, move.Index1, move.Index2); var afterMatrix = EstimatedProbabilisticTravelingSalesmanProblem.Evaluate(tour, distance, realizations, out variance); Assert.IsTrue(Math.Abs(moveMatrix).IsAlmost(Math.Abs(afterMatrix - beforeMatrix)), string.Format(@"Inversion move is calculated with quality {0}, but actual difference is {4}. The move would invert the tour {1} between values {2} and {3}.", moveMatrix, tour, tour[move.Index1], tour[move.Index2], Math.Abs(afterMatrix - beforeMatrix))); beforeMatrix = afterMatrix; } }