#region License Information /* HeuristicLab * Copyright (C) 2002-2018 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 System.Linq; using HeuristicLab.Common; using HeuristicLab.Core; using HeuristicLab.Data; using HeuristicLab.Encodings.IntegerVectorEncoding; using HeuristicLab.Operators; using HeuristicLab.Parameters; using HeuristicLab.Persistence.Default.CompositeSerializers.Storable; namespace HeuristicLab.Problems.GeneralizedQuadraticAssignment { [Item("N-Move Evaluator", "Evaluates an N-Move.")] [StorableClass] public class GQAPNMoveEvaluator : SingleSuccessorOperator, IGQAPNMoveEvaluator, IQualityAwareGQAPOperator, IProblemInstanceAwareGQAPOperator, IAssignmentAwareGQAPOperator { #region Parameter Descriptions public static readonly string MoveQualityDescription = "The quality of the move if it would be applied."; public static readonly string MoveEvaluationDescription = "The results of evaluating the move."; #endregion #region Parameter Properties public ILookupParameter MoveQualityParameter { get { return (ILookupParameter)Parameters["MoveQuality"]; } } public ILookupParameter MoveEvaluationParameter { get { return (ILookupParameter)Parameters["MoveEvaluation"]; } } public ILookupParameter MoveParameter { get { return (ILookupParameter)Parameters["Move"]; } } public ILookupParameter AssignmentParameter { get { return (ILookupParameter)Parameters["Assignment"]; } } public ILookupParameter QualityParameter { get { return (ILookupParameter)Parameters["Quality"]; } } public ILookupParameter EvaluationParameter { get { return (ILookupParameter)Parameters["Evaluation"]; } } public ILookupParameter ProblemInstanceParameter { get { return (ILookupParameter)Parameters["ProblemInstance"]; } } #endregion [StorableConstructor] protected GQAPNMoveEvaluator(bool deserializing) : base(deserializing) { } protected GQAPNMoveEvaluator(GQAPNMoveEvaluator original, Cloner cloner) : base(original, cloner) { } public GQAPNMoveEvaluator() : base() { Parameters.Add(new LookupParameter("Assignment", GQAPSolutionCreator.AssignmentDescription)); Parameters.Add(new LookupParameter("Move", GQAPNMoveGenerator.MoveDescription)); Parameters.Add(new LookupParameter("Quality", "")); Parameters.Add(new LookupParameter("Evaluation", GQAP.EvaluationDescription)); Parameters.Add(new LookupParameter("MoveQuality", MoveQualityDescription)); Parameters.Add(new LookupParameter("MoveEvaluation", MoveEvaluationDescription)); Parameters.Add(new LookupParameter("ProblemInstance", GQAP.ProblemInstanceDescription)); } public override IDeepCloneable Clone(Cloner cloner) { return new GQAPNMoveEvaluator(this, cloner); } public static Evaluation Evaluate(NMove move, IntegerVector assignment, Evaluation evaluation, GQAPInstance problemInstance) { int moves = move.N; var excessDemand = evaluation.ExcessDemand; var flowCosts = evaluation.FlowCosts; var installationCosts = evaluation.InstallationCosts; var slack = evaluation.Slack.ToArray(); foreach (var equip in move.Indices) { int newLoc = move.Reassignments[equip] - 1; // locations are given 1-based int oldLoc = assignment[equip]; var equipDemand = problemInstance.Demands[equip]; installationCosts -= problemInstance.InstallationCosts[equip, oldLoc]; installationCosts += problemInstance.InstallationCosts[equip, newLoc]; for (int j = 0; j < assignment.Length; j++) { var reassignedLoc = move.Reassignments[j] - 1; // 0 indicates that this equipment is not reassigned if (reassignedLoc < 0) { flowCosts += problemInstance.Weights[equip, j] * problemInstance.Distances[newLoc, assignment[j]]; flowCosts -= problemInstance.Weights[equip, j] * problemInstance.Distances[oldLoc, assignment[j]]; flowCosts += problemInstance.Weights[j, equip] * problemInstance.Distances[assignment[j], newLoc]; flowCosts -= problemInstance.Weights[j, equip] * problemInstance.Distances[assignment[j], oldLoc]; } else { flowCosts += problemInstance.Weights[equip, j] * problemInstance.Distances[newLoc, reassignedLoc]; flowCosts -= problemInstance.Weights[equip, j] * problemInstance.Distances[oldLoc, assignment[j]]; } } slack[oldLoc] += equipDemand; if (slack[oldLoc] < equipDemand) excessDemand -= Math.Min(equipDemand, equipDemand - slack[oldLoc]); slack[newLoc] -= equipDemand; if (slack[newLoc] < 0) excessDemand += Math.Min(equipDemand, -slack[newLoc]); } return new Evaluation(flowCosts, installationCosts, excessDemand, slack); } public override IOperation Apply() { var problemInstance = ProblemInstanceParameter.ActualValue; var evaluation = EvaluationParameter.ActualValue; var moveEvaluation = Evaluate(MoveParameter.ActualValue, AssignmentParameter.ActualValue, evaluation, problemInstance); MoveEvaluationParameter.ActualValue = moveEvaluation; MoveQualityParameter.ActualValue = new DoubleValue(problemInstance.ToSingleObjective(moveEvaluation)); return base.Apply(); } } }