#region License Information
/* HeuristicLab
* Copyright (C) 2002-2008 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.Collections.Generic;
using HeuristicLab.Core;
using HeuristicLab.GP.Interfaces;
namespace HeuristicLab.GP.Operators {
///
/// Implementation of a homologous one point crossover operator as described in:
/// W. B. Langdon and R. Poli. Foundations of Genetic Programming. Springer-Verlag, 2002.
///
public class OnePointCrossOver : SizeConstrictedGPCrossoverBase {
// internal data structure to represent crossover points
private class CrossoverPoint {
public IFunctionTree parent0;
public IFunctionTree parent1;
public int childIndex;
}
public override string Description {
get {
return @"One point crossover for trees as described in W. B. Langdon and R. Poli. Foundations of Genetic Programming. Springer-Verlag, 2002.";
}
}
internal override IFunctionTree Cross(TreeGardener gardener, IRandom random, IFunctionTree tree0, IFunctionTree tree1, int maxTreeSize, int maxTreeHeight) {
List allowedCrossOverPoints = new List();
GetCrossOverPoints(gardener, tree0, tree1, maxTreeSize - tree0.GetSize(), allowedCrossOverPoints);
if (allowedCrossOverPoints.Count > 0) {
CrossoverPoint crossOverPoint = allowedCrossOverPoints[random.Next(allowedCrossOverPoints.Count)];
IFunctionTree parent0 = crossOverPoint.parent0;
IFunctionTree branch1 = crossOverPoint.parent1.SubTrees[crossOverPoint.childIndex];
parent0.RemoveSubTree(crossOverPoint.childIndex);
parent0.InsertSubTree(crossOverPoint.childIndex, branch1);
}
return tree0;
}
private void GetCrossOverPoints(TreeGardener gardener, IFunctionTree branch0, IFunctionTree branch1, int maxNewNodes, List crossoverPoints) {
if (branch0.SubTrees.Count != branch1.SubTrees.Count) return;
for (int i = 0; i < branch0.SubTrees.Count; i++) {
// if the current branch can be attached as a sub-tree to branch0
if (gardener.GetAllowedSubFunctions(branch0.Function, i).Contains(branch1.SubTrees[i].Function) &&
branch1.SubTrees[i].GetSize() - branch0.SubTrees[i].GetSize() <= maxNewNodes) {
CrossoverPoint p = new CrossoverPoint();
p.childIndex = i;
p.parent0 = branch0;
p.parent1 = branch1;
crossoverPoints.Add(p);
}
GetCrossOverPoints(gardener, branch0.SubTrees[i], branch1.SubTrees[i], maxNewNodes, crossoverPoints);
}
}
}
}