Free cookie consent management tool by TermsFeed Policy Generator

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

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

merged FunctionsAndStructIdRefactoring-branch (r142, r143, r144, r145, r146, r147, r148, r149, r152, r153) back into the trunk (ticket #112)

File size: 12.8 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.MANIPULATION) == null) {
44        CombinedOperator manipulationOperator = new CombinedOperator();
45        SequentialProcessor manipulationSequence = new SequentialProcessor();
46        foreach(IVariableInfo variableInfo in localVariableInfos) {
47          IOperator manipulator = GetDefaultManipulationOperator(variableInfo);
48          if (manipulator != null) {
49            manipulationSequence.AddSubOperator(manipulator);
50          }
51        }
52        if(manipulationSequence.SubOperators.Count > 0) {
53          op.AddVariable(new Variable(GPOperatorLibrary.MANIPULATION, manipulationOperator));
54
55          manipulationOperator.OperatorGraph.AddOperator(manipulationSequence);
56          manipulationOperator.OperatorGraph.InitialOperator = manipulationSequence;
57          foreach(IOperator subOp in manipulationSequence.SubOperators) {
58            manipulationOperator.OperatorGraph.AddOperator(subOp);
59          }
60        }
61      }
62
63      if(op.GetVariable(GPOperatorLibrary.INITIALIZATION) == null) {
64        CombinedOperator initOperator = new CombinedOperator();
65        SequentialProcessor initSequence = new SequentialProcessor();
66        foreach(IVariableInfo variableInfo in localVariableInfos) {
67          IOperator initializer = GetDefaultInitOperator(variableInfo);
68          if (initializer != null) {
69            initSequence.AddSubOperator(initializer);
70          }
71        }
72        if(initSequence.SubOperators.Count > 0) {
73          op.AddVariable(new Variable(GPOperatorLibrary.INITIALIZATION, initOperator));
74          initOperator.OperatorGraph.AddOperator(initSequence);
75          initOperator.OperatorGraph.InitialOperator = initSequence;
76          foreach(IOperator subOp in initSequence.SubOperators) {
77            initOperator.OperatorGraph.AddOperator(subOp);
78          }
79        }
80      }
81
82      // add a new typeid if necessary
83      if(op.GetVariable(GPOperatorLibrary.TYPE_ID) == null) {
84        op.AddVariable(new Variable(GPOperatorLibrary.TYPE_ID, new StringData(Guid.NewGuid().ToString())));
85      }
86
87      if(op.GetVariable(GPOperatorLibrary.MIN_TREE_HEIGHT) == null) {
88        op.AddVariable(new Variable(GPOperatorLibrary.MIN_TREE_HEIGHT, new IntData(-1)));
89      }
90      if(op.GetVariable(GPOperatorLibrary.MIN_TREE_SIZE) == null) {
91        op.AddVariable(new Variable(GPOperatorLibrary.MIN_TREE_SIZE, new IntData(-1)));
92      }
93      if(op.GetVariable(GPOperatorLibrary.ALLOWED_SUBOPERATORS) == null) {
94        op.AddVariable(new Variable(GPOperatorLibrary.ALLOWED_SUBOPERATORS, new ItemList()));
95      }
96
97      RecalculateAllowedSuboperators();
98      RecalculateMinimalTreeBounds();
99
100      OnOperatorAdded(op);
101    }
102
103
104    private Dictionary<string, int> minTreeHeight = new Dictionary<string, int>();
105    private Dictionary<string, int> minTreeSize = new Dictionary<string, int>();
106    private SubOperatorsConstraintAnalyser constraintAnalyser = new SubOperatorsConstraintAnalyser();
107
108    private void RecalculateAllowedSuboperators() {
109      foreach(IOperator op in Operators) {
110        RecalculateAllowedSuboperators(op);
111      }
112    }
113
114    private void RecalculateAllowedSuboperators(IOperator op) {
115      constraintAnalyser.AllPossibleOperators = Operators;
116      int minArity;
117      int maxArity;
118      GetMinMaxArity(op, out minArity, out maxArity);
119      var slotsList = (ItemList)op.GetVariable(GPOperatorLibrary.ALLOWED_SUBOPERATORS).Value;
120      slotsList.Clear();
121      for(int i = 0; i < maxArity; i++) {
122        ItemList slotList = new ItemList();
123        foreach(IOperator allowedOp in constraintAnalyser.GetAllowedOperators(op, i)) {
124          slotList.Add(allowedOp);
125        }
126        slotsList.Add(slotList);
127      }
128    }
129
130
131    private void RecalculateMinimalTreeBounds() {
132      minTreeHeight.Clear();
133      minTreeSize.Clear();
134      constraintAnalyser.AllPossibleOperators = Operators;
135
136      foreach(IOperator op in Operators) {
137        ((IntData)op.GetVariable(GPOperatorLibrary.MIN_TREE_HEIGHT).Value).Data = RecalculateMinimalTreeHeight(op);
138        ((IntData)op.GetVariable(GPOperatorLibrary.MIN_TREE_SIZE).Value).Data = RecalculateMinimalTreeSize(op);
139      }
140    }
141
142    private int RecalculateMinimalTreeSize(IOperator op) {
143      string typeId = GetTypeId(op);
144      // check for memoized value
145      if(minTreeSize.ContainsKey(typeId)) {
146        return minTreeSize[typeId];
147      }
148
149      int minArity;
150      int maxArity;
151      GetMinMaxArity(op, out minArity, out maxArity);
152      // no suboperators possible => minimalTreeSize == 1 (the current node)
153      if(minArity == 0 && maxArity == 0) {
154        minTreeSize[typeId] = 1;
155        return 1;
156      }
157
158      // when suboperators are necessary we have to find the smallest possible tree (recursively)
159      // the minimal size of the parent is 1 + the sum of the minimal sizes of all subtrees
160      int subTreeSizeSum = 0;
161
162      // mark the currently processed operator to prevent infinite recursions and stack overflow
163      minTreeSize[typeId] = 9999;
164      for(int i = 0; i < minArity; i++) {
165        // calculate the minTreeSize of all allowed sub-operators
166        // if the list of allowed suboperators is empty because the operator needs suboperators
167        // but there are no valid suboperators defined in the current group then we just use an impossible
168        // tree size here to indicate that there was a problem.
169        // usually as more operators are added to the group the problem will be corrected (by adding the missing operator).
170        // however if the missing operator is never added the high min tree size here has the effect that this operator
171        // will not be included in generated subtrees because the resulting size would always be higher than a reasonably set
172        // maximal tree size.
173        int minSubTreeSize = constraintAnalyser.GetAllowedOperators(op, i).Select(subOp => RecalculateMinimalTreeSize(subOp))
174          .Concat(Enumerable.Repeat(9999, 1)).Min();
175        subTreeSizeSum += minSubTreeSize;
176      }
177
178      minTreeSize[typeId] = subTreeSizeSum + 1;
179      return subTreeSizeSum + 1;
180    }
181
182
183    private int RecalculateMinimalTreeHeight(IOperator op) {
184      string typeId = GetTypeId(op);
185      // check for memoized value
186      if(minTreeHeight.ContainsKey(typeId)) {
187        return minTreeHeight[typeId];
188      }
189
190      int minArity;
191      int maxArity;
192      GetMinMaxArity(op, out minArity, out maxArity);
193      // no suboperators possible => minimalTreeHeight == 1
194      if(minArity == 0 && maxArity == 0) {
195        minTreeHeight[typeId] = 1;
196        return 1;
197      }
198
199      // when suboperators are necessary we have to find the smallest possible tree (recursively)
200      // the minimal height of the parent is 1 + the height of the largest subtree
201      int maxSubTreeHeight = 0;
202
203      // mark the currently processed operator to prevent infinite recursions leading to stack overflow
204      minTreeHeight[typeId] = 9999;
205      for(int i = 0; i < minArity; i++) {
206        // calculate the minTreeHeight of all possible sub-operators.
207        // use the smallest possible subTree as lower bound for the subTreeHeight.
208        // if the list of allowed suboperators is empty because the operator needs suboperators
209        // but there are no valid suboperators defined in the current group then we use an impossible tree height
210        // to indicate that there was a problem.
211        // usually as more operators are added to the group the problem will be corrected (by adding the missing operator).
212        // however if the missing operator is never added the high min tree height here has the effect that this operator
213        // will not be included in generated subtrees because the resulting (virtual) height would always be higher than a reasonably set
214        // maximal tree height.
215        int minSubTreeHeight = constraintAnalyser.GetAllowedOperators(op, i).Select(subOp => RecalculateMinimalTreeHeight(subOp))
216          .Concat(Enumerable.Repeat(9999, 1)).Min();
217
218        // if the smallest height of this subtree is larger than all other subtrees before we have to update the min height of the parent
219        if(minSubTreeHeight > maxSubTreeHeight) {
220          maxSubTreeHeight = minSubTreeHeight;
221        }
222      }
223
224      minTreeHeight[typeId] = maxSubTreeHeight + 1;
225      return maxSubTreeHeight + 1;
226    }
227
228    private void GetMinMaxArity(IOperator op, out int minArity, out int maxArity) {
229      foreach(IConstraint constraint in op.Constraints) {
230        NumberOfSubOperatorsConstraint theConstraint = constraint as NumberOfSubOperatorsConstraint;
231        if(theConstraint != null) {
232          minArity = theConstraint.MinOperators.Data;
233          maxArity = theConstraint.MaxOperators.Data;
234          return;
235        }
236      }
237      // the default arity is 2
238      minArity = 2;
239      maxArity = 2;
240    }
241
242    private string GetTypeId(IOperator op) {
243      return ((StringData)op.GetVariable(GPOperatorLibrary.TYPE_ID).Value).Data;
244    }
245
246
247    private IOperator GetDefaultManipulationOperator(IVariableInfo variableInfo) {
248      IOperator shaker;
249      if(variableInfo.DataType == typeof(ConstrainedDoubleData) ||
250        variableInfo.DataType == typeof(ConstrainedIntData) ||
251        variableInfo.DataType == typeof(DoubleData) ||
252        variableInfo.DataType == typeof(IntData)) {
253        shaker = new UniformRandomAdder();
254      } else {
255        return null;
256      }
257      shaker.GetVariableInfo("Value").ActualName = variableInfo.FormalName;
258      shaker.Name = variableInfo.FormalName + " manipulation";
259      return shaker;
260    }
261
262    private IOperator GetDefaultInitOperator(IVariableInfo variableInfo) {
263      IOperator shaker;
264      if(variableInfo.DataType == typeof(ConstrainedDoubleData) ||
265        variableInfo.DataType == typeof(ConstrainedIntData) ||
266        variableInfo.DataType == typeof(DoubleData) ||
267        variableInfo.DataType == typeof(IntData)) {
268        shaker = new UniformRandomizer();
269      } else {
270        return null;
271      }
272      shaker.GetVariableInfo("Value").ActualName = variableInfo.FormalName;
273      shaker.Name = variableInfo.FormalName + " initialization";
274      return shaker;
275    }
276
277    public override void AddSubGroup(IOperatorGroup group) {
278      throw new NotSupportedException();
279    }
280
281    public override void RemoveOperator(IOperator op) {
282      base.RemoveOperator(op);
283
284      op.RemoveVariable(GPOperatorLibrary.MANIPULATION);
285      op.RemoveVariable(GPOperatorLibrary.INITIALIZATION);
286      op.RemoveVariable(GPOperatorLibrary.TYPE_ID);
287      op.RemoveVariable(GPOperatorLibrary.MIN_TREE_SIZE);
288      op.RemoveVariable(GPOperatorLibrary.MIN_TREE_HEIGHT);
289      op.RemoveVariable(GPOperatorLibrary.ALLOWED_SUBOPERATORS);
290
291      OnOperatorRemoved(op);
292    }
293
294    public override void RemoveSubGroup(IOperatorGroup group) {
295      throw new NotSupportedException();
296    }
297
298    public event EventHandler OperatorAdded;
299    public event EventHandler OperatorRemoved;
300
301    protected virtual void OnOperatorAdded(IOperator op) {
302      if(OperatorAdded != null) {
303        OperatorAdded(this, new OperatorEventArgs(op));
304      }
305    }
306    protected virtual void OnOperatorRemoved(IOperator op) {
307      if(OperatorRemoved != null) {
308        OperatorRemoved(this, new OperatorEventArgs(op));
309      }
310    }
311  }
312
313
314  internal class OperatorEventArgs : EventArgs {
315    public IOperator op;
316
317    public OperatorEventArgs(IOperator op) {
318      this.op = op;
319    }
320  }
321}
Note: See TracBrowser for help on using the repository browser.