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()); }