Free cookie consent management tool by TermsFeed Policy Generator

source: branches/2966_interval_calculation/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/Interpreter/IntervalInterpreter.cs @ 16331

Last change on this file since 16331 was 16331, checked in by chaider, 6 years ago

#2966: Changed Evaluate method (changed intervals parameter to optional)

File size: 11.1 KB
Line 
1#region License Information
2/* HeuristicLab
3 * Copyright (C) 2002-2018 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.Persistence.Default.CompositeSerializers.Storable;
30using HeuristicLab.Problems.DataAnalysis;
31using HeuristicLab.Problems.DataAnalysis.Symbolic;
32
33namespace HeuristicLab.Algorithms.DataAnalysis.Symbolic {
34  [StorableClass]
35  [Item("IntervalInterpreter", "Intperter for calculation of intervals of symbolic models.")]
36  public sealed class IntervalInterpreter : ParameterizedNamedItem, IStatefulItem {
37
38    private const string EvaluatedSolutionsParameterName = "EvaluatedSolutions";
39    private static int InstructionCount = 0;
40
41    public IFixedValueParameter<IntValue> EvaluatedSolutionsParameter {
42      get { return (IFixedValueParameter<IntValue>)Parameters[EvaluatedSolutionsParameterName]; }
43    }
44
45    public int EvaluatedSolutions {
46      get { return EvaluatedSolutionsParameter.Value.Value; }
47      set { EvaluatedSolutionsParameter.Value.Value = value; }
48    }
49
50    private IntervalInterpreter(bool deserializing) : base(deserializing) { }
51    private IntervalInterpreter(IntervalInterpreter original, Cloner cloner)
52        : base(original, cloner) { }
53
54    public IntervalInterpreter()
55        : base("IntervalInterpreter", "Intperter for calculation of intervals of symbolic models.") { }
56
57    public override IDeepCloneable Clone(Cloner cloner) {
58      return new IntervalInterpreter(this, cloner);
59    }
60
61    private readonly object syncRoot = new object();
62
63    #region IStatefulItem Members
64    public void InitializeState() {
65      EvaluatedSolutions = 0;
66    }
67    public void ClearState() { }
68    #endregion
69
70    private static void ResetInstrucitonCount() {
71      InstructionCount = 0;
72    }
73
74
75    public Interval GetSymbolicExressionTreeIntervals(ISymbolicExpressionTree tree, IDataset dataset, IEnumerable<int> rows = null) {
76      lock (syncRoot) {
77        EvaluatedSolutions++;
78        ResetInstrucitonCount();
79      }
80      var instructions = PrepareInterpreterState(tree, rows, dataset);
81      var x = Evaluate(instructions);
82
83      return x;
84    }
85
86    public Interval GetSymbolicExressionTreeIntervals(ISymbolicExpressionTree tree, Dictionary<string, Interval> customIntervals, IEnumerable<int> rows = null) {
87      lock (syncRoot) {
88        EvaluatedSolutions++;
89        ResetInstrucitonCount();
90      }
91      var instructions = PrepareInterpreterState(tree, rows, null, customIntervals);
92      var x = Evaluate(instructions);
93
94      return x;
95    }
96
97    public Interval GetSymbolicExressionTreeIntervals(ISymbolicExpressionTree tree, IDataset dataset,
98      Dictionary<string, Interval> customIntervals, out Dictionary<ISymbolicExpressionTreeNode, Interval> intervals, IEnumerable<int> rows = null) {
99      lock (syncRoot) {
100        EvaluatedSolutions++;
101        ResetInstrucitonCount();
102      }
103      intervals = new Dictionary<ISymbolicExpressionTreeNode, Interval>();
104      var instructions = PrepareInterpreterState(tree, rows, dataset, customIntervals);
105      var x = Evaluate(instructions, intervals);
106
107      return x;
108    }
109
110    public Interval GetSymbolicExressionTreeIntervals(ISymbolicExpressionTree tree, IDataset dataset,
111      out Dictionary<ISymbolicExpressionTreeNode, Interval> intervals, IEnumerable<int> rows = null) {
112      lock(syncRoot) {
113        EvaluatedSolutions++;
114        ResetInstrucitonCount();
115      }
116      intervals = new Dictionary<ISymbolicExpressionTreeNode, Interval>();
117      var instructions = PrepareInterpreterState(tree, rows, dataset);
118      var x = Evaluate(instructions, intervals);
119
120      return x;
121    }
122
123    public Interval GetSymbolicExressionTreeIntervals(ISymbolicExpressionTree tree, Dictionary<string, Interval> customIntervals,
124      out Dictionary<ISymbolicExpressionTreeNode, Interval> intervals, IEnumerable<int> rows = null) {
125      lock (syncRoot) {
126        EvaluatedSolutions++;
127        ResetInstrucitonCount();
128      }
129      intervals = new Dictionary<ISymbolicExpressionTreeNode, Interval>();
130      var instructions = PrepareInterpreterState(tree, rows, null, customIntervals);
131      var x = Evaluate(instructions, intervals);
132
133      return x;
134    }
135
136    private static Instruction[] PrepareInterpreterState(ISymbolicExpressionTree tree,
137      IEnumerable<int> rows = null, IDataset dataset = null, Dictionary<string, Interval> customIntervals = null) {
138      Instruction[] code = SymbolicExpressionTreeCompiler.Compile(tree, OpCodes.MapSymbolToOpCode);
139
140      if (dataset == null && customIntervals == null)
141        throw new Exception("No dataset or ranges for intervals are given!");
142
143      if(rows == null)
144        rows = Enumerable.Range(0, dataset.Rows);
145
146      foreach (Instruction instr in code) {
147        if (instr.opCode == OpCodes.Variable) {
148          var variableTreeNode = (VariableTreeNode)instr.dynamicNode;
149          IList<double> values = new List<double>();
150
151          if (customIntervals != null) {
152            if (customIntervals.ContainsKey(variableTreeNode.VariableName)) {
153              instr.data = customIntervals[variableTreeNode.VariableName];
154            }
155          } else {
156            foreach (var rowEnum in rows) {
157              values.Add(dataset.GetReadOnlyDoubleValues(variableTreeNode.VariableName)[rowEnum]);
158            }
159            instr.data = new Interval(values.Min(), values.Max());
160          }
161        }
162      }
163      return code;
164    }
165
166    private Interval Evaluate(Instruction[] instructions, Dictionary<ISymbolicExpressionTreeNode, Interval> intervals = null) {
167      Instruction currentInstr = instructions[InstructionCount++];
168      Interval intermediate = null;
169
170      switch (currentInstr.opCode) {
171        //Elementary arithmetic rules
172        case OpCodes.Add: {
173            intermediate = Evaluate(instructions, intervals);
174            for (int i = 1; i < currentInstr.nArguments; i++) {
175              intermediate = Interval.Add(intermediate, Evaluate(instructions, intervals));
176            }
177            break;
178          }
179        case OpCodes.Sub: {
180            intermediate = Evaluate(instructions, intervals);
181            for (int i = 1; i < currentInstr.nArguments; i++) {
182              intermediate = Interval.Subtract(intermediate, Evaluate(instructions, intervals));
183            }
184            break;
185          }
186        case OpCodes.Mul: {
187            intermediate = Evaluate(instructions, intervals);
188            for (int i = 1; i < currentInstr.nArguments; i++) {
189              intermediate = Interval.Multiply(intermediate, Evaluate(instructions, intervals));
190            }
191            break;
192          }
193        case OpCodes.Div: {
194            intermediate = Evaluate(instructions, intervals);
195            for (int i = 1; i < currentInstr.nArguments; i++) {
196              intermediate = Interval.Divide(intermediate, Evaluate(instructions, intervals));
197            }
198            break;
199          }
200        //Trigonometric functions
201        case OpCodes.Sin: {
202            intermediate = Interval.Sine(Evaluate(instructions, intervals));
203            break;
204          }
205        case OpCodes.Cos: {
206            intermediate = Interval.Cosine(Evaluate(instructions, intervals));
207            break;
208          }
209        case OpCodes.Tan: {
210            intermediate = Interval.Tangens(Evaluate(instructions, intervals));
211            break;
212          }
213        //Exponential functions
214        case OpCodes.Log: {
215            intermediate = Interval.Logarithm(Evaluate(instructions, intervals));
216            break;
217          }
218        case OpCodes.Exp: {
219            intermediate = Interval.Exponential(Evaluate(instructions, intervals));
220            break;
221          }
222        case OpCodes.Power: {
223            intermediate = Evaluate(instructions, intervals);
224            for (int i = 1; i < currentInstr.nArguments; i++) {
225              intermediate = Interval.Power(intermediate, Evaluate(instructions, intervals));
226            }
227            break;
228          }
229        case OpCodes.Square: {
230            intermediate = Interval.Square(Evaluate(instructions, intervals));
231            break;
232          }
233        case OpCodes.Root: {
234            intermediate = Evaluate(instructions, intervals);
235            for (int i = 1; i < currentInstr.nArguments; i++) {
236              intermediate = Interval.Root(intermediate, Evaluate(instructions, intervals));
237            }
238            break;
239          }
240        case OpCodes.SquareRoot: {
241            intermediate = Interval.SquareRoot(Evaluate(instructions, intervals));
242            break;
243          }
244        //Variables, Constants, ...
245        case OpCodes.Variable: {
246            intervals.Add(currentInstr.dynamicNode, (Interval)currentInstr.data);
247            return (Interval)currentInstr.data;
248          }
249        case OpCodes.Constant: {
250            var constTreeNode = (ConstantTreeNode)currentInstr.dynamicNode;
251            var inter = new Interval(constTreeNode.Value, constTreeNode.Value);
252            intervals.Add(currentInstr.dynamicNode, inter);
253            return inter;
254          }
255        default:
256          throw new NotSupportedException("Tree contains an unknown symbol.");
257      }
258
259      if (intervals != null)
260        intervals.Add(currentInstr.dynamicNode, intermediate);
261      return intermediate;
262    }
263
264    public static bool IsCompatible(ISymbolicExpressionTree tree) {
265      var containsUnknownSyumbol = (
266        from n in tree.Root.GetSubtree(0).IterateNodesPrefix()
267        where
268          !(n.Symbol is StartSymbol) &&
269          !(n.Symbol is Addition) &&
270          !(n.Symbol is Subtraction) &&
271          !(n.Symbol is Multiplication) &&
272          !(n.Symbol is Division) &&
273          !(n.Symbol is Sine) &&
274          !(n.Symbol is Cosine) &&
275          !(n.Symbol is Tangent) &&
276          !(n.Symbol is Logarithm) &&
277          !(n.Symbol is Exponential) &&
278          !(n.Symbol is Power) &&
279          !(n.Symbol is Square) &&
280          !(n.Symbol is Root) &&
281          !(n.Symbol is SquareRoot) &&
282          !(n.Symbol is Problems.DataAnalysis.Symbolic.Variable) &&
283          !(n.Symbol is Constant)
284        select n).Any();
285      return !containsUnknownSyumbol;
286    }
287  }
288}
Note: See TracBrowser for help on using the repository browser.