/// <summary> /// Takes two parent individuals P0 and P1. /// Randomly choose a node i from the second parent, then test all possible crossover points from the first parent to determine the best location for i to be inserted. /// </summary> public static ISymbolicExpressionTree Cross(IRandom random, ISymbolicExpressionTree parent0, ISymbolicExpressionTree parent1, IExecutionContext context, ISymbolicDataAnalysisSingleObjectiveEvaluator <T> evaluator, T problemData, List <int> rows, int maxDepth, int maxLength) { // randomly choose a node from the second parent var possibleChildren = new List <ISymbolicExpressionTreeNode>(); parent1.Root.ForEachNodePostfix((n) => { if (n.Parent != null && n.Parent != parent1.Root) { possibleChildren.Add(n); } }); var selectedChild = possibleChildren.SampleRandom(random); var crossoverPoints = new List <CutPoint>(); var qualities = new List <Tuple <CutPoint, double> >(); parent0.Root.ForEachNodePostfix((n) => { if (n.Parent != null && n.Parent != parent0.Root) { var totalDepth = parent0.Root.GetBranchLevel(n) + selectedChild.GetDepth(); var totalLength = parent0.Root.GetLength() - n.GetLength() + selectedChild.GetLength(); if (totalDepth <= maxDepth && totalLength <= maxLength) { var crossoverPoint = new CutPoint(n.Parent, n); if (crossoverPoint.IsMatchingPointType(selectedChild)) { crossoverPoints.Add(crossoverPoint); } } } }); if (crossoverPoints.Any()) { // this loop will perform two swap operations per each crossover point foreach (var crossoverPoint in crossoverPoints) { // save the old parent so we can restore it later var parent = selectedChild.Parent; // perform a swap and check the quality of the solution Swap(crossoverPoint, selectedChild); IExecutionContext childContext = new ExecutionContext(context, evaluator, context.Scope); double quality = evaluator.Evaluate(childContext, parent0, problemData, rows); qualities.Add(new Tuple <CutPoint, double>(crossoverPoint, quality)); // restore the correct parent selectedChild.Parent = parent; // swap the replaced subtree back into the tree so that the structure is preserved Swap(crossoverPoint, crossoverPoint.Child); } qualities.Sort((a, b) => a.Item2.CompareTo(b.Item2)); // assuming this sorts the list in ascending order var crossoverPoint0 = evaluator.Maximization ? qualities.Last().Item1 : qualities.First().Item1; // swap the node that would create the best offspring // this last swap makes a total of (2 * crossoverPoints.Count() + 1) swap operations. Swap(crossoverPoint0, selectedChild); } return(parent0); }
/// <summary> /// Takes two parent individuals P0 and P1. /// Randomly choose a node i from the first parent, then test all nodes j from the second parent to determine the best child that would be obtained by swapping i for j. /// </summary> public static ISymbolicExpressionTree Cross(IRandom random, ISymbolicExpressionTree parent0, ISymbolicExpressionTree parent1, IExecutionContext context, ISymbolicDataAnalysisSingleObjectiveEvaluator <T> evaluator, T problemData, List <int> rows, int maxDepth, int maxLength) { var crossoverPoints0 = new List <CutPoint>(); parent0.Root.ForEachNodePostfix((n) => { if (n.Parent != null && n.Parent != parent0.Root) { crossoverPoints0.Add(new CutPoint(n.Parent, n)); } }); CutPoint crossoverPoint0 = crossoverPoints0.SampleRandom(random); int level = parent0.Root.GetBranchLevel(crossoverPoint0.Child); int length = parent0.Root.GetLength() - crossoverPoint0.Child.GetLength(); var allowedBranches = new List <ISymbolicExpressionTreeNode>(); parent1.Root.ForEachNodePostfix((n) => { if (n.Parent != null && n.Parent != parent1.Root) { if (n.GetDepth() + level <= maxDepth && n.GetLength() + length <= maxLength && crossoverPoint0.IsMatchingPointType(n)) { allowedBranches.Add(n); } } }); if (allowedBranches.Count == 0) { return(parent0); } // create symbols in order to improvize an ad-hoc tree so that the child can be evaluated ISymbolicExpressionTreeNode selectedBranch = null; var nodeQualities = new List <Tuple <ISymbolicExpressionTreeNode, double> >(); var originalChild = crossoverPoint0.Child; foreach (var node in allowedBranches) { var parent = node.Parent; Swap(crossoverPoint0, node); // the swap will set the nodes parent to crossoverPoint0.Parent IExecutionContext childContext = new ExecutionContext(context, evaluator, context.Scope); double quality = evaluator.Evaluate(childContext, parent0, problemData, rows); Swap(crossoverPoint0, originalChild); // swap the child back (so that the next swap will not affect the currently swapped node from parent1) nodeQualities.Add(new Tuple <ISymbolicExpressionTreeNode, double>(node, quality)); node.Parent = parent; // restore correct parent } nodeQualities.Sort((a, b) => a.Item2.CompareTo(b.Item2)); selectedBranch = evaluator.Maximization ? nodeQualities.Last().Item1 : nodeQualities.First().Item1; // swap the node that would create the best offspring Swap(crossoverPoint0, selectedBranch); return(parent0); }
public override ISymbolicExpressionTree Crossover(IRandom random, ISymbolicExpressionTree parent0, ISymbolicExpressionTree parent1) { if (this.ExecutionContext == null) { throw new InvalidOperationException("ExecutionContext not set."); } List <int> rows = GenerateRowsToEvaluate().ToList(); T problemData = ProblemDataParameter.ActualValue; ISymbolicDataAnalysisSingleObjectiveEvaluator <T> evaluator = EvaluatorParameter.ActualValue; return(Cross(random, parent0, parent1, this.ExecutionContext, evaluator, problemData, rows, MaximumSymbolicExpressionTreeDepth.Value, MaximumSymbolicExpressionTreeLength.Value)); }