#region License Information /* HeuristicLab * Copyright (C) 2002-2019 Heuristic and Evolutionary Algorithms Laboratory (HEAL) * * This file is part of HeuristicLab. * * HeuristicLab is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * HeuristicLab is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with HeuristicLab. If not, see . */ #endregion using System; using HeuristicLab.Common; using HeuristicLab.Core; using HeuristicLab.Data; using HeuristicLab.Encodings.PermutationEncoding; using HeuristicLab.Parameters; using HEAL.Attic; namespace HeuristicLab.Problems.QuadraticAssignment { [Item("QAPScrambleMoveEvaluator", "Evaluated a scramble move on a QAP solution.")] [StorableType("E5D1B682-6ADA-4DEE-8546-6C5BCE1C91D0")] public class QAPScrambleMoveEvaluator : QAPMoveEvaluator, IPermutationScrambleMoveOperator { public ILookupParameter ScrambleMoveParameter { get { return (ILookupParameter)Parameters["ScrambleMove"]; } } [StorableConstructor] protected QAPScrambleMoveEvaluator(StorableConstructorFlag _) : base(_) { } protected QAPScrambleMoveEvaluator(QAPScrambleMoveEvaluator original, Cloner cloner) : base(original, cloner) { } public QAPScrambleMoveEvaluator() { Parameters.Add(new LookupParameter("ScrambleMove", "The move to evaluate.")); } public override IDeepCloneable Clone(Cloner cloner) { return new QAPScrambleMoveEvaluator(this, cloner); } /// /// Calculates the quality of the move by evaluating the changes. /// The runtime complexity of this method is O(N) with N being the size of the permutation. /// /// The current permutation. /// The move that is to be evaluated if it was applied to the current permutation. /// The weights matrix. /// The distances matrix. /// The relative change in quality if was applied to . 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; } 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(); } } }