Free cookie consent management tool by TermsFeed Policy Generator

source: branches/CEDMA-Refactoring-Ticket419/HeuristicLab.GP/Recombination/SizeFairCrossOver.cs @ 1200

Last change on this file since 1200 was 1200, checked in by gkronber, 15 years ago

Set probability of creating larger trees to zero when max-tree size is reached in SizeFairCrossOver #479 (Crossover operators create trees that are larger than the allowed max size).

File size: 6.9 KB
Line 
1#region License Information
2/* HeuristicLab
3 * Copyright (C) 2002-2008 Heuristic and Evolutionary Algorithms Laboratory (HEAL)
4 *
5 * This file is part of HeuristicLab.
6 *
7 * HeuristicLab is free software: you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation, either version 3 of the License, or
10 * (at your option) any later version.
11 *
12 * HeuristicLab is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15 * GNU General Public License for more details.
16 *
17 * You should have received a copy of the GNU General Public License
18 * along with HeuristicLab. If not, see <http://www.gnu.org/licenses/>.
19 */
20#endregion
21
22using System;
23using System.Collections.Generic;
24using System.Linq;
25using System.Text;
26using HeuristicLab.Core;
27using HeuristicLab.Operators;
28using HeuristicLab.Random;
29using HeuristicLab.Data;
30using HeuristicLab.Constraints;
31using System.Diagnostics;
32
33namespace HeuristicLab.GP {
34  /// <summary>
35  /// Implementation of a size fair crossover operator as described in:
36  /// William B. Langdon
37  /// Size Fair and Homologous Tree Genetic Programming Crossovers,
38  /// Genetic Programming and Evolvable Machines, Vol. 1, Number 1/2, pp. 95-119, April 2000
39  /// </summary>
40  public class SizeFairCrossOver : SizeConstrictedGPCrossoverBase {
41    private int MaxRecombinationTries { get { return 20; } }
42    // private data structure for crossover points
43    protected class CrossoverPoint {
44      public IFunctionTree tree;
45      public int branchSize;
46      public List<int> trail;
47    }
48
49    internal override IFunctionTree Cross(TreeGardener gardener, MersenneTwister random, IFunctionTree tree0, IFunctionTree tree1, int maxTreeSize, int maxTreeHeight) {
50      int tries = 0;
51      IFunctionTree insertedBranch = null;
52      IFunctionTree parent = null;
53      int removedBranchIndex = 0;
54      do {
55        // select a random suboperator of the 'receiving' tree
56        while (parent == null) parent = gardener.GetRandomParentNode(tree0);
57        removedBranchIndex = random.Next(parent.SubTrees.Count);
58        insertedBranch = GetReplacementBranch(random, gardener, tree0, parent, removedBranchIndex, tree1, maxTreeSize, maxTreeHeight);
59      } while (insertedBranch == null && tries++ < MaxRecombinationTries);
60
61      if (insertedBranch != null) {
62        // replace the branch below the crossoverpoint with the selected branch from root1
63        parent.RemoveSubTree(removedBranchIndex);
64        parent.InsertSubTree(removedBranchIndex, insertedBranch);
65      }
66      return tree0;
67    }
68
69    private IFunctionTree GetReplacementBranch(MersenneTwister random, TreeGardener gardener, IFunctionTree intoTree, IFunctionTree parent, int replacedBranchIndex, IFunctionTree fromTree, int maxTreeSize, int maxTreeHeight) {
70      IList<IFunction> allowedFunctions = gardener.GetAllowedSubFunctions(parent.Function, replacedBranchIndex);
71      int removedBranchSize = parent.SubTrees[replacedBranchIndex].Size;
72      int maxBranchSize = maxTreeSize - (intoTree.Size - removedBranchSize);
73      int maxBranchHeight = maxTreeHeight - gardener.GetBranchLevel(intoTree, parent);  // returns 1 if intoTree==parent and 2 if parent is a child of intoTree
74      List<int> replacedTrail = GetTrail(intoTree, parent);
75      replacedTrail.Add(replacedBranchIndex);
76
77      List<CrossoverPoint> shorterBranches = new List<CrossoverPoint>();
78      List<CrossoverPoint> longerBranches = new List<CrossoverPoint>();
79      List<CrossoverPoint> equalLengthBranches = new List<CrossoverPoint>();
80
81      FindPossibleBranches(fromTree, allowedFunctions, maxBranchSize, maxBranchHeight, removedBranchSize, shorterBranches, equalLengthBranches, longerBranches, new List<int>());
82
83      if (shorterBranches.Count > 0 && longerBranches.Count > 0) {
84        double pEqualLength = equalLengthBranches.Count > 0 ? 1.0 / removedBranchSize : 0.0;
85        double pLonger;
86        if (parent.Size == maxTreeSize) {
87          pLonger = 0.0;
88        } else {
89          pLonger = (1.0 - pEqualLength) / (longerBranches.Count * (1.0 + longerBranches.Average(p => p.branchSize) / shorterBranches.Average(p => p.branchSize)));
90        }
91        double pShorter = (1.0 - pEqualLength - pLonger);
92
93        double r = random.NextDouble();
94        if (r < pLonger) {
95          return SelectReplacement(random, replacedTrail, longerBranches);
96        } else if (r < pLonger + pShorter) {
97          return SelectReplacement(random, replacedTrail, shorterBranches);
98        } else {
99          return SelectReplacement(random, replacedTrail, equalLengthBranches);
100        }
101      } else if (equalLengthBranches.Count > 0) {
102        return SelectReplacement(random, replacedTrail, equalLengthBranches);
103      } else {
104        return null;
105      }
106    }
107
108    protected virtual IFunctionTree SelectReplacement(MersenneTwister random, List<int> replacedTrail, List<CrossoverPoint> crossoverPoints) {
109      return crossoverPoints[random.Next(crossoverPoints.Count)].tree;
110    }
111
112    private void FindPossibleBranches(IFunctionTree tree, IList<IFunction> allowedFunctions, int maxBranchSize, int maxBranchHeight, int removedBranchSize,
113      List<CrossoverPoint> shorterBranches, List<CrossoverPoint> equalLengthBranches, List<CrossoverPoint> longerBranches, List<int> trail) {
114      int treeSize = tree.Size;
115      if (allowedFunctions.Contains(tree.Function) && treeSize <= maxBranchSize && tree.Height <= maxBranchHeight) {
116        CrossoverPoint p = new CrossoverPoint();
117        p.branchSize = treeSize;
118        p.tree = tree;
119        p.trail = new List<int>(trail);
120        if (treeSize < removedBranchSize) shorterBranches.Add(p);
121        else if (treeSize > removedBranchSize) longerBranches.Add(p);
122        else equalLengthBranches.Add(p);
123      }
124      for (int i = 0; i < tree.SubTrees.Count; i++) {
125        trail.Add(i);
126        FindPossibleBranches(tree.SubTrees[i], allowedFunctions, maxBranchSize, maxBranchHeight, removedBranchSize, shorterBranches, equalLengthBranches, longerBranches, trail);
127        trail.RemoveAt(trail.Count - 1);
128      }
129    }
130
131    private List<int> GetTrail(IFunctionTree root, IFunctionTree branch) {
132      List<int> trail = new List<int>();
133      GetTrail(root, branch, trail);
134      trail.Reverse();
135      trail.RemoveAt(trail.Count - 1);
136      return trail;
137    }
138    private void GetTrail(IFunctionTree root, IFunctionTree branch, List<int> trail) {
139      if (root == branch) {
140        trail.Add(-1); // add flag that there was a match
141        return;
142      }
143
144      for (int i = 0; i < root.SubTrees.Count; i++) {
145        GetTrail(root.SubTrees[i], branch, trail);
146        if (trail.Count > 0) {
147          trail.Add(i);
148          return;
149        }
150      }
151    }
152  }
153}
Note: See TracBrowser for help on using the repository browser.