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();
     }
 }
Ejemplo n.º 2
0
        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");
            }
        }
Ejemplo n.º 3
0
        public override IOperation Apply()
        {
            ScrambleMove move = ScrambleMoveParameter.ActualValue;

            if (move == null)
            {
                throw new InvalidOperationException("Scramble move is not found.");
            }
            Permutation  assignment = PermutationParameter.ActualValue;
            DoubleMatrix distances  = DistancesParameter.ActualValue;
            DoubleMatrix weights    = WeightsParameter.ActualValue;

            double moveQuality = QualityParameter.ActualValue.Value;

            moveQuality += Apply(assignment, move, weights, distances);
            MoveQualityParameter.ActualValue = new DoubleValue(moveQuality);
            return(base.Apply());
        }
Ejemplo n.º 4
0
        /// <summary>
        /// Calculates the quality of the move <paramref name="move"/> by evaluating the changes.
        /// The runtime complexity of this method is O(N) with N being the size of the permutation.
        /// </summary>
        /// <param name="assignment">The current permutation.</param>
        /// <param name="move">The move that is to be evaluated if it was applied to the current permutation.</param>
        /// <param name="weights">The weights matrix.</param>
        /// <param name="distances">The distances matrix.</param>
        /// <returns>The relative change in quality if <paramref name="move"/> was applied to <paramref name="assignment"/>.</returns>
        public static double Apply(Permutation assignment, ScrambleMove move, DoubleMatrix weights, DoubleMatrix distances)
        {
            double moveQuality = 0;
            int    min         = move.StartIndex;
            int    max         = min + move.ScrambledIndices.Length - 1;

            for (int i = min; i <= max; i++)
            {
                int locI    = assignment[i];
                int newlocI = assignment[min + move.ScrambledIndices[i - min]];
                if (locI == newlocI)
                {
                    continue;
                }

                for (int j = 0; j < assignment.Length; j++)
                {
                    int locJ = assignment[j];
                    if (j >= min && j <= max)
                    {
                        int newlocJ = assignment[min + move.ScrambledIndices[j - min]];
                        moveQuality += weights[i, j] * (distances[newlocI, newlocJ] - distances[locI, locJ]);
                        if (locJ == newlocJ)
                        {
                            moveQuality += weights[j, i] * (distances[newlocJ, newlocI] - distances[locJ, locI]);
                        }
                    }
                    else
                    {
                        moveQuality += weights[i, j] * (distances[newlocI, locJ] - distances[locI, locJ]);
                        moveQuality += weights[j, i] * (distances[locJ, newlocI] - distances[locJ, locI]);
                    }
                }
            }
            return(moveQuality);
        }