Пример #1
0
        public void Swap2MoveEvaluatorTest()
        {
            for (int i = 0; i < 500; i++)
            {
                int index1 = random.Next(ProblemSize);
                int index2 = random.Next(ProblemSize);

                // SYMMETRIC MATRICES
                double before = QAPEvaluator.Apply(assignment, symmetricWeights, symmetricDistances);
                Swap2Manipulator.Apply(assignment, index1, index2);
                double after = QAPEvaluator.Apply(assignment, symmetricWeights, symmetricDistances);
                double move  = QAPSwap2MoveEvaluator.Apply(assignment, new Swap2Move(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();
                Swap2Manipulator.Apply(assignment, index1, index2);
                after = QAPEvaluator.Apply(assignment, asymmetricWeights, asymmetricDistances);
                move  = QAPSwap2MoveEvaluator.Apply(clone, new Swap2Move(index1, index2), asymmetricWeights, asymmetricDistances);
                Assert.IsTrue(move.IsAlmost(after - before), "Failed on asymmetric matrices");

                // NON-ZERO DIAGONAL ASSYMETRIC MATRICES
                before = QAPEvaluator.Apply(assignment, nonZeroDiagonalWeights, nonZeroDiagonalDistances);
                clone  = (Permutation)assignment.Clone();
                Swap2Manipulator.Apply(assignment, index1, index2);
                after = QAPEvaluator.Apply(assignment, nonZeroDiagonalWeights, nonZeroDiagonalDistances);
                move  = QAPSwap2MoveEvaluator.Apply(clone, new Swap2Move(index1, index2), nonZeroDiagonalWeights, nonZeroDiagonalDistances);
                Assert.IsTrue(move.IsAlmost(after - before), "Failed on non-zero diagonal matrices");
            }
        }
Пример #2
0
        public void Swap2MoveEvaluatorFastEvaluationTest()
        {
            for (int i = 0; i < 500; i++)
            {
                Swap2Move   lastMove       = new Swap2Move(random.Next(ProblemSize), random.Next(ProblemSize));
                Permutation prevAssignment = (Permutation)assignment.Clone();
                Swap2Manipulator.Apply(assignment, lastMove.Index1, lastMove.Index2);
                Permutation nextAssignment = (Permutation)assignment.Clone();
                Swap2Move   currentMove    = new Swap2Move(random.Next(ProblemSize), random.Next(ProblemSize));
                Swap2Manipulator.Apply(nextAssignment, currentMove.Index1, currentMove.Index2);

                double moveBefore = QAPSwap2MoveEvaluator.Apply(prevAssignment, currentMove, symmetricWeights, symmetricDistances);
                double moveAfter  = QAPSwap2MoveEvaluator.Apply(assignment, currentMove,
                                                                moveBefore, symmetricWeights, symmetricDistances, lastMove);
                double before = QAPEvaluator.Apply(assignment, symmetricWeights, symmetricDistances);
                double after  = QAPEvaluator.Apply(nextAssignment, symmetricWeights, symmetricDistances);

                Assert.IsTrue(moveAfter.IsAlmost(after - before), "Failed on symmetric matrices: " + Environment.NewLine
                              + "Quality changed from " + before + " to " + after + " (" + (after - before).ToString() + "), but move quality change was " + moveAfter + ".");

                moveBefore = QAPSwap2MoveEvaluator.Apply(prevAssignment, currentMove, asymmetricWeights, asymmetricDistances);
                moveAfter  = QAPSwap2MoveEvaluator.Apply(assignment, currentMove,
                                                         moveBefore, asymmetricWeights, asymmetricDistances, lastMove);
                before = QAPEvaluator.Apply(assignment, asymmetricWeights, asymmetricDistances);
                after  = QAPEvaluator.Apply(nextAssignment, asymmetricWeights, asymmetricDistances);

                Assert.IsTrue(moveAfter.IsAlmost(after - before), "Failed on asymmetric matrices: " + Environment.NewLine
                              + "Quality changed from " + before + " to " + after + " (" + (after - before).ToString() + "), but move quality change was " + moveAfter + ".");

                moveBefore = QAPSwap2MoveEvaluator.Apply(prevAssignment, currentMove, nonZeroDiagonalWeights, nonZeroDiagonalDistances);
                moveAfter  = QAPSwap2MoveEvaluator.Apply(assignment, currentMove,
                                                         moveBefore, nonZeroDiagonalWeights, nonZeroDiagonalDistances, lastMove);
                before = QAPEvaluator.Apply(assignment, nonZeroDiagonalWeights, nonZeroDiagonalDistances);
                after  = QAPEvaluator.Apply(nextAssignment, nonZeroDiagonalWeights, nonZeroDiagonalDistances);

                Assert.IsTrue(moveAfter.IsAlmost(after - before), "Failed on non-zero diagonal matrices: " + Environment.NewLine
                              + "Quality changed from " + before + " to " + after + " (" + (after - before).ToString() + "), but move quality change was " + moveAfter + ".");
            }
        }
Пример #3
0
        public override IOperation Apply()
        {
            IRandom      random            = RandomParameter.ActualValue;
            int          iteration         = IterationsParameter.ActualValue.Value;
            IntMatrix    shortTermMemory   = ShortTermMemoryParameter.ActualValue;
            DoubleMatrix weights           = WeightsParameter.ActualValue;
            DoubleMatrix distances         = DistancesParameter.ActualValue;
            DoubleMatrix moveQualityMatrix = MoveQualityMatrixParameter.ActualValue;

            DoubleValue quality     = QualityParameter.ActualValue;
            DoubleValue bestQuality = BestQualityParameter.ActualValue;

            if (bestQuality == null)
            {
                BestQualityParameter.ActualValue = (DoubleValue)quality.Clone();
                bestQuality = BestQualityParameter.ActualValue;
            }
            bool allMovesTabu = false;

            if (AllMovesTabuParameter.ActualValue == null)
            {
                AllMovesTabuParameter.ActualValue = new BoolValue(false);
            }
            else
            {
                allMovesTabu = AllMovesTabuParameter.ActualValue.Value;
            }

            int         minTenure = MinimumTabuTenureParameter.ActualValue.Value;
            int         maxTenure = MaximumTabuTenureParameter.ActualValue.Value;
            int         alternativeAspirationTenure = AlternativeAspirationTenureParameter.ActualValue.Value;
            bool        useAlternativeAspiration    = UseAlternativeAspirationParameter.ActualValue.Value;
            Permutation solution = PermutationParameter.ActualValue;
            Swap2Move   lastMove = LastMoveParameter.ActualValue;

            double    bestMoveQuality = double.MaxValue;
            Swap2Move bestMove        = null;
            bool      already_aspired = false;

            double evaluations = EvaluatedSolutionEquivalentsParameter.ActualValue.Value;

            foreach (Swap2Move move in ExhaustiveSwap2MoveGenerator.Generate(solution))
            {
                double moveQuality;
                if (lastMove == null)
                {
                    moveQuality  = QAPSwap2MoveEvaluator.Apply(solution, move, weights, distances);
                    evaluations += 4.0 / solution.Length;
                }
                else if (allMovesTabu)
                {
                    moveQuality = moveQualityMatrix[move.Index1, move.Index2];
                }
                else
                {
                    moveQuality = QAPSwap2MoveEvaluator.Apply(solution, move, moveQualityMatrix[move.Index1, move.Index2], weights, distances, lastMove);
                    if (move.Index1 == lastMove.Index1 || move.Index2 == lastMove.Index1 || move.Index1 == lastMove.Index2 || move.Index2 == lastMove.Index2)
                    {
                        evaluations += 4.0 / solution.Length;
                    }
                    else
                    {
                        evaluations += 2.0 / (solution.Length * solution.Length);
                    }
                }

                moveQualityMatrix[move.Index1, move.Index2] = moveQuality;
                moveQualityMatrix[move.Index2, move.Index1] = moveQuality;

                bool autorized = shortTermMemory[move.Index1, solution[move.Index2]] < iteration ||
                                 shortTermMemory[move.Index2, solution[move.Index1]] < iteration;

                bool aspired = (shortTermMemory[move.Index1, solution[move.Index2]] < iteration - alternativeAspirationTenure &&
                                shortTermMemory[move.Index2, solution[move.Index1]] < iteration - alternativeAspirationTenure) ||
                               quality.Value + moveQuality < bestQuality.Value;

                if ((aspired && !already_aspired) || // the first alternative move is aspired
                    (aspired && already_aspired && moveQuality < bestMoveQuality) || // an alternative move was already aspired, but this is better
                    (autorized && !aspired && !already_aspired && moveQuality < bestMoveQuality)) // a regular better move is found
                {
                    bestMove        = move;
                    bestMoveQuality = moveQuality;
                    if (aspired)
                    {
                        already_aspired = true;
                    }
                }
            }

            ResultCollection results = ResultsParameter.ActualValue;

            if (results != null)
            {
                IntValue aspiredMoves = null;
                if (!results.ContainsKey("AspiredMoves"))
                {
                    aspiredMoves = new IntValue(already_aspired ? 1 : 0);
                    results.Add(new Result("AspiredMoves", "Counts the number of moves that were selected because of the aspiration criteria.", aspiredMoves));
                }
                else if (already_aspired)
                {
                    aspiredMoves = (IntValue)results["AspiredMoves"].Value;
                    aspiredMoves.Value++;
                }
            }

            EvaluatedSolutionEquivalentsParameter.ActualValue.Value = evaluations;
            EvaluatedSolutionsParameter.ActualValue.Value           = (int)Math.Ceiling(evaluations);

            allMovesTabu = bestMove == null;
            if (!allMovesTabu)
            {
                LastMoveParameter.ActualValue = bestMove;
            }
            AllMovesTabuParameter.ActualValue.Value = allMovesTabu;

            if (allMovesTabu)
            {
                return(base.Apply());
            }

            bool useNewAdaptionScheme = UseNewTabuTenureAdaptionSchemeParameter.ActualValue.Value;

            if (useNewAdaptionScheme)
            {
                double r = random.NextDouble();
                if (r == 0)
                {
                    r = 1; // transform to (0;1]
                }
                shortTermMemory[bestMove.Index1, solution[bestMove.Index1]] = (int)(iteration + r * r * r * maxTenure);
                r = random.NextDouble();
                if (r == 0)
                {
                    r = 1; // transform to (0;1]
                }
                shortTermMemory[bestMove.Index2, solution[bestMove.Index2]] = (int)(iteration + r * r * r * maxTenure);
            }
            else
            {
                shortTermMemory[bestMove.Index1, solution[bestMove.Index1]] = iteration + random.Next(minTenure, maxTenure);
                shortTermMemory[bestMove.Index2, solution[bestMove.Index2]] = iteration + random.Next(minTenure, maxTenure);
            }
            Swap2Manipulator.Apply(solution, bestMove.Index1, bestMove.Index2);
            quality.Value += bestMoveQuality;

            if (quality.Value < bestQuality.Value)
            {
                bestQuality.Value = quality.Value;
            }

            return(base.Apply());
        }