Free cookie consent management tool by TermsFeed Policy Generator

source: trunk/sources/HeuristicLab.StructureIdentification/Manipulation/SubstituteSubTreeManipulation.cs @ 23

Last change on this file since 23 was 23, checked in by gkronber, 16 years ago

changed boolean variable BalanceTrees to double BalancedTreesRate (ticket #11)

File size: 6.5 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 HeuristicLab.Core;
26using HeuristicLab.Data;
27using HeuristicLab.Operators;
28using HeuristicLab.Random;
29
30namespace HeuristicLab.StructureIdentification {
31  public class SubstituteSubTreeManipulation : OperatorBase {
32
33    public override string Description {
34      get { return "Selects a random node of the tree and replaces it with randomly initialized subtree."; }
35    }
36
37    public SubstituteSubTreeManipulation()
38      : base() {
39      AddVariableInfo(new VariableInfo("Random", "Uniform random number generator", typeof(MersenneTwister), VariableKind.In));
40      AddVariableInfo(new VariableInfo("OperatorLibrary", "The operator library containing all available operators", typeof(GPOperatorLibrary), VariableKind.In));
41      AddVariableInfo(new VariableInfo("MaxTreeHeight", "The maximal allowed height of the tree", typeof(IntData), VariableKind.In));
42      AddVariableInfo(new VariableInfo("MaxTreeSize", "The maximal allowed size (number of nodes) of the tree", typeof(IntData), VariableKind.In));
43      AddVariableInfo(new VariableInfo("BalancedTreesRate", "Determines how many trees should be balanced", typeof(DoubleData), VariableKind.In));
44      AddVariableInfo(new VariableInfo("OperatorTree", "The tree to manipulate", typeof(IOperator), VariableKind.In));
45      AddVariableInfo(new VariableInfo("TreeSize", "The size (number of nodes) of the tree", typeof(IntData), VariableKind.In));
46      AddVariableInfo(new VariableInfo("TreeHeight", "The height of the tree", typeof(IntData), VariableKind.In));
47    }
48
49    public override IOperation Apply(IScope scope) {
50      IOperator rootOperator = GetVariableValue<IOperator>("OperatorTree", scope, true);
51
52      MersenneTwister random = GetVariableValue<MersenneTwister>("Random", scope, true);
53      GPOperatorLibrary library = GetVariableValue<GPOperatorLibrary>("OperatorLibrary", scope, true);
54      int maxTreeHeight = GetVariableValue<IntData>("MaxTreeHeight", scope, true).Data;
55      int maxTreeSize = GetVariableValue<IntData>("MaxTreeSize", scope, true).Data;
56      double balancedTreesRate = GetVariableValue<DoubleData>("BalancedTreesRate", scope, true).Data;
57      int treeSize = GetVariableValue<IntData>("TreeSize", scope, true).Data;
58      int treeHeight = GetVariableValue<IntData>("TreeHeight", scope, true).Data;
59
60      TreeGardener gardener = new TreeGardener(random, library);
61
62      IOperator parent = gardener.GetRandomParentNode(rootOperator);
63      if(parent == null) {
64        // parent == null means we should subsitute the whole tree
65        // => create a new random tree
66
67        // create a new random operator tree
68
69        IOperator newOperatorTree;
70        if(random.NextDouble() <= balancedTreesRate) {
71          newOperatorTree = gardener.CreateRandomTree(gardener.AllOperators, maxTreeSize, maxTreeHeight, true);
72        } else {
73          newOperatorTree = gardener.CreateRandomTree(gardener.AllOperators, maxTreeSize, maxTreeHeight, false);
74        }
75
76        if(!gardener.IsValidTree(newOperatorTree)) {
77          throw new InvalidProgramException();
78        }
79
80        // update the variables in the scope with the new values
81        GetVariableValue<IntData>("TreeSize", scope, true).Data = gardener.GetTreeSize(newOperatorTree);
82        GetVariableValue<IntData>("TreeHeight", scope, true).Data = gardener.GetTreeHeight(newOperatorTree);
83        scope.GetVariable("OperatorTree").Value = newOperatorTree;
84       
85        // return a CompositeOperation that randomly initializes the new operator
86        return gardener.CreateInitializationOperation(gardener.GetAllOperators(newOperatorTree), scope);
87      } else {
88        // determine a random child of the parent to be replaced
89        int childIndex = random.Next(parent.SubOperators.Count);
90
91        // get the list of allowed suboperators as the new child
92        IList<IOperator> allowedOperators = gardener.GetAllowedSubOperators(parent, childIndex);
93
94        if(allowedOperators.Count == 0) {
95          // don't change anything
96          // this shouldn't happen
97          throw new InvalidProgramException();
98        }
99
100        // calculate the maximum size and height of the new sub-tree based on the location where
101        // it will be inserted
102        int parentLevel = gardener.GetNodeLevel(rootOperator, parent);
103
104        int maxSubTreeHeight = maxTreeHeight - parentLevel;
105        int maxSubTreeSize = maxTreeSize - (treeSize - gardener.GetTreeSize(parent.SubOperators[childIndex]));
106
107        // get a random operatorTree
108        IOperator newOperatorTree;
109        if(random.NextDouble() <= balancedTreesRate) {
110          newOperatorTree = gardener.CreateRandomTree(allowedOperators, maxSubTreeSize, maxSubTreeHeight, true);
111        } else {
112          newOperatorTree = gardener.CreateRandomTree(allowedOperators, maxSubTreeSize, maxSubTreeHeight, false);
113        }
114
115        IOperator oldChild = parent.SubOperators[childIndex];
116        parent.RemoveSubOperator(childIndex);
117        parent.AddSubOperator(newOperatorTree, childIndex);
118
119        if(!gardener.IsValidTree(rootOperator)) {
120          throw new InvalidProgramException();
121        }
122
123        // update the values of treeSize and treeHeight
124        GetVariableValue<IntData>("TreeSize", scope, true).Data = gardener.GetTreeSize(rootOperator);
125        GetVariableValue<IntData>("TreeHeight", scope, true).Data = gardener.GetTreeHeight(rootOperator);
126        // the root operator hasn't changed so we don't need to update
127
128        // return a CompositeOperation that randomly initializes all nodes of the new subtree
129        return gardener.CreateInitializationOperation(gardener.GetAllOperators(newOperatorTree), scope);
130      }
131    }
132  }
133}
Note: See TracBrowser for help on using the repository browser.