source: branches/2966_interval_calculation/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/Interpreter/Intervalnterpreter.cs @ 16328

Last change on this file since 16328 was 16328, checked in by mkommend, 3 years ago

#2966: Reordered methods in interval interpreter, added IStatefulItem interface, sealed class.

File size: 8.8 KB
Line 
1using System;
2using System.Collections.Generic;
3using System.Linq;
4using HeuristicLab.Common;
5using HeuristicLab.Core;
6using HeuristicLab.Data;
7using HeuristicLab.Encodings.SymbolicExpressionTreeEncoding;
8using HeuristicLab.Persistence.Default.CompositeSerializers.Storable;
9using HeuristicLab.Problems.DataAnalysis;
10using HeuristicLab.Problems.DataAnalysis.Symbolic;
11
12namespace HeuristicLab.Algorithms.DataAnalysis.Symbolic {
13  [StorableClass]
14  [Item("SymbolicDataAnalysisIntervalArithmeticInterpreter", "Interpreter for interval arithmetic within symbolic regression.")]
15  public sealed class IntervalInterpreter : ParameterizedNamedItem, IStatefulItem {
16
17    private const string EvaluatedSolutionsParameterName = "EvaluatedSolutions";
18    public IFixedValueParameter<IntValue> EvaluatedSolutionsParameter {
19      get { return (IFixedValueParameter<IntValue>)Parameters[EvaluatedSolutionsParameterName]; }
20    }
21
22    public int EvaluatedSolutions {
23      get { return EvaluatedSolutionsParameter.Value.Value; }
24      set { EvaluatedSolutionsParameter.Value.Value = value; }
25    }
26
27    private IntervalInterpreter(bool deserializing) : base(deserializing) { }
28    private IntervalInterpreter(IntervalInterpreter original, Cloner cloner)
29        : base(original, cloner) { }
30
31    public IntervalInterpreter()
32        : base("SymbolicDataAnalysisIntervalArithmeticInterpreter", "Interpreter for interval arithmetic within symbolic regression.") { }
33
34    public override IDeepCloneable Clone(Cloner cloner) {
35      return new IntervalInterpreter(this, cloner);
36    }
37
38    #region IStatefulItem Members
39    public void InitializeState() {
40      EvaluatedSolutions = 0;
41    }
42    public void ClearState() { }
43    #endregion
44
45
46    public Interval GetSymbolicExressionTreeIntervals(ISymbolicExpressionTree tree, IEnumerable<int> rows, out Dictionary<ISymbolicExpressionTreeNode, Interval> intervals) {
47      intervals = new Dictionary<ISymbolicExpressionTreeNode, Interval>();
48      var state = PrepareInterpreterState(tree, rows);
49      var x = Evaluate(state, intervals);
50
51      return x;
52    }
53
54    public Interval GetSymbolicExressionTreeIntervals(ISymbolicExpressionTree tree, IDataset dataset, IEnumerable<int> rows,
55      Dictionary<string, Interval> customIntervals, out Dictionary<ISymbolicExpressionTreeNode, Interval> intervals) {
56      intervals = new Dictionary<ISymbolicExpressionTreeNode, Interval>();
57      var state = PrepareInterpreterState(tree, rows, dataset, customIntervals);
58      var x = Evaluate(state, intervals);
59
60      return x;
61    }
62
63    public Interval GetSymbolicExressionTreeIntervals(ISymbolicExpressionTree tree, IDataset dataset, IEnumerable<int> rows,
64      out Dictionary<ISymbolicExpressionTreeNode, Interval> intervals) {
65      intervals = new Dictionary<ISymbolicExpressionTreeNode, Interval>();
66      var state = PrepareInterpreterState(tree, rows, dataset);
67      var x = Evaluate(state, intervals);
68
69      return x;
70    }
71
72    private readonly object syncRoot = new object();
73
74    private static InterpreterState PrepareInterpreterState(ISymbolicExpressionTree tree,
75      IEnumerable<int> rows, IDataset dataset = null, Dictionary<string, Interval> customIntervals = null) {
76      Instruction[] code = SymbolicExpressionTreeCompiler.Compile(tree, OpCodes.MapSymbolToOpCode);
77      int necessaryArgStackSize = 0;
78
79      foreach (Instruction instr in code) {
80        if (instr.opCode == OpCodes.Variable) {
81          var variableTreeNode = (VariableTreeNode)instr.dynamicNode;
82          IList<double> values = new List<double>();
83
84          if (dataset != null && customIntervals != null) {
85            if (customIntervals.ContainsKey(variableTreeNode.VariableName)) {
86              instr.data = customIntervals[variableTreeNode.VariableName];
87            }
88            else {
89              foreach (var rowEnum in rows) {
90                values.Add(dataset.GetReadOnlyDoubleValues(variableTreeNode.VariableName)[rowEnum]);
91              }
92              instr.data = new Interval(values.Min(), values.Max());
93            }
94          }
95          else if (dataset != null) {
96            foreach (var rowEnum in rows) {
97              values.Add(dataset.GetReadOnlyDoubleValues(variableTreeNode.VariableName)[rowEnum]);
98            }
99            instr.data = new Interval(values.Min(), values.Max());
100          }
101          else if (customIntervals != null) {
102            if (customIntervals.ContainsKey(variableTreeNode.VariableName)) {
103              instr.data = customIntervals[variableTreeNode.VariableName];
104            }
105          }
106          else {
107            throw new Exception("No valid input for variables!");
108          }
109        }
110      }
111
112      return new InterpreterState(code, necessaryArgStackSize);
113    }
114
115    private Interval Evaluate(InterpreterState state, Dictionary<ISymbolicExpressionTreeNode, Interval> intervals) {
116      Instruction currentInstr = state.NextInstruction();
117      switch (currentInstr.opCode) {
118        //Elementary arithmetic rules
119        case OpCodes.Add: {
120            var s = Evaluate(state, intervals);
121            for (int i = 1; i < currentInstr.nArguments; i++) {
122              s = Interval.Add(s, Evaluate(state, intervals));
123            }
124            intervals.Add(currentInstr.dynamicNode, s);
125            return s;
126          }
127        case OpCodes.Sub: {
128            var s = Evaluate(state, intervals);
129            for (int i = 1; i < currentInstr.nArguments; i++) {
130              s = Interval.Subtract(s, Evaluate(state, intervals));
131            }
132            intervals.Add(currentInstr.dynamicNode, s);
133            return s;
134          }
135        case OpCodes.Mul: {
136            var s = Evaluate(state, intervals);
137            for (int i = 1; i < currentInstr.nArguments; i++) {
138              s = Interval.Multiply(s, Evaluate(state, intervals));
139            }
140            intervals.Add(currentInstr.dynamicNode, s);
141            return s;
142          }
143        case OpCodes.Div: {
144            var s = Evaluate(state, intervals);
145            for (int i = 1; i < currentInstr.nArguments; i++) {
146              s = Interval.Divide(s, Evaluate(state, intervals));
147            }
148            intervals.Add(currentInstr.dynamicNode, s);
149            return s;
150          }
151        //Trigonometric functions
152        case OpCodes.Sin: {
153            var s = Interval.Sine(Evaluate(state, intervals));
154            intervals.Add(currentInstr.dynamicNode, s);
155            return s;
156          }
157        case OpCodes.Cos: {
158            var s = Interval.Cosine(Evaluate(state, intervals));
159            intervals.Add(currentInstr.dynamicNode, s);
160            return s;
161          }
162        case OpCodes.Tan: {
163            var s = Interval.Tangens(Evaluate(state, intervals));
164            intervals.Add(currentInstr.dynamicNode, s);
165            return s;
166          }
167        //Exponential functions
168        case OpCodes.Log: {
169            var s = Interval.Logarithm(Evaluate(state, intervals));
170            intervals.Add(currentInstr.dynamicNode, s);
171            return s;
172          }
173        case OpCodes.Exp: {
174            var s = Interval.Exponential(Evaluate(state, intervals));
175            intervals.Add(currentInstr.dynamicNode, s);
176            return s;
177          }
178        case OpCodes.Power: {
179            var s = Evaluate(state, intervals);
180            for (int i = 1; i < currentInstr.nArguments; i++) {
181              s = Interval.Power(s, Evaluate(state, intervals));
182            }
183            intervals.Add(currentInstr.dynamicNode, s);
184            return s;
185          }
186        case OpCodes.Square: {
187            var s = Interval.Square(Evaluate(state, intervals));
188            intervals.Add(currentInstr.dynamicNode, s);
189            return s;
190          }
191        case OpCodes.Root: {
192            var s = Evaluate(state, intervals);
193            for (int i = 1; i < currentInstr.nArguments; i++) {
194              s = Interval.Root(s, Evaluate(state, intervals));
195            }
196            intervals.Add(currentInstr.dynamicNode, s);
197            return s;
198          }
199        case OpCodes.SquareRoot: {
200            var s = Interval.SquareRoot(Evaluate(state, intervals));
201            intervals.Add(currentInstr.dynamicNode, s);
202            return s;
203          }
204        //Variables, Constants, ...
205        case OpCodes.Variable: {
206            intervals.Add(currentInstr.dynamicNode, (Interval)currentInstr.data);
207            return (Interval)currentInstr.data;
208          }
209        case OpCodes.Constant: {
210            var constTreeNode = (ConstantTreeNode)currentInstr.dynamicNode;
211            var inter = new Interval(constTreeNode.Value, constTreeNode.Value);
212            intervals.Add(currentInstr.dynamicNode, inter);
213            return inter;
214          }
215        default:
216          throw new NotSupportedException();
217      }
218    }
219  }
220}
Note: See TracBrowser for help on using the repository browser.