Free cookie consent management tool by TermsFeed Policy Generator

source: branches/GP-MoveOperators/HeuristicLab.Problems.DataAnalysis.Symbolic.Regression/3.4/ReplaceBranchMultiMoveGenerator.cs @ 8206

Last change on this file since 8206 was 8206, checked in by gkronber, 12 years ago

#1847: merged r8084:8205 from trunk into GP move operators branch

File size: 10.8 KB
Line 
1#region License Information
2/* HeuristicLab
3 * Copyright (C) 2002-2012 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.Common;
26using HeuristicLab.Core;
27using HeuristicLab.Data;
28using HeuristicLab.Encodings.SymbolicExpressionTreeEncoding;
29using HeuristicLab.Operators;
30using HeuristicLab.Optimization;
31using HeuristicLab.Parameters;
32using HeuristicLab.Persistence.Default.CompositeSerializers.Storable;
33
34namespace HeuristicLab.Problems.DataAnalysis.Symbolic.Regression {
35  [Item("ReplaceBranchMultiMoveGenerator", "")]
36  [StorableClass]
37  public class ReplaceBranchMultiMoveGenerator : SingleSuccessorOperator, IStochasticOperator, ISymbolicExpressionTreeMoveOperator, IMultiMoveGenerator,
38    ISymbolicDataAnalysisInterpreterOperator, ISymbolicExpressionTreeGrammarBasedOperator {
39    public ILookupParameter<IRandom> RandomParameter {
40      get { return (ILookupParameter<IRandom>)Parameters["Random"]; }
41    }
42    public IValueLookupParameter<IntValue> SampleSizeParameter {
43      get { return (IValueLookupParameter<IntValue>)Parameters["SampleSize"]; }
44    }
45    public ILookupParameter<ISymbolicDataAnalysisExpressionTreeInterpreter> SymbolicDataAnalysisTreeInterpreterParameter {
46      get { return (ILookupParameter<ISymbolicDataAnalysisExpressionTreeInterpreter>)Parameters["Interpreter"]; }
47    }
48
49    public IValueLookupParameter<ISymbolicExpressionGrammar> SymbolicExpressionTreeGrammarParameter {
50      get { return (IValueLookupParameter<ISymbolicExpressionGrammar>)Parameters["Grammar"]; }
51    }
52    public ILookupParameter<IRegressionProblemData> ProblemDataParameter {
53      get { return (ILookupParameter<IRegressionProblemData>)Parameters["ProblemData"]; }
54    }
55
56    public IntValue SampleSize {
57      get { return SampleSizeParameter.Value; }
58      set { SampleSizeParameter.Value = value; }
59    }
60    public ILookupParameter<ISymbolicExpressionTree> SymbolicExpressionTreeParameter {
61      get { return (ILookupParameter<ISymbolicExpressionTree>)Parameters["SymbolicExpressionTree"]; }
62    }
63    public ILookupParameter<ReplaceBranchMove> ReplaceBranchMoveParameter {
64      get { return (LookupParameter<ReplaceBranchMove>)Parameters["ReplaceBranchMove"]; }
65    }
66
67    public IValueParameter<IntValue> ReplacementBranchesPoolSize {
68      get { return (IValueParameter<IntValue>)Parameters["ReplacementBranchesPoolSize"]; }
69    }
70
71    public IValueParameter<IntValue> MaxReplacementBranchLength {
72      get { return (IValueParameter<IntValue>)Parameters["MaxReplacementBranchLength"]; }
73    }
74
75    public IValueParameter<IntValue> MaxReplacementBranchDepth {
76      get { return (IValueParameter<IntValue>)Parameters["MaxReplacementBranchDepth"]; }
77    }
78
79    protected ScopeParameter CurrentScopeParameter {
80      get { return (ScopeParameter)Parameters["CurrentScope"]; }
81    }
82
83    private IList<ISymbolicExpressionTree> trees;
84    private IList<double[]> treeOutput;
85
86    [StorableConstructor]
87    protected ReplaceBranchMultiMoveGenerator(bool deserializing) : base(deserializing) { }
88    protected ReplaceBranchMultiMoveGenerator(ReplaceBranchMultiMoveGenerator original, Cloner cloner) : base(original, cloner) { }
89    public ReplaceBranchMultiMoveGenerator()
90      : base() {
91      Parameters.Add(new LookupParameter<IRandom>("Random", "The random number generator."));
92      Parameters.Add(new ValueLookupParameter<IntValue>("SampleSize", "The number of moves to generate."));
93
94      Parameters.Add(new LookupParameter<ISymbolicExpressionTree>("SymbolicExpressionTree", "The symbolic expression tree for which moves should be generated."));
95      Parameters.Add(new LookupParameter<ReplaceBranchMove>("ReplaceBranchMove", "The moves that should be generated in subscopes."));
96      Parameters.Add(new ScopeParameter("CurrentScope", "The current scope where the moves should be added as subscopes."));
97      Parameters.Add(new ValueLookupParameter<ISymbolicExpressionGrammar>("Grammar"));
98      Parameters.Add(new LookupParameter<ISymbolicDataAnalysisExpressionTreeInterpreter>("Interpreter"));
99      Parameters.Add(new LookupParameter<IRegressionProblemData>("ProblemData"));
100      Parameters.Add(new ValueParameter<IntValue>("ReplacementBranchesPoolSize", new IntValue(10000)));
101      Parameters.Add(new ValueParameter<IntValue>("MaxReplacementBranchLength", new IntValue(8)));
102      Parameters.Add(new ValueParameter<IntValue>("MaxReplacementBranchDepth", new IntValue(4)));
103    }
104
105    public override IDeepCloneable Clone(Cloner cloner) {
106      return new ReplaceBranchMultiMoveGenerator(this, cloner);
107    }
108
109    public override void ClearState() {
110      trees = null;
111      treeOutput = null;
112      base.ClearState();
113    }
114
115    public override IOperation Apply() {
116      var random = RandomParameter.ActualValue;
117      if (trees == null || treeOutput == null) {
118        InitializeOperator();
119      }
120
121      var tree = SymbolicExpressionTreeParameter.ActualValue;
122
123      string moveParameterName = ReplaceBranchMoveParameter.ActualName;
124      var moveScopes = new List<Scope>();
125      int n = SampleSizeParameter.ActualValue.Value;
126
127      var moves = GenerateMoves(tree, random, n);
128
129      foreach (var m in moves) {
130        var moveScope = new Scope(moveScopes.Count.ToString());
131        moveScope.Variables.Add(new HeuristicLab.Core.Variable(moveParameterName, m));
132        moveScopes.Add(moveScope);
133      }
134      CurrentScopeParameter.ActualValue.SubScopes.AddRange(moveScopes);
135      return base.Apply();
136    }
137
138    public IEnumerable<ReplaceBranchMove> GenerateMoves(ISymbolicExpressionTree tree, IRandom random, int n) {
139      int count = 0;
140      var possibleChildren = (from parent in tree.Root.GetSubtree(0).IterateNodesPrefix()
141                              from i in Enumerable.Range(0, parent.SubtreeCount)
142                              let currentChild = parent.GetSubtree(i)
143                              select new { parent, i }).ToArray();
144
145      var root = (new ProgramRootSymbol()).CreateTreeNode();
146      var start = (new StartSymbol()).CreateTreeNode();
147      root.AddSubtree(start);
148      var t = new SymbolicExpressionTree(root);
149      var interpreter = SymbolicDataAnalysisTreeInterpreterParameter.ActualValue;
150      var ds = ProblemDataParameter.ActualValue.Dataset;
151      var rows = ProblemDataParameter.ActualValue.TrainingIndizes;
152
153      while (count < n) {
154        // select a random replacement point
155        var selected = possibleChildren[random.Next(possibleChildren.Length)];
156        // evaluate
157        start.AddSubtree(selected.parent.GetSubtree(selected.i));
158        var output = interpreter.GetSymbolicExpressionTreeValues(t, ds, rows).ToArray();
159        start.RemoveSubtree(0);
160
161        var bestTrees = new SortedList<double, Tuple<ISymbolicExpressionTree, double[]>>();
162        double bestSimilarity = 0.0;
163        // iterate over the whole pool of branches for replacement
164        for (int i = 0; i < trees.Count; i++) {
165          // if the branch is allowed in the selected point
166          if (tree.Root.Grammar.IsAllowedChildSymbol(selected.parent.Symbol, trees[i].Root.GetSubtree(0).GetSubtree(0).Symbol, selected.i)) {
167            OnlineCalculatorError error;
168            // calculate the similarity
169            double similarity = OnlinePearsonsRSquaredCalculator.Calculate(output, treeOutput[i], out error);
170            if (error != OnlineCalculatorError.None) similarity = 0.0;
171
172            // if we found a new bestSimilarity then keep the replacement branch in a sorted list (keep maximally the 30 best for this replacement point)
173            if (similarity > bestSimilarity && !similarity.IsAlmost(1.0)) {
174              bestSimilarity = similarity;
175              bestTrees.Add(similarity, Tuple.Create(trees[i], treeOutput[i]));
176              if (bestTrees.Count > 30)
177                bestTrees.RemoveAt(bestTrees.Count - 1);
178            }
179          }
180        }
181        // did not find a move better than similarity 0.0 => create a move to replace it with a random branch
182        // this is necessary to make it possible to replace branches that evaluate to NaN or infinity
183        if (bestTrees.Count == 0) {
184          int r = random.Next(trees.Count);
185          bestTrees.Add(0.0, Tuple.Create(trees[r], treeOutput[r]));
186        }
187        // yield moves (we need to add linear scaling parameters for the inserted tree)
188        foreach (var pair in bestTrees.Values) {
189          yield return
190            new ReplaceBranchMove(tree, selected.parent, selected.i, pair.Item1.Root.GetSubtree(0).GetSubtree(0), output, pair.Item2);
191          count++;
192        }
193      }
194    }
195
196    private void InitializeOperator() {
197      // init locally and set only at the end in case of exceptions
198      var trees = new List<ISymbolicExpressionTree>();
199      var treeOutput = new List<double[]>();
200      var random = RandomParameter.ActualValue;
201      var g = SymbolicExpressionTreeGrammarParameter.ActualValue;
202      var constSym = g.Symbols.Single(s => s is Constant);
203      // temporarily disable constants
204      double oldConstFreq = constSym.InitialFrequency;
205      constSym.InitialFrequency = 0.0;
206      var interpreter = SymbolicDataAnalysisTreeInterpreterParameter.ActualValue;
207      var ds = ProblemDataParameter.ActualValue.Dataset;
208      var rows = ProblemDataParameter.ActualValue.TrainingIndizes;
209      // create pool of random branches for replacement (no constants)
210      // and evaluate the output
211      // only keep trees if the output does not contain invalid values
212      var n = ReplacementBranchesPoolSize.Value.Value;
213      while (trees.Count < n) {
214        var t = ProbabilisticTreeCreator.Create(random, g, MaxReplacementBranchLength.Value.Value, MaxReplacementBranchDepth.Value.Value);
215        var output = interpreter.GetSymbolicExpressionTreeValues(t, ds, rows);
216        if (!output.Any(x => double.IsInfinity(x) || double.IsNaN(x))) {
217          trees.Add(t);
218          treeOutput.Add(output.ToArray());
219        }
220      }
221      // enable constants again
222      constSym.InitialFrequency = oldConstFreq;
223      this.trees = trees;
224      this.treeOutput = treeOutput;
225    }
226
227  }
228}
Note: See TracBrowser for help on using the repository browser.