#region License Information /* HeuristicLab * Copyright (C) 2002-2012 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.Collections.Generic; using System.Linq; using HeuristicLab.Common; using HeuristicLab.Core; using HeuristicLab.Data; using HeuristicLab.Encodings.IntegerVectorEncoding; using HeuristicLab.Parameters; using HeuristicLab.Persistence.Default.CompositeSerializers.Storable; using HeuristicLab.Problems.GeneralizedQuadraticAssignment.Common; namespace HeuristicLab.Problems.GeneralizedQuadraticAssignment { [Item("DemandEquivalentSwapEquipmentManipluator", "Swaps equipment X from location A with as much equipments from location B that the demand of X is less than or equal to the demand of the swapped equipments in B.")] [StorableClass] public class DemandEquivalentSwapEquipmentManipluator : GQAPManipulator, IDemandsAwareGQAPOperator, ICapacitiesAwareGQAPOperator { public ILookupParameter DemandsParameter { get { return (ILookupParameter)Parameters["Demands"]; } } public ILookupParameter CapacitiesParameter { get { return (ILookupParameter)Parameters["Capacities"]; } } [StorableConstructor] protected DemandEquivalentSwapEquipmentManipluator(bool deserializing) : base(deserializing) { } protected DemandEquivalentSwapEquipmentManipluator(DemandEquivalentSwapEquipmentManipluator original, Cloner cloner) : base(original, cloner) { } public DemandEquivalentSwapEquipmentManipluator() : base() { Parameters.Add(new LookupParameter("Demands", GeneralizedQuadraticAssignmentProblem.DemandsDescription)); Parameters.Add(new LookupParameter("Capacities", GeneralizedQuadraticAssignmentProblem.CapacitiesDescription)); } public override IDeepCloneable Clone(Cloner cloner) { return new DemandEquivalentSwapEquipmentManipluator(this, cloner); } public static void Apply(IRandom random, IntegerVector assignment, DoubleArray capacities, DoubleArray demands) { if (assignment.Length < 2) throw new InvalidOperationException("Vector is too small for swap operation."); int equipment1 = random.Next(assignment.Length), equipment2 = random.Next(assignment.Length); int counter = 1; while (assignment[equipment1] == assignment[equipment2] && counter < assignment.Length) { equipment2 = random.Next(assignment.Length); counter++; } if (assignment[equipment1] != assignment[equipment2]) { var groupedLocations = assignment .Select((value, index) => new { Index = index, Value = value }) .GroupBy(x => x.Value) .ToDictionary(x => x.Key, y => new HashSet(y.Select(x => x.Index))); double demand = demands[equipment1]; int location1 = assignment[equipment1]; int location2 = assignment[equipment2]; assignment[equipment1] = location2; while (demand > 0) { demand -= demands[equipment2]; assignment[equipment2] = location1; groupedLocations[location2].Remove(equipment2); if (!groupedLocations[location2].Any()) break; equipment2 = groupedLocations[location2].ChooseUniformRandom(random); } } } protected override void Manipulate(IRandom random, IntegerVector vector) { Apply(random, vector, CapacitiesParameter.ActualValue, DemandsParameter.ActualValue); } } }