コード例 #1
0
        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();
            }
        }
コード例 #3
0
        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");
            }
        }
コード例 #4
0
        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));
        }
コード例 #5
0
 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();
     }
 }
コード例 #6
0
        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;
            }
        }
コード例 #7
0
        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();
            }
        }
コード例 #8
0
 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);
     }
 }
コード例 #9
0
        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));
        }
コード例 #10
0
        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;
            }
        }