#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 HeuristicLab.Collections; using HeuristicLab.Common; using HeuristicLab.Core; using HeuristicLab.Data; using HeuristicLab.Persistence.Default.CompositeSerializers.Storable; using HeuristicLab.Problems.BinPacking.Interfaces; namespace HeuristicLab.Encodings.PackingEncoding.MultiComponentVector { [Item("Bin Based Multi Component Vector Crossover", "An operator which crosses two MultiComponentVector representations. The applied strategy is based on the RBX crossover proposed by Potvin.")] [StorableClass] public class BinBasedMultiComponentVectorCrossover : MultiComponentVectorCrossover { [StorableConstructor] protected BinBasedMultiComponentVectorCrossover (bool deserializing) : base(deserializing) { } protected BinBasedMultiComponentVectorCrossover (BinBasedMultiComponentVectorCrossover original, Cloner cloner) : base(original, cloner) { } public BinBasedMultiComponentVectorCrossover () : base() { } public override IDeepCloneable Clone(Cloner cloner) { return new BinBasedMultiComponentVectorCrossover (this, cloner); } public override MultiComponentVectorEncoding Cross(IRandom random, MultiComponentVectorEncoding parent1, MultiComponentVectorEncoding parent2) { MultiComponentVectorEncoding child = new MultiComponentVectorEncoding(); int nrOfItems = parent1.NrOfItems; bool[] itemAlreadyAssigned = new bool[nrOfItems]; bool useParent2 = false; int nrOfBins = parent1.NrOfBins > parent2.NrOfBins ? parent2.NrOfBins : parent1.NrOfBins; for (int binNr = 0; binNr < nrOfBins; binNr++) { MultiComponentVectorEncoding currentParent1 = useParent2 ? parent2 : parent1; MultiComponentVectorEncoding currentParent2 = useParent2 ? parent1 : parent2; var newBin = new ItemList(); double crossPointPercent = 0; int nrOfItems1 = currentParent1.PackingInformations[binNr].Count; if (nrOfItems1 > 0) { double crossPoint1 = random.Next(nrOfItems1); crossPointPercent = crossPoint1 / nrOfItems1; for (int i = 0; i < crossPoint1; i++) { PackingInformation pi = new PackingInformation(currentParent1.PackingInformations[binNr][i]); if (!itemAlreadyAssigned[pi.ItemID]) { itemAlreadyAssigned[pi.ItemID] = true; newBin.Add(new PackingInformation(pi)); } } } int nrOfItems2 = currentParent2.PackingInformations[binNr].Count; if (nrOfItems2 > 0) { int crossPoint2 = Convert.ToInt32(nrOfItems2 * crossPointPercent); for (int i = crossPoint2; i < nrOfItems2; i++) { PackingInformation pi = new PackingInformation(currentParent2.PackingInformations[binNr][i]); if (!itemAlreadyAssigned[pi.ItemID]) { itemAlreadyAssigned[pi.ItemID] = true; newBin.Add(new PackingInformation(pi)); } } } child.PackingInformations[binNr] = newBin; useParent2 = !useParent2; } for (int itemID = 0; itemID < nrOfItems; itemID++) { if (!itemAlreadyAssigned[itemID]) child.PackingInformations[0].Add(new PackingInformation(itemID, random.Next(2) == 0 ? true : false)); } return child; } } }