Free cookie consent management tool by TermsFeed Policy Generator

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

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

#2966 Removed member variable InstructionCount and added ref parameter to Evaluate method instead

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