#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;
}
}
}