#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;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using HeuristicLab.Core;
using HeuristicLab.Operators;
using HeuristicLab.Random;
using HeuristicLab.Data;
using HeuristicLab.Constraints;
using System.Diagnostics;
namespace HeuristicLab.GP {
public class StandardCrossOver : SizeConstrictedGPCrossoverBase {
private int MaxRecombinationTries { get { return 20; } }
public override string Description {
get {
return @"Takes two parent individuals P0 and P1 each. Selects a random node N0 of P0 and a random node N1 of P1.
And replaces the branch with root0 N0 in P0 with N1 from P1 if the tree-size limits are not violated.
When recombination with N0 and N1 would create a tree that is too large or invalid the operator randomly selects new N0 and N1
until a valid configuration is found.";
}
}
internal override IFunctionTree Cross(TreeGardener gardener, IRandom random, IFunctionTree tree0, IFunctionTree tree1, int maxTreeSize, int maxTreeHeight) {
int tries = 0;
List allowedCrossoverPoints = null;
IFunctionTree parent0;
int replacedChildIndex;
do {
// select a random crossover point in the first parent tree0
parent0 = null;
while (parent0 == null) parent0 = gardener.GetRandomParentNode(tree0);
// select a random branch to replace
replacedChildIndex = random.Next(parent0.SubTrees.Count);
// calculate the max size and height that the inserted branch can have
int maxInsertedBranchSize = maxTreeSize - (tree0.Size - parent0.SubTrees[replacedChildIndex].Size);
int maxInsertedBranchHeight = maxTreeHeight - gardener.GetBranchLevel(tree0, parent0); // branchlevel is 1 if tree0==parent0
IList allowedFunctions = gardener.GetAllowedSubFunctions(parent0.Function, replacedChildIndex);
allowedCrossoverPoints = GetPossibleCrossoverPoints(gardener, tree1, maxInsertedBranchSize, maxInsertedBranchHeight, allowedFunctions);
} while (allowedCrossoverPoints.Count == 0 && tries++ < MaxRecombinationTries);
if (allowedCrossoverPoints.Count > 0) {
IFunctionTree branch1 = allowedCrossoverPoints[random.Next(allowedCrossoverPoints.Count)];
// replace the branch in tree0 with the selected branch from tree1
parent0.RemoveSubTree(replacedChildIndex);
parent0.InsertSubTree(replacedChildIndex, branch1);
}
return tree0;
}
private List GetPossibleCrossoverPoints(TreeGardener gardener, IFunctionTree tree, int maxInsertedBranchSize, int maxInsertedBranchHeight, IList allowedFunctions) {
List crossoverPoints = new List();
foreach (IFunctionTree possiblePoint in gardener.GetAllSubTrees(tree)) {
if (allowedFunctions.Contains(possiblePoint.Function) && possiblePoint.Size <= maxInsertedBranchSize && possiblePoint.Height <= maxInsertedBranchHeight)
crossoverPoints.Add(possiblePoint);
}
return crossoverPoints;
}
}
}