Free cookie consent management tool by TermsFeed Policy Generator

source: branches/GP-Refactoring-713/sources/HeuristicLab.GP/3.3/Manipulation/CutOutNodeManipulation.cs @ 2210

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

GP Refactoring #713

  • introduced a plugin for GP interfaces
  • created a new interface IGeneticProgrammingModel which represents GP models in HL scopes instead of IFunctionTree
  • changed interfaces IFunction and IFunctionTree
  • moved some files to new directories (general housekeeping)
  • changed all GP operators and engines to work with IGeneticProgrammingModels
  • removed parameters TreeSize and TreeHeight in all GP operators
  • changed parameter OperatorLibrary to FunctionLibrary in all GP operators
File size: 5.3 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.Collections.Generic;
23using System.Linq;
24using HeuristicLab.Core;
25using HeuristicLab.Data;
26using HeuristicLab.Operators;
27using HeuristicLab.Random;
28using System;
29using System.Diagnostics;
30using HeuristicLab.GP.Interfaces;
31
32namespace HeuristicLab.GP {
33  public class CutOutNodeManipulation : GPManipulatorBase {
34    public override string Description {
35      get {
36        return @"Takes a tree, selects a random node of the tree and then tries to replace a random sub-tree
37of that node with one of the childs of the selected child.
38
39               O                             O
40              / \                           / \
41             O   X                         O   2
42                / \    2 is selected =>       / \
43               1   2                         4   5
44              /   / \
45             3   4   5
46";
47      }
48    }
49
50    public CutOutNodeManipulation()
51      : base() {
52    }
53
54
55    internal override IOperation Manipulate(MersenneTwister random, IGeneticProgrammingModel gpModel, FunctionLibrary library, int maxTreeSize, int maxTreeHeight, IScope scope) {
56      TreeGardener gardener = new TreeGardener(random, library);
57      IFunctionTree parent = gardener.GetRandomParentNode(gpModel.FunctionTree);
58      // parent == null means we should cut out the root node
59      // => return a random sub-tree of the root
60      if (parent == null) {
61        // when there are sub-trees then replace the old tree with a random sub-tree
62        if (gpModel.FunctionTree.SubTrees.Count > 0) {
63          gpModel.FunctionTree = gpModel.FunctionTree.SubTrees[random.Next(gpModel.FunctionTree.SubTrees.Count)];
64          Debug.Assert(gardener.IsValidTree(gpModel.FunctionTree));
65          // we reused a sub-tree so we don't have to schedule initialization operations
66          return null;
67        } else {
68          // we want to cut the root node and there are no sub-trees => create a new random terminal
69          gpModel.FunctionTree = gardener.CreateRandomTree(gardener.Terminals, 1, 1);
70          Debug.Assert(gardener.IsValidTree(gpModel.FunctionTree));
71
72          // schedule an operation to initialize the whole tree
73          return TreeGardener.CreateInitializationOperation(TreeGardener.GetAllSubTrees(gpModel.FunctionTree), scope);
74        }
75      }
76
77      // select a child to cut away
78      int childIndex = random.Next(parent.SubTrees.Count);
79      IFunctionTree child = parent.SubTrees[childIndex];
80      // match the sub-trees of the child with the allowed sub-trees of the parent
81      ICollection<IFunction> allowedFunctions = gardener.GetAllowedSubFunctions(parent.Function, childIndex);
82      IFunctionTree[] possibleChilds = child.SubTrees.Where(t => allowedFunctions.Contains(t.Function)).ToArray();
83      if (possibleChilds.Length > 0) {
84        // replace child with a random child of that child
85        IFunctionTree selectedChild = possibleChilds[random.Next(possibleChilds.Length)];
86        parent.RemoveSubTree(childIndex);
87        parent.InsertSubTree(childIndex, selectedChild);
88        Debug.Assert(gardener.IsValidTree(gpModel.FunctionTree));
89        // recalculate the size and height of our tree
90        gpModel.Size = gpModel.FunctionTree.GetSize();
91        gpModel.Height = gpModel.FunctionTree.GetHeight();
92        // don't need to schedule initialization operations
93        return null;
94      } else {
95        // can't reuse an existing branch => create a new tree
96        // determine the level of the parent
97        int parentLevel = gardener.GetBranchLevel(gpModel.FunctionTree, parent);
98        // first remove the old child (first step essential!)
99        parent.RemoveSubTree(childIndex);
100        // then determine the number of nodes left over after the child has been removed!
101        int remainingNodes = gpModel.FunctionTree.GetSize();
102        allowedFunctions = gardener.GetAllowedSubFunctions(parent.Function, childIndex);
103        IFunctionTree newFunctionTree = gardener.CreateRandomTree(allowedFunctions, maxTreeSize - remainingNodes, maxTreeHeight - parentLevel);
104        parent.InsertSubTree(childIndex, newFunctionTree);
105        Debug.Assert(gardener.IsValidTree(gpModel.FunctionTree));
106        // recalculate size and height
107        gpModel.Size = gpModel.FunctionTree.GetSize();
108        gpModel.Height = gpModel.FunctionTree.GetHeight();
109        // schedule an initialization operation for the new function-tree
110        return TreeGardener.CreateInitializationOperation(TreeGardener.GetAllSubTrees(newFunctionTree), scope);
111      }
112    }
113  }
114}
Note: See TracBrowser for help on using the repository browser.