Free cookie consent management tool by TermsFeed Policy Generator

source: trunk/sources/HeuristicLab.StructureIdentification/GPOperatorGroup.cs @ 430

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

removed 'TypeIds' for functions (also a relic of an old design) (ticket #225)

File size: 9.4 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.Data;
29using HeuristicLab.Random;
30using HeuristicLab.Constraints;
31
32namespace HeuristicLab.StructureIdentification {
33  public class GPOperatorGroup : OperatorGroup {
34    public GPOperatorGroup()
35      : base() {
36    }
37
38    public override void AddOperator(IOperator op) {
39      base.AddOperator(op);
40
41      var localVariableInfos = op.VariableInfos.Where(f => f.Local);
42
43      if(op.GetVariable(GPOperatorLibrary.MIN_TREE_HEIGHT) == null) {
44        op.AddVariable(new Variable(GPOperatorLibrary.MIN_TREE_HEIGHT, new IntData(-1)));
45      }
46      if(op.GetVariable(GPOperatorLibrary.MIN_TREE_SIZE) == null) {
47        op.AddVariable(new Variable(GPOperatorLibrary.MIN_TREE_SIZE, new IntData(-1)));
48      }
49      if(op.GetVariable(GPOperatorLibrary.ALLOWED_SUBOPERATORS) == null) {
50        op.AddVariable(new Variable(GPOperatorLibrary.ALLOWED_SUBOPERATORS, new ItemList()));
51      }
52      if(op.GetVariable(GPOperatorLibrary.TICKETS) == null) {
53        op.AddVariable(new Variable(GPOperatorLibrary.TICKETS, new DoubleData(1.0)));
54      }
55      OnOperatorAdded(op);
56    }
57
58
59    private Dictionary<IOperator, int> minTreeHeight = new Dictionary<IOperator, int>();
60    private Dictionary<IOperator, int> minTreeSize = new Dictionary<IOperator, int>();
61    private SubOperatorsConstraintAnalyser constraintAnalyser = new SubOperatorsConstraintAnalyser();
62
63    private void RecalculateAllowedSuboperators() {
64      foreach(IOperator op in Operators) {
65        RecalculateAllowedSuboperators(op);
66      }
67    }
68
69    private void RecalculateAllowedSuboperators(IOperator op) {
70      constraintAnalyser.AllPossibleOperators = Operators;
71      int minArity;
72      int maxArity;
73      GetMinMaxArity(op, out minArity, out maxArity);
74      var slotsList = (ItemList)op.GetVariable(GPOperatorLibrary.ALLOWED_SUBOPERATORS).Value;
75      slotsList.Clear();
76      for(int i = 0; i < maxArity; i++) {
77        ItemList slotList = new ItemList();
78        foreach(IOperator allowedOp in constraintAnalyser.GetAllowedOperators(op, i)) {
79          slotList.Add(allowedOp);
80        }
81        slotsList.Add(slotList);
82      }
83    }
84
85
86    private void RecalculateMinimalTreeBounds() {
87      minTreeHeight.Clear();
88      minTreeSize.Clear();
89      constraintAnalyser.AllPossibleOperators = Operators;
90
91      foreach(IOperator op in Operators) {
92        ((IntData)op.GetVariable(GPOperatorLibrary.MIN_TREE_HEIGHT).Value).Data = RecalculateMinimalTreeHeight(op);
93        ((IntData)op.GetVariable(GPOperatorLibrary.MIN_TREE_SIZE).Value).Data = RecalculateMinimalTreeSize(op);
94      }
95    }
96
97    private int RecalculateMinimalTreeSize(IOperator op) {
98      // check for memoized value
99      if(minTreeSize.ContainsKey(op)) {
100        return minTreeSize[op];
101      }
102
103      int minArity;
104      int maxArity;
105      GetMinMaxArity(op, out minArity, out maxArity);
106      // no suboperators possible => minimalTreeSize == 1 (the current node)
107      if(minArity == 0 && maxArity == 0) {
108        minTreeSize[op] = 1;
109        return 1;
110      }
111
112      // when suboperators are necessary we have to find the smallest possible tree (recursively)
113      // the minimal size of the parent is 1 + the sum of the minimal sizes of all subtrees
114      int subTreeSizeSum = 0;
115
116      // mark the currently processed operator to prevent infinite recursions and stack overflow
117      minTreeSize[op] = 9999;
118      for(int i = 0; i < minArity; i++) {
119        // calculate the minTreeSize of all allowed sub-operators
120        // if the list of allowed suboperators is empty because the operator needs suboperators
121        // but there are no valid suboperators defined in the current group then we just use an impossible
122        // tree size here to indicate that there was a problem.
123        // usually as more operators are added to the group the problem will be corrected (by adding the missing operator).
124        // however if the missing operator is never added the high min tree size here has the effect that this operator
125        // will not be included in generated subtrees because the resulting size would always be higher than a reasonably set
126        // maximal tree size.
127        int minSubTreeSize = constraintAnalyser.GetAllowedOperators(op, i).Select(subOp => RecalculateMinimalTreeSize(subOp))
128          .Concat(Enumerable.Repeat(9999, 1)).Min();
129        subTreeSizeSum += minSubTreeSize;
130      }
131
132      minTreeSize[op] = subTreeSizeSum + 1;
133      return subTreeSizeSum + 1;
134    }
135
136
137    private int RecalculateMinimalTreeHeight(IOperator op) {
138      // check for memoized value
139      if(minTreeHeight.ContainsKey(op)) {
140        return minTreeHeight[op];
141      }
142
143      int minArity;
144      int maxArity;
145      GetMinMaxArity(op, out minArity, out maxArity);
146      // no suboperators possible => minimalTreeHeight == 1
147      if(minArity == 0 && maxArity == 0) {
148        minTreeHeight[op] = 1;
149        return 1;
150      }
151
152      // when suboperators are necessary we have to find the smallest possible tree (recursively)
153      // the minimal height of the parent is 1 + the height of the largest subtree
154      int maxSubTreeHeight = 0;
155
156      // mark the currently processed operator to prevent infinite recursions leading to stack overflow
157      minTreeHeight[op] = 9999;
158      for(int i = 0; i < minArity; i++) {
159        // calculate the minTreeHeight of all possible sub-operators.
160        // use the smallest possible subTree as lower bound for the subTreeHeight.
161        // if the list of allowed suboperators is empty because the operator needs suboperators
162        // but there are no valid suboperators defined in the current group then we use an impossible tree height
163        // to indicate that there was a problem.
164        // usually as more operators are added to the group the problem will be corrected (by adding the missing operator).
165        // however if the missing operator is never added the high min tree height here has the effect that this operator
166        // will not be included in generated subtrees because the resulting (virtual) height would always be higher than a reasonably set
167        // maximal tree height.
168        int minSubTreeHeight = constraintAnalyser.GetAllowedOperators(op, i).Select(subOp => RecalculateMinimalTreeHeight(subOp))
169          .Concat(Enumerable.Repeat(9999, 1)).Min();
170
171        // if the smallest height of this subtree is larger than all other subtrees before we have to update the min height of the parent
172        if(minSubTreeHeight > maxSubTreeHeight) {
173          maxSubTreeHeight = minSubTreeHeight;
174        }
175      }
176
177      minTreeHeight[op] = maxSubTreeHeight + 1;
178      return maxSubTreeHeight + 1;
179    }
180
181    private void GetMinMaxArity(IOperator op, out int minArity, out int maxArity) {
182      foreach(IConstraint constraint in op.Constraints) {
183        NumberOfSubOperatorsConstraint theConstraint = constraint as NumberOfSubOperatorsConstraint;
184        if(theConstraint != null) {
185          minArity = theConstraint.MinOperators.Data;
186          maxArity = theConstraint.MaxOperators.Data;
187          return;
188        }
189      }
190      // the default arity is 2
191      minArity = 2;
192      maxArity = 2;
193    }
194
195    public override void AddSubGroup(IOperatorGroup group) {
196      throw new NotSupportedException();
197    }
198
199    public override void RemoveOperator(IOperator op) {
200      base.RemoveOperator(op);
201      op.RemoveVariable(GPOperatorLibrary.MIN_TREE_SIZE);
202      op.RemoveVariable(GPOperatorLibrary.MIN_TREE_HEIGHT);
203      op.RemoveVariable(GPOperatorLibrary.ALLOWED_SUBOPERATORS);
204      op.RemoveVariable(GPOperatorLibrary.TICKETS);
205      OnOperatorRemoved(op);
206    }
207
208    public override void RemoveSubGroup(IOperatorGroup group) {
209      throw new NotSupportedException();
210    }
211
212    public event EventHandler OperatorAdded;
213    public event EventHandler OperatorRemoved;
214
215    protected virtual void OnOperatorAdded(IOperator op) {
216      if(OperatorAdded != null) {
217        OperatorAdded(this, new OperatorEventArgs(op));
218      }
219    }
220    protected virtual void OnOperatorRemoved(IOperator op) {
221      if(OperatorRemoved != null) {
222        OperatorRemoved(this, new OperatorEventArgs(op));
223      }
224    }
225
226    internal void Prepare() {
227      RecalculateAllowedSuboperators();
228      RecalculateMinimalTreeBounds();
229    }
230  }
231
232
233  internal class OperatorEventArgs : EventArgs {
234    public IOperator op;
235
236    public OperatorEventArgs(IOperator op) {
237      this.op = op;
238    }
239  }
240}
Note: See TracBrowser for help on using the repository browser.