public static void Improve(Permutation assignment, DoubleMatrix weights, DoubleMatrix distances, DoubleValue quality, IntValue localIterations, IntValue evaluatedSolutions, bool maximization, int maxIterations, CancellationToken cancellation)
        {
            double evalSolPerMove = 4.0 / assignment.Length;

            for (int i = localIterations.Value; i < maxIterations; i++)
            {
                Swap2Move bestMove    = null;
                double    bestQuality = 0; // we have to make an improvement, so 0 is the baseline
                double    evaluations = 0.0;
                foreach (Swap2Move move in ExhaustiveSwap2MoveGenerator.Generate(assignment))
                {
                    double moveQuality = QAPSwap2MoveEvaluator.Apply(assignment, move, weights, distances);
                    evaluations += evalSolPerMove;
                    if (maximization && moveQuality > bestQuality ||
                        !maximization && moveQuality < bestQuality)
                    {
                        bestQuality = moveQuality;
                        bestMove    = move;
                    }
                }
                evaluatedSolutions.Value += (int)Math.Ceiling(evaluations);
                if (bestMove == null)
                {
                    break;
                }
                Swap2Manipulator.Apply(assignment, bestMove.Index1, bestMove.Index2);
                quality.Value += bestQuality;
                localIterations.Value++;
                cancellation.ThrowIfCancellationRequested();
            }
        }
        public static void ImproveFast(Permutation assignment, DoubleMatrix weights, DoubleMatrix distances, DoubleValue quality, IntValue localIterations, IntValue evaluatedSolutions, bool maximization, int maxIterations, CancellationToken cancellation)
        {
            Swap2Move bestMove    = null;
            double    evaluations = 0.0;
            var       lastQuality = new double[assignment.Length, assignment.Length];

            for (int i = localIterations.Value; i < maxIterations; i++)
            {
                double bestQuality = 0; // we have to make an improvement, so 0 is the baseline
                var    lastMove    = bestMove;
                bestMove = null;
                foreach (Swap2Move move in ExhaustiveSwap2MoveGenerator.Generate(assignment))
                {
                    double moveQuality;
                    if (lastMove == null)
                    {
                        moveQuality  = QAPSwap2MoveEvaluator.Apply(assignment, move, weights, distances);
                        evaluations += 4.0 / assignment.Length;
                    }
                    else
                    {
                        moveQuality = QAPSwap2MoveEvaluator.Apply(assignment, move, lastQuality[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 / assignment.Length;
                        }
                        else
                        {
                            evaluations += 2.0 / (assignment.Length * assignment.Length);
                        }
                    }
                    lastQuality[move.Index1, move.Index2] = moveQuality;
                    if (maximization && moveQuality > bestQuality ||
                        !maximization && moveQuality < bestQuality)
                    {
                        bestQuality = moveQuality;
                        bestMove    = move;
                    }
                }
                if (bestMove == null)
                {
                    break;
                }
                Swap2Manipulator.Apply(assignment, bestMove.Index1, bestMove.Index2);
                quality.Value += bestQuality;
                localIterations.Value++;
                if (cancellation.IsCancellationRequested)
                {
                    evaluatedSolutions.Value += (int)Math.Round(evaluations);
                    throw new OperationCanceledException();
                }
            }
            evaluatedSolutions.Value += (int)Math.Round(evaluations);
        }
Example #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());
        }