Free cookie consent management tool by TermsFeed Policy Generator

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

Last change on this file since 16330 was 16330, checked in by chaider, 5 years ago

#2966: Implemented review comments and added IsCompatible method.

File size: 11.5 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      switch (currentInstr.opCode) {
169        //Elementary arithmetic rules
170        case OpCodes.Add: {
171            var s = Evaluate(instructions, intervals);
172            for (int i = 1; i < currentInstr.nArguments; i++) {
173              s = Interval.Add(s, Evaluate(instructions, intervals));
174            }
175            intervals.Add(currentInstr.dynamicNode, s);
176            return s;
177          }
178        case OpCodes.Sub: {
179            var s = Evaluate(instructions, intervals);
180            for (int i = 1; i < currentInstr.nArguments; i++) {
181              s = Interval.Subtract(s, Evaluate(instructions, intervals));
182            }
183            intervals.Add(currentInstr.dynamicNode, s);
184            return s;
185          }
186        case OpCodes.Mul: {
187            var s = Evaluate(instructions, intervals);
188            for (int i = 1; i < currentInstr.nArguments; i++) {
189              s = Interval.Multiply(s, Evaluate(instructions, intervals));
190            }
191            intervals.Add(currentInstr.dynamicNode, s);
192            return s;
193          }
194        case OpCodes.Div: {
195            var s = Evaluate(instructions, intervals);
196            for (int i = 1; i < currentInstr.nArguments; i++) {
197              s = Interval.Divide(s, Evaluate(instructions, intervals));
198            }
199            intervals.Add(currentInstr.dynamicNode, s);
200            return s;
201          }
202        //Trigonometric functions
203        case OpCodes.Sin: {
204            var s = Interval.Sine(Evaluate(instructions, intervals));
205            intervals.Add(currentInstr.dynamicNode, s);
206            return s;
207          }
208        case OpCodes.Cos: {
209            var s = Interval.Cosine(Evaluate(instructions, intervals));
210            intervals.Add(currentInstr.dynamicNode, s);
211            return s;
212          }
213        case OpCodes.Tan: {
214            var s = Interval.Tangens(Evaluate(instructions, intervals));
215            intervals.Add(currentInstr.dynamicNode, s);
216            return s;
217          }
218        //Exponential functions
219        case OpCodes.Log: {
220            var s = Interval.Logarithm(Evaluate(instructions, intervals));
221            intervals.Add(currentInstr.dynamicNode, s);
222            return s;
223          }
224        case OpCodes.Exp: {
225            var s = Interval.Exponential(Evaluate(instructions, intervals));
226            intervals.Add(currentInstr.dynamicNode, s);
227            return s;
228          }
229        case OpCodes.Power: {
230            var s = Evaluate(instructions, intervals);
231            for (int i = 1; i < currentInstr.nArguments; i++) {
232              s = Interval.Power(s, Evaluate(instructions, intervals));
233            }
234            intervals.Add(currentInstr.dynamicNode, s);
235            return s;
236          }
237        case OpCodes.Square: {
238            var s = Interval.Square(Evaluate(instructions, intervals));
239            intervals.Add(currentInstr.dynamicNode, s);
240            return s;
241          }
242        case OpCodes.Root: {
243            var s = Evaluate(instructions, intervals);
244            for (int i = 1; i < currentInstr.nArguments; i++) {
245              s = Interval.Root(s, Evaluate(instructions, intervals));
246            }
247            intervals.Add(currentInstr.dynamicNode, s);
248            return s;
249          }
250        case OpCodes.SquareRoot: {
251            var s = Interval.SquareRoot(Evaluate(instructions, intervals));
252            intervals.Add(currentInstr.dynamicNode, s);
253            return s;
254          }
255        //Variables, Constants, ...
256        case OpCodes.Variable: {
257            intervals.Add(currentInstr.dynamicNode, (Interval)currentInstr.data);
258            return (Interval)currentInstr.data;
259          }
260        case OpCodes.Constant: {
261            var constTreeNode = (ConstantTreeNode)currentInstr.dynamicNode;
262            var inter = new Interval(constTreeNode.Value, constTreeNode.Value);
263            intervals.Add(currentInstr.dynamicNode, inter);
264            return inter;
265          }
266        default:
267          throw new NotSupportedException("Tree contains an unknown symbol.");
268      }
269    }
270
271    public static bool IsCompatible(ISymbolicExpressionTree tree) {
272      var containsUnknownSyumbol = (
273        from n in tree.Root.GetSubtree(0).IterateNodesPrefix()
274        where
275          !(n.Symbol is StartSymbol) &&
276          !(n.Symbol is Addition) &&
277          !(n.Symbol is Subtraction) &&
278          !(n.Symbol is Multiplication) &&
279          !(n.Symbol is Division) &&
280          !(n.Symbol is Sine) &&
281          !(n.Symbol is Cosine) &&
282          !(n.Symbol is Tangent) &&
283          !(n.Symbol is Logarithm) &&
284          !(n.Symbol is Exponential) &&
285          !(n.Symbol is Power) &&
286          !(n.Symbol is Square) &&
287          !(n.Symbol is Root) &&
288          !(n.Symbol is SquareRoot) &&
289          !(n.Symbol is Problems.DataAnalysis.Symbolic.Variable) &&
290          !(n.Symbol is Constant)
291        select n).Any();
292      return !containsUnknownSyumbol;
293    }
294  }
295}
Note: See TracBrowser for help on using the repository browser.