#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.Persistence.Default.CompositeSerializers.Storable;
namespace HeuristicLab.Encodings.VariableVector {
[Item("SinglePointCrossover", "Description missing")]
[StorableClass]
public class SinglePointCrossover : VariableVectorCrossover {
#region Parameter Properties
#endregion
[StorableConstructor]
protected SinglePointCrossover(bool deserializing) : base(deserializing) { }
protected SinglePointCrossover(SinglePointCrossover original, Cloner cloner)
: base(original, cloner) {
}
public SinglePointCrossover() : base() { }
public override IDeepCloneable Clone(Cloner cloner) {
return new SinglePointCrossover(this, cloner);
}
public static VariableVector Apply(IRandom random, VariableVector parent1, VariableVector parent2) {
var parent1Condition = parent1.Condition;
var parent2Condition = parent2.Condition;
var parent1Action = parent1.Action;
var parent2Action = parent2.Action;
if (parent1.Count != parent2.Count && parent1.VirtualLength != parent2.VirtualLength
&& parent1Condition.VariableDictionary.Count != parent2Condition.VariableDictionary.Count && parent1Condition.VirtualLength != parent2Condition.VirtualLength
&& parent1Action.VariableDictionary.Count != parent2Action.VariableDictionary.Count && parent1Action.VirtualLength != parent2Action.VirtualLength)
throw new ArgumentException("SinglePointCrossover: The parents are of different length.");
int conditionLength = parent1Condition.VirtualLength;
int breakPoint = random.Next(1, conditionLength);
IList newCondition = new List(parent1Condition.VariableDictionary.Count);
var keyEnumerator = parent1Condition.VariableDictionary.Keys.GetEnumerator();
int index = 0;
IVariable curVariable = null;
while (index < breakPoint) {
if (!keyEnumerator.MoveNext()) { throw new IndexOutOfRangeException("Enumerator has no next element!"); }
curVariable = parent1Condition.VariableDictionary[keyEnumerator.Current];
if (index + curVariable.VirtualLength <= breakPoint) {
newCondition.Add(curVariable.GetSetCopy());
}
index += curVariable.VirtualLength;
}
// breakpoint is in between a variable
if (index != breakPoint) {
newCondition.Add(parent1Condition.VariableDictionary[keyEnumerator.Current].CrossParentsAtPosition(parent2Condition.VariableDictionary[keyEnumerator.Current], breakPoint - (index - curVariable.VirtualLength)));
}
while (index < conditionLength) {
keyEnumerator.MoveNext();
curVariable = parent2Condition.VariableDictionary[keyEnumerator.Current];
newCondition.Add(curVariable.GetSetCopy());
index += curVariable.VirtualLength;
}
var action = random.Next(2) == 1 ? parent1Action.VariableDictionary.Values.Select(x => x.GetSetCopy()) : parent2Action.VariableDictionary.Values.Select(x => x.GetSetCopy());
return new VariableVector(newCondition, action);
}
protected override VariableVector Cross(IRandom random, ItemArray parents) {
if (parents.Length != 2) throw new ArgumentException("ERROR in SinglePointCrossover: The number of parents is not equal to 2");
return Apply(random, parents[0], parents[1]);
}
}
}