Free cookie consent management tool by TermsFeed Policy Generator

source: branches/2988_ModelsOfModels2/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/Interpreter/SymbolicDataAnalysisExpressionTreeLinearInterpreter.cs @ 16899

Last change on this file since 16899 was 16899, checked in by msemenki, 5 years ago

#2988: New version of class structure.

File size: 22.2 KB
RevLine 
[5571]1#region License Information
2/* HeuristicLab
[16565]3 * Copyright (C) 2002-2019 Heuristic and Evolutionary Algorithms Laboratory (HEAL)
[5571]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;
[9739]24using System.Linq;
[5571]25using HeuristicLab.Common;
26using HeuristicLab.Core;
[6740]27using HeuristicLab.Data;
[5571]28using HeuristicLab.Encodings.SymbolicExpressionTreeEncoding;
[6740]29using HeuristicLab.Parameters;
[16565]30using HEAL.Attic;
[5571]31
32namespace HeuristicLab.Problems.DataAnalysis.Symbolic {
[16565]33  [StorableType("EF325166-E03A-44C4-83CE-7F07B836285E")]
[9815]34  [Item("SymbolicDataAnalysisExpressionTreeLinearInterpreter", "Fast linear (non-recursive) interpreter for symbolic expression trees. Does not support ADFs.")]
[9758]35  public sealed class SymbolicDataAnalysisExpressionTreeLinearInterpreter : ParameterizedNamedItem, ISymbolicDataAnalysisExpressionTreeInterpreter {
[5749]36    private const string CheckExpressionsWithIntervalArithmeticParameterName = "CheckExpressionsWithIntervalArithmetic";
[13248]37    private const string CheckExpressionsWithIntervalArithmeticParameterDescription = "Switch that determines if the interpreter checks the validity of expressions with interval arithmetic before evaluating the expression.";
[7615]38    private const string EvaluatedSolutionsParameterName = "EvaluatedSolutions";
[5571]39
[14282]40    private readonly SymbolicDataAnalysisExpressionTreeInterpreter interpreter;
[9776]41
[9732]42    public override bool CanChangeName {
43      get { return false; }
44    }
[5571]45
[9732]46    public override bool CanChangeDescription {
47      get { return false; }
48    }
49
[5749]50    #region parameter properties
[13248]51    public IFixedValueParameter<BoolValue> CheckExpressionsWithIntervalArithmeticParameter {
52      get { return (IFixedValueParameter<BoolValue>)Parameters[CheckExpressionsWithIntervalArithmeticParameterName]; }
[5749]53    }
[7615]54
[13248]55    public IFixedValueParameter<IntValue> EvaluatedSolutionsParameter {
56      get { return (IFixedValueParameter<IntValue>)Parameters[EvaluatedSolutionsParameterName]; }
[7615]57    }
[5749]58    #endregion
59
60    #region properties
[13248]61    public bool CheckExpressionsWithIntervalArithmetic {
62      get { return CheckExpressionsWithIntervalArithmeticParameter.Value.Value; }
63      set { CheckExpressionsWithIntervalArithmeticParameter.Value.Value = value; }
[5749]64    }
[13248]65    public int EvaluatedSolutions {
66      get { return EvaluatedSolutionsParameter.Value.Value; }
67      set { EvaluatedSolutionsParameter.Value.Value = value; }
[7615]68    }
[5749]69    #endregion
70
[5571]71    [StorableConstructor]
[16565]72    private SymbolicDataAnalysisExpressionTreeLinearInterpreter(StorableConstructorFlag _) : base(_) {
[14282]73      interpreter = new SymbolicDataAnalysisExpressionTreeInterpreter();
[9732]74    }
75
[9828]76    private SymbolicDataAnalysisExpressionTreeLinearInterpreter(SymbolicDataAnalysisExpressionTreeLinearInterpreter original, Cloner cloner)
[9732]77      : base(original, cloner) {
[9828]78      interpreter = cloner.Clone(original.interpreter);
[9732]79    }
80
[5571]81    public override IDeepCloneable Clone(Cloner cloner) {
[9734]82      return new SymbolicDataAnalysisExpressionTreeLinearInterpreter(this, cloner);
[5571]83    }
84
[9734]85    public SymbolicDataAnalysisExpressionTreeLinearInterpreter()
[9758]86      : base("SymbolicDataAnalysisExpressionTreeLinearInterpreter", "Linear (non-recursive) interpreter for symbolic expression trees (does not support ADFs).") {
[13248]87      Parameters.Add(new FixedValueParameter<BoolValue>(CheckExpressionsWithIntervalArithmeticParameterName, CheckExpressionsWithIntervalArithmeticParameterDescription, new BoolValue(false)));
88      Parameters.Add(new FixedValueParameter<IntValue>(EvaluatedSolutionsParameterName, "A counter for the total number of solutions the interpreter has evaluated", new IntValue(0)));
[9776]89      interpreter = new SymbolicDataAnalysisExpressionTreeInterpreter();
[5571]90    }
91
[13248]92    public SymbolicDataAnalysisExpressionTreeLinearInterpreter(string name, string description)
93      : base(name, description) {
94      Parameters.Add(new FixedValueParameter<BoolValue>(CheckExpressionsWithIntervalArithmeticParameterName, CheckExpressionsWithIntervalArithmeticParameterDescription, new BoolValue(false)));
95      Parameters.Add(new FixedValueParameter<IntValue>(EvaluatedSolutionsParameterName, "A counter for the total number of solutions the interpreter has evaluated", new IntValue(0)));
96      interpreter = new SymbolicDataAnalysisExpressionTreeInterpreter();
97    }
98
[7615]99    [StorableHook(HookType.AfterDeserialization)]
100    private void AfterDeserialization() {
[13248]101      var evaluatedSolutions = new IntValue(0);
102      var checkExpressionsWithIntervalArithmetic = new BoolValue(false);
103      if (Parameters.ContainsKey(EvaluatedSolutionsParameterName)) {
104        var evaluatedSolutionsParameter = (IValueParameter<IntValue>)Parameters[EvaluatedSolutionsParameterName];
105        evaluatedSolutions = evaluatedSolutionsParameter.Value;
106        Parameters.Remove(EvaluatedSolutionsParameterName);
107      }
108      Parameters.Add(new FixedValueParameter<IntValue>(EvaluatedSolutionsParameterName, "A counter for the total number of solutions the interpreter has evaluated", evaluatedSolutions));
109      if (Parameters.ContainsKey(CheckExpressionsWithIntervalArithmeticParameterName)) {
110        var checkExpressionsWithIntervalArithmeticParameter = (IValueParameter<BoolValue>)Parameters[CheckExpressionsWithIntervalArithmeticParameterName];
111        Parameters.Remove(CheckExpressionsWithIntervalArithmeticParameterName);
112        checkExpressionsWithIntervalArithmetic = checkExpressionsWithIntervalArithmeticParameter.Value;
113      }
114      Parameters.Add(new FixedValueParameter<BoolValue>(CheckExpressionsWithIntervalArithmeticParameterName, CheckExpressionsWithIntervalArithmeticParameterDescription, checkExpressionsWithIntervalArithmetic));
[7615]115    }
116
117    #region IStatefulItem
118    public void InitializeState() {
[13248]119      EvaluatedSolutions = 0;
[7615]120    }
121
[9828]122    public void ClearState() { }
[7615]123    #endregion
124
[13251]125    private readonly object syncRoot = new object();
[12509]126    public IEnumerable<double> GetSymbolicExpressionTreeValues(ISymbolicExpressionTree tree, IDataset dataset, IEnumerable<int> rows) {
[14345]127      if (!rows.Any()) return Enumerable.Empty<double>();
[13248]128      if (CheckExpressionsWithIntervalArithmetic)
[9734]129        throw new NotSupportedException("Interval arithmetic is not yet supported in the symbolic data analysis interpreter.");
[7120]130
[13251]131      lock (syncRoot) {
[13248]132        EvaluatedSolutions++; // increment the evaluated solutions counter
[9004]133      }
[8436]134
[16899]135      var code = SymbolicExpressionTreeLinearCompiler.Compile(tree, OpCode.MapSymbolToOpCode);
[9758]136      PrepareInstructions(code, dataset);
[9818]137      return rows.Select(row => Evaluate(dataset, row, code));
[9739]138    }
[9732]139
[12509]140    private double Evaluate(IDataset dataset, int row, LinearInstruction[] code) {
[9732]141      for (int i = code.Length - 1; i >= 0; --i) {
[9776]142        if (code[i].skip) continue;
[9871]143        #region opcode if
[9732]144        var instr = code[i];
[16899]145        if (instr.opCode == OpCode.Variable) {
[9871]146          if (row < 0 || row >= dataset.Rows) instr.value = double.NaN;
[13268]147          else {
148            var variableTreeNode = (VariableTreeNode)instr.dynamicNode;
149            instr.value = ((IList<double>)instr.data)[row] * variableTreeNode.Weight;
150          }
[16899]151        } else if (instr.opCode == OpCode.BinaryFactorVariable) {
[14826]152          if (row < 0 || row >= dataset.Rows) instr.value = double.NaN;
153          else {
154            var factorTreeNode = instr.dynamicNode as BinaryFactorVariableTreeNode;
155            instr.value = ((IList<string>)instr.data)[row] == factorTreeNode.VariableValue ? factorTreeNode.Weight : 0;
156          }
[16899]157        } else if (instr.opCode == OpCode.FactorVariable) {
[14826]158          if (row < 0 || row >= dataset.Rows) instr.value = double.NaN;
159          else {
160            var factorTreeNode = instr.dynamicNode as FactorVariableTreeNode;
161            instr.value = factorTreeNode.GetValue(((IList<string>)instr.data)[row]);
162          }
[16899]163        } else if (instr.opCode == OpCode.LagVariable) {
[9871]164          var laggedVariableTreeNode = (LaggedVariableTreeNode)instr.dynamicNode;
165          int actualRow = row + laggedVariableTreeNode.Lag;
166          if (actualRow < 0 || actualRow >= dataset.Rows)
167            instr.value = double.NaN;
168          else
169            instr.value = ((IList<double>)instr.data)[actualRow] * laggedVariableTreeNode.Weight;
[16899]170        } else if (instr.opCode == OpCode.VariableCondition) {
[9871]171          if (row < 0 || row >= dataset.Rows) instr.value = double.NaN;
172          var variableConditionTreeNode = (VariableConditionTreeNode)instr.dynamicNode;
[14345]173          if (!variableConditionTreeNode.Symbol.IgnoreSlope) {
174            double variableValue = ((IList<double>)instr.data)[row];
175            double x = variableValue - variableConditionTreeNode.Threshold;
176            double p = 1 / (1 + Math.Exp(-variableConditionTreeNode.Slope * x));
[9738]177
[14345]178            double trueBranch = code[instr.childIndex].value;
179            double falseBranch = code[instr.childIndex + 1].value;
[9738]180
[14345]181            instr.value = trueBranch * p + falseBranch * (1 - p);
182          } else {
183            double variableValue = ((IList<double>)instr.data)[row];
184            if (variableValue <= variableConditionTreeNode.Threshold) {
185              instr.value = code[instr.childIndex].value;
186            } else {
187              instr.value = code[instr.childIndex + 1].value;
188            }
189          }
[16899]190        } else if (instr.opCode == OpCode.Add) {
[9871]191          double s = code[instr.childIndex].value;
192          for (int j = 1; j != instr.nArguments; ++j) {
193            s += code[instr.childIndex + j].value;
194          }
195          instr.value = s;
[16899]196        } else if (instr.opCode == OpCode.Sub) {
[9871]197          double s = code[instr.childIndex].value;
198          for (int j = 1; j != instr.nArguments; ++j) {
199            s -= code[instr.childIndex + j].value;
200          }
201          if (instr.nArguments == 1) s = -s;
202          instr.value = s;
[16899]203        } else if (instr.opCode == OpCode.Mul) {
[9871]204          double p = code[instr.childIndex].value;
205          for (int j = 1; j != instr.nArguments; ++j) {
206            p *= code[instr.childIndex + j].value;
207          }
208          instr.value = p;
[16899]209        } else if (instr.opCode == OpCode.Div) {
[9871]210          double p = code[instr.childIndex].value;
211          for (int j = 1; j != instr.nArguments; ++j) {
212            p /= code[instr.childIndex + j].value;
213          }
214          if (instr.nArguments == 1) p = 1.0 / p;
215          instr.value = p;
[16899]216        } else if (instr.opCode == OpCode.AnalyticQuotient) {
[16356]217          var x1 = code[instr.childIndex].value;
218          var x2 = code[instr.childIndex + 1].value;
219          instr.value = x1 / Math.Sqrt(1 + x2 * x2);
[16899]220        } else if (instr.opCode == OpCode.Average) {
[9871]221          double s = code[instr.childIndex].value;
222          for (int j = 1; j != instr.nArguments; ++j) {
223            s += code[instr.childIndex + j].value;
224          }
225          instr.value = s / instr.nArguments;
[16899]226        } else if (instr.opCode == OpCode.Absolute) {
[16356]227          instr.value = Math.Abs(code[instr.childIndex].value);
[16899]228        } else if (instr.opCode == OpCode.Tanh) {
[16722]229          instr.value = Math.Tanh(code[instr.childIndex].value);
[16899]230        } else if (instr.opCode == OpCode.Cos) {
[9871]231          instr.value = Math.Cos(code[instr.childIndex].value);
[16899]232        } else if (instr.opCode == OpCode.Sin) {
[9871]233          instr.value = Math.Sin(code[instr.childIndex].value);
[16899]234        } else if (instr.opCode == OpCode.Tan) {
[9871]235          instr.value = Math.Tan(code[instr.childIndex].value);
[16899]236        } else if (instr.opCode == OpCode.Square) {
[9871]237          instr.value = Math.Pow(code[instr.childIndex].value, 2);
[16899]238        } else if (instr.opCode == OpCode.Cube) {
[16356]239          instr.value = Math.Pow(code[instr.childIndex].value, 3);
[16899]240        } else if (instr.opCode == OpCode.Power) {
[9871]241          double x = code[instr.childIndex].value;
242          double y = Math.Round(code[instr.childIndex + 1].value);
243          instr.value = Math.Pow(x, y);
[16899]244        } else if (instr.opCode == OpCode.SquareRoot) {
[9871]245          instr.value = Math.Sqrt(code[instr.childIndex].value);
[16899]246        } else if (instr.opCode == OpCode.CubeRoot) {
[16356]247          instr.value = Math.Pow(code[instr.childIndex].value, 1.0 / 3.0);
[16899]248        } else if (instr.opCode == OpCode.Root) {
[9871]249          double x = code[instr.childIndex].value;
[13254]250          double y = Math.Round(code[instr.childIndex + 1].value);
[9871]251          instr.value = Math.Pow(x, 1 / y);
[16899]252        } else if (instr.opCode == OpCode.Exp) {
[9871]253          instr.value = Math.Exp(code[instr.childIndex].value);
[16899]254        } else if (instr.opCode == OpCode.Log) {
[9871]255          instr.value = Math.Log(code[instr.childIndex].value);
[16899]256        } else if (instr.opCode == OpCode.Gamma) {
[9871]257          var x = code[instr.childIndex].value;
258          instr.value = double.IsNaN(x) ? double.NaN : alglib.gammafunction(x);
[16899]259        } else if (instr.opCode == OpCode.Psi) {
[9871]260          var x = code[instr.childIndex].value;
261          if (double.IsNaN(x)) instr.value = double.NaN;
262          else if (x <= 0 && (Math.Floor(x) - x).IsAlmost(0)) instr.value = double.NaN;
263          else instr.value = alglib.psi(x);
[16899]264        } else if (instr.opCode == OpCode.Dawson) {
[9871]265          var x = code[instr.childIndex].value;
266          instr.value = double.IsNaN(x) ? double.NaN : alglib.dawsonintegral(x);
[16899]267        } else if (instr.opCode == OpCode.ExponentialIntegralEi) {
[9871]268          var x = code[instr.childIndex].value;
269          instr.value = double.IsNaN(x) ? double.NaN : alglib.exponentialintegralei(x);
[16899]270        } else if (instr.opCode == OpCode.SineIntegral) {
[9871]271          double si, ci;
272          var x = code[instr.childIndex].value;
273          if (double.IsNaN(x)) instr.value = double.NaN;
274          else {
275            alglib.sinecosineintegrals(x, out si, out ci);
276            instr.value = si;
277          }
[16899]278        } else if (instr.opCode == OpCode.CosineIntegral) {
[9871]279          double si, ci;
280          var x = code[instr.childIndex].value;
281          if (double.IsNaN(x)) instr.value = double.NaN;
282          else {
283            alglib.sinecosineintegrals(x, out si, out ci);
284            instr.value = ci;
285          }
[16899]286        } else if (instr.opCode == OpCode.HyperbolicSineIntegral) {
[9871]287          double shi, chi;
288          var x = code[instr.childIndex].value;
289          if (double.IsNaN(x)) instr.value = double.NaN;
290          else {
291            alglib.hyperbolicsinecosineintegrals(x, out shi, out chi);
292            instr.value = shi;
293          }
[16899]294        } else if (instr.opCode == OpCode.HyperbolicCosineIntegral) {
[9871]295          double shi, chi;
296          var x = code[instr.childIndex].value;
297          if (double.IsNaN(x)) instr.value = double.NaN;
298          else {
299            alglib.hyperbolicsinecosineintegrals(x, out shi, out chi);
300            instr.value = chi;
301          }
[16899]302        } else if (instr.opCode == OpCode.FresnelCosineIntegral) {
[9871]303          double c = 0, s = 0;
304          var x = code[instr.childIndex].value;
305          if (double.IsNaN(x)) instr.value = double.NaN;
306          else {
307            alglib.fresnelintegral(x, ref c, ref s);
308            instr.value = c;
309          }
[16899]310        } else if (instr.opCode == OpCode.FresnelSineIntegral) {
[9871]311          double c = 0, s = 0;
312          var x = code[instr.childIndex].value;
313          if (double.IsNaN(x)) instr.value = double.NaN;
314          else {
315            alglib.fresnelintegral(x, ref c, ref s);
316            instr.value = s;
317          }
[16899]318        } else if (instr.opCode == OpCode.AiryA) {
[9871]319          double ai, aip, bi, bip;
320          var x = code[instr.childIndex].value;
321          if (double.IsNaN(x)) instr.value = double.NaN;
322          else {
323            alglib.airy(x, out ai, out aip, out bi, out bip);
324            instr.value = ai;
325          }
[16899]326        } else if (instr.opCode == OpCode.AiryB) {
[9871]327          double ai, aip, bi, bip;
328          var x = code[instr.childIndex].value;
329          if (double.IsNaN(x)) instr.value = double.NaN;
330          else {
331            alglib.airy(x, out ai, out aip, out bi, out bip);
332            instr.value = bi;
333          }
[16899]334        } else if (instr.opCode == OpCode.Norm) {
[9871]335          var x = code[instr.childIndex].value;
336          if (double.IsNaN(x)) instr.value = double.NaN;
337          else instr.value = alglib.normaldistribution(x);
[16899]338        } else if (instr.opCode == OpCode.Erf) {
[9871]339          var x = code[instr.childIndex].value;
340          if (double.IsNaN(x)) instr.value = double.NaN;
341          else instr.value = alglib.errorfunction(x);
[16899]342        } else if (instr.opCode == OpCode.Bessel) {
[9871]343          var x = code[instr.childIndex].value;
344          if (double.IsNaN(x)) instr.value = double.NaN;
345          else instr.value = alglib.besseli0(x);
[16899]346        } else if (instr.opCode == OpCode.IfThenElse) {
[9871]347          double condition = code[instr.childIndex].value;
348          double result;
349          if (condition > 0.0) {
350            result = code[instr.childIndex + 1].value;
351          } else {
352            result = code[instr.childIndex + 2].value;
353          }
354          instr.value = result;
[16899]355        } else if (instr.opCode == OpCode.AND) {
[9871]356          double result = code[instr.childIndex].value;
357          for (int j = 1; j < instr.nArguments; j++) {
358            if (result > 0.0) result = code[instr.childIndex + j].value;
359            else break;
360          }
361          instr.value = result > 0.0 ? 1.0 : -1.0;
[16899]362        } else if (instr.opCode == OpCode.OR) {
[9871]363          double result = code[instr.childIndex].value;
364          for (int j = 1; j < instr.nArguments; j++) {
365            if (result <= 0.0) result = code[instr.childIndex + j].value;
366            else break;
367          }
368          instr.value = result > 0.0 ? 1.0 : -1.0;
[16899]369        } else if (instr.opCode == OpCode.NOT) {
[9871]370          instr.value = code[instr.childIndex].value > 0.0 ? -1.0 : 1.0;
[16899]371        } else if (instr.opCode == OpCode.XOR) {
[10788]372          int positiveSignals = 0;
373          for (int j = 0; j < instr.nArguments; j++) {
374            if (code[instr.childIndex + j].value > 0.0) positiveSignals++;
[10774]375          }
[10788]376          instr.value = positiveSignals % 2 != 0 ? 1.0 : -1.0;
[16899]377        } else if (instr.opCode == OpCode.GT) {
[9871]378          double x = code[instr.childIndex].value;
379          double y = code[instr.childIndex + 1].value;
380          instr.value = x > y ? 1.0 : -1.0;
[16899]381        } else if (instr.opCode == OpCode.LT) {
[9871]382          double x = code[instr.childIndex].value;
383          double y = code[instr.childIndex + 1].value;
384          instr.value = x < y ? 1.0 : -1.0;
[16899]385        } else if (instr.opCode == OpCode.TimeLag || instr.opCode == OpCode.Derivative || instr.opCode == OpCode.Integral) {
[9871]386          var state = (InterpreterState)instr.data;
387          state.Reset();
388          instr.value = interpreter.Evaluate(dataset, ref row, state);
389        } else {
390          var errorText = string.Format("The {0} symbol is not supported by the linear interpreter. To support this symbol, please use the SymbolicDataAnalysisExpressionTreeInterpreter.", instr.dynamicNode.Symbol.Name);
391          throw new NotSupportedException(errorText);
[9271]392        }
[9739]393        #endregion
[5571]394      }
[9739]395      return code[0].value;
[5571]396    }
[9815]397
398    private static LinearInstruction[] GetPrefixSequence(LinearInstruction[] code, int startIndex) {
[9944]399      var s = new Stack<int>();
[9815]400      var list = new List<LinearInstruction>();
[9944]401      s.Push(startIndex);
402      while (s.Any()) {
403        int i = s.Pop();
[9815]404        var instr = code[i];
[9944]405        // push instructions in reverse execution order
406        for (int j = instr.nArguments - 1; j >= 0; j--) s.Push(instr.childIndex + j);
[9815]407        list.Add(instr);
408      }
409      return list.ToArray();
410    }
411
[12509]412    public static void PrepareInstructions(LinearInstruction[] code, IDataset dataset) {
[9815]413      for (int i = 0; i != code.Length; ++i) {
414        var instr = code[i];
415        #region opcode switch
416        switch (instr.opCode) {
[16899]417          case OpCode.Constant: {
[9815]418              var constTreeNode = (ConstantTreeNode)instr.dynamicNode;
419              instr.value = constTreeNode.Value;
420              instr.skip = true; // the value is already set so this instruction should be skipped in the evaluation phase
421            }
422            break;
[16899]423          case OpCode.Variable: {
[9815]424              var variableTreeNode = (VariableTreeNode)instr.dynamicNode;
[9826]425              instr.data = dataset.GetReadOnlyDoubleValues(variableTreeNode.VariableName);
[9815]426            }
427            break;
[16899]428          case OpCode.BinaryFactorVariable: {
[14826]429              var factorVariableTreeNode = instr.dynamicNode as BinaryFactorVariableTreeNode;
430              instr.data = dataset.GetReadOnlyStringValues(factorVariableTreeNode.VariableName);
431            }
432            break;
[16899]433          case OpCode.FactorVariable: {
[14826]434              var factorVariableTreeNode = instr.dynamicNode as FactorVariableTreeNode;
435              instr.data = dataset.GetReadOnlyStringValues(factorVariableTreeNode.VariableName);
436            }
437            break;
[16899]438          case OpCode.LagVariable: {
[9815]439              var laggedVariableTreeNode = (LaggedVariableTreeNode)instr.dynamicNode;
[9826]440              instr.data = dataset.GetReadOnlyDoubleValues(laggedVariableTreeNode.VariableName);
[9815]441            }
442            break;
[16899]443          case OpCode.VariableCondition: {
[9815]444              var variableConditionTreeNode = (VariableConditionTreeNode)instr.dynamicNode;
[9826]445              instr.data = dataset.GetReadOnlyDoubleValues(variableConditionTreeNode.VariableName);
[9815]446            }
447            break;
[16899]448          case OpCode.TimeLag:
449          case OpCode.Integral:
450          case OpCode.Derivative: {
[9815]451              var seq = GetPrefixSequence(code, i);
452              var interpreterState = new InterpreterState(seq, 0);
[9826]453              instr.data = interpreterState;
[9815]454              for (int j = 1; j != seq.Length; ++j)
455                seq[j].skip = true;
[14345]456              break;
[9815]457            }
458        }
459        #endregion
460      }
461    }
[5571]462  }
463}
Note: See TracBrowser for help on using the repository browser.