Changeset 8436


Ignore:
Timestamp:
08/08/12 16:04:29 (9 years ago)
Author:
mkommend
Message:

#1081: Merged changes from trunk into timeseries branch and refactored GP interpreter.

Location:
branches/HeuristicLab.TimeSeries
Files:
5 edited

Legend:

Unmodified
Added
Removed
  • branches/HeuristicLab.TimeSeries/HeuristicLab.Encodings.SymbolicExpressionTreeEncoding/3.4/Compiler/SymbolicExpressionTreeCompiler.cs

    r7989 r8436  
    5353          var invokeNode = (InvokeFunctionTreeNode)instr.dynamicNode;
    5454          instr.iArg0 = entryPoint[invokeNode.Symbol.FunctionName];
    55           code[i] = instr;
    5655        }
    5756      }
  • branches/HeuristicLab.TimeSeries/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/Interpreter/InterpreterState.cs

    r8431 r8436  
    2424namespace HeuristicLab.Problems.DataAnalysis.Symbolic {
    2525  public class InterpreterState {
    26     private double[] argumentStack;
     26    private readonly double[] argumentStack;
    2727    private int argumentStackPointer;
    28     private Instruction[] code;
    29     private int pc;
    30     public int ProgramCounter {
    31       get { return pc; }
    32       set { pc = value; }
    33     }
     28    private readonly Instruction[] code;
     29
     30    public int ProgramCounter { get; set; }
     31    public bool InLaggedContext { get; set; }
     32
    3433    public InterpreterState(Instruction[] code, int argumentStackSize) {
    3534      this.code = code;
    36       this.pc = 0;
     35      this.ProgramCounter = 0;
     36      this.InLaggedContext = false;
    3737      if (argumentStackSize > 0) {
    3838        this.argumentStack = new double[argumentStackSize];
     
    4242
    4343    public void Reset() {
    44       this.pc = 0;
     44      this.ProgramCounter = 0;
    4545      this.argumentStackPointer = 0;
     46      this.InLaggedContext = false;
    4647    }
    4748
    4849    public Instruction NextInstruction() {
    49       return code[pc++];
     50      return code[ProgramCounter++];
    5051    }
    5152    // skips a whole branch
  • branches/HeuristicLab.TimeSeries/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/Interpreter/OpCodes.cs

    r8431 r8436  
    8484
    8585    private static Dictionary<Type, byte> symbolToOpcode = new Dictionary<Type, byte>() {
    86       { typeof(Addition), OpCodes.Add },
     86       { typeof(Addition), OpCodes.Add },
    8787      { typeof(Subtraction), OpCodes.Sub },
    8888      { typeof(Multiplication), OpCodes.Mul },
     
    127127      { typeof(Norm), OpCodes.Norm},
    128128      { typeof(Erf), OpCodes.Erf},
    129       { typeof(Bessel), OpCodes.Bessel}      
     129      { typeof(Bessel), OpCodes.Bessel}   
    130130    };
    131131
  • branches/HeuristicLab.TimeSeries/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/Interpreter/SymbolicDataAnalysisExpressionTreeILEmittingInterpreter.cs

    r8432 r8436  
    3535  [StorableClass]
    3636  [Item("SymbolicDataAnalysisExpressionTreeILEmittingInterpreter", "Interpreter for symbolic expression trees.")]
    37   public sealed class SymbolicDataAnalysisExpressionTreeILEmittingInterpreter : ParameterizedNamedItem,
    38                                                                                 ISymbolicDataAnalysisExpressionTreeInterpreter {
    39     private static MethodInfo listGetValue =
    40       typeof(IList<double>).GetProperty("Item", new Type[] { typeof(int) }).GetGetMethod();
     37  public sealed class SymbolicDataAnalysisExpressionTreeILEmittingInterpreter : ParameterizedNamedItem, ISymbolicDataAnalysisExpressionTreeInterpreter {
     38    private static readonly Type thisType = typeof(SymbolicDataAnalysisExpressionTreeILEmittingInterpreter);
     39    internal delegate double CompiledFunction(int sampleIndex, IList<double>[] columns);
     40
     41    #region method infos
     42    private static MethodInfo listGetValue = typeof(IList<double>).GetProperty("Item", new Type[] { typeof(int) }).GetGetMethod();
    4143
    4244    private static MethodInfo cos = typeof(Math).GetMethod("Cos", new Type[] { typeof(double) });
     
    4951    private static MethodInfo sqrt = typeof(Math).GetMethod("Sqrt", new Type[] { typeof(double) });
    5052
    51     internal delegate double CompiledFunction(int sampleIndex, IList<double>[] columns, IList<double>[] cachedValues, int cacheStartIndex);
    52     private static Type thisType = typeof(SymbolicDataAnalysisExpressionTreeILEmittingInterpreter);
    5353    private static MethodInfo airyA = thisType.GetMethod("AiryA", new Type[] { typeof(double) });
    5454    private static MethodInfo airyB = thisType.GetMethod("AiryB", new Type[] { typeof(double) });
     
    6666    private static MethodInfo erf = thisType.GetMethod("Erf", new Type[] { typeof(double) });
    6767    private static MethodInfo bessel = thisType.GetMethod("Bessel", new Type[] { typeof(double) });
    68 
    69    
     68    #endregion
    7069
    7170    private const string CheckExpressionsWithIntervalArithmeticParameterName = "CheckExpressionsWithIntervalArithmetic";
    7271    private const string EvaluatedSolutionsParameterName = "EvaluatedSolutions";
    73 
    74     #region private classes
    75 
    76     private class InterpreterState {
    77       private Instruction[] code;
    78       private int pc;
    79 
    80       public int ProgramCounter {
    81         get { return pc; }
    82         set { pc = value; }
    83       }
    84 
    85       private bool inLaggedContext;
    86 
    87       public bool InLaggedContext {
    88         get { return inLaggedContext; }
    89         set { inLaggedContext = value; }
    90       }
    91 
    92       internal InterpreterState(Instruction[] code) {
    93         this.inLaggedContext = false;
    94         this.code = code;
    95         this.pc = 0;
    96       }
    97 
    98       internal Instruction NextInstruction() {
    99         return code[pc++];
    100       }
    101     }
    102 
    103     private class OpCodes {
    104       public const byte Add = 1;
    105       public const byte Sub = 2;
    106       public const byte Mul = 3;
    107       public const byte Div = 4;
    108 
    109       public const byte Sin = 5;
    110       public const byte Cos = 6;
    111       public const byte Tan = 7;
    112 
    113       public const byte Log = 8;
    114       public const byte Exp = 9;
    115 
    116       public const byte IfThenElse = 10;
    117 
    118       public const byte GT = 11;
    119       public const byte LT = 12;
    120 
    121       public const byte AND = 13;
    122       public const byte OR = 14;
    123       public const byte NOT = 15;
    124 
    125 
    126       public const byte Average = 16;
    127 
    128       public const byte Call = 17;
    129 
    130       public const byte Variable = 18;
    131       public const byte LagVariable = 19;
    132       public const byte Constant = 20;
    133       public const byte Arg = 21;
    134 
    135       public const byte Power = 22;
    136       public const byte Root = 23;
    137       public const byte TimeLag = 24;
    138       public const byte Integral = 25;
    139       public const byte Derivative = 26;
    140 
    141       public const byte VariableCondition = 27;
    142 
    143       public const byte Square = 28;
    144       public const byte SquareRoot = 29;
    145       public const byte Gamma = 30;
    146       public const byte Psi = 31;
    147       public const byte Dawson = 32;
    148       public const byte ExponentialIntegralEi = 33;
    149       public const byte CosineIntegral = 34;
    150       public const byte SineIntegral = 35;
    151       public const byte HyperbolicCosineIntegral = 36;
    152       public const byte HyperbolicSineIntegral = 37;
    153       public const byte FresnelCosineIntegral = 38;
    154       public const byte FresnelSineIntegral = 39;
    155       public const byte AiryA = 40;
    156       public const byte AiryB = 41;
    157       public const byte Norm = 42;
    158       public const byte Erf = 43;
    159       public const byte Bessel = 44;
    160     }
    161 
    162     #endregion
    163 
    164     private Dictionary<Type, byte> symbolToOpcode = new Dictionary<Type, byte>()
    165                                                       {
    166                                                         {typeof (Addition), OpCodes.Add},
    167                                                         {typeof (Subtraction), OpCodes.Sub},
    168                                                         {typeof (Multiplication), OpCodes.Mul},
    169                                                         {typeof (Division), OpCodes.Div},
    170                                                         {typeof (Sine), OpCodes.Sin},
    171                                                         {typeof (Cosine), OpCodes.Cos},
    172                                                         {typeof (Tangent), OpCodes.Tan},
    173                                                         {typeof (Logarithm), OpCodes.Log},
    174                                                         {typeof (Exponential), OpCodes.Exp},
    175                                                         {typeof (IfThenElse), OpCodes.IfThenElse},
    176                                                         {typeof (GreaterThan), OpCodes.GT},
    177                                                         {typeof (LessThan), OpCodes.LT},
    178                                                         {typeof (And), OpCodes.AND},
    179                                                         {typeof (Or), OpCodes.OR},
    180                                                         {typeof (Not), OpCodes.NOT},
    181                                                         {typeof (Average), OpCodes.Average},
    182                                                         {typeof (InvokeFunction), OpCodes.Call},
    183                                                         {
    184                                                           typeof (HeuristicLab.Problems.DataAnalysis.Symbolic.Variable),
    185                                                           OpCodes.Variable
    186                                                           },
    187                                                         {typeof (LaggedVariable), OpCodes.LagVariable},
    188                                                         {typeof (Constant), OpCodes.Constant},
    189                                                         {typeof (Argument), OpCodes.Arg},
    190                                                         {typeof (Power), OpCodes.Power},
    191                                                         {typeof (Root), OpCodes.Root},
    192                                                         {typeof (TimeLag), OpCodes.TimeLag},
    193                                                         {typeof (Integral), OpCodes.Integral},
    194                                                         {typeof (Derivative), OpCodes.Derivative},
    195                                                         {typeof (VariableCondition), OpCodes.VariableCondition},
    196                                                         {typeof (Square), OpCodes.Square},
    197                                                         {typeof (SquareRoot), OpCodes.SquareRoot},
    198                                                         {typeof (Gamma), OpCodes.Gamma},
    199                                                         {typeof (Psi), OpCodes.Psi},
    200                                                         {typeof (Dawson), OpCodes.Dawson},
    201                                                         {typeof (ExponentialIntegralEi), OpCodes.ExponentialIntegralEi},
    202                                                         {typeof (CosineIntegral), OpCodes.CosineIntegral},
    203                                                         {typeof (SineIntegral), OpCodes.SineIntegral},
    204                                                         {
    205                                                           typeof (HyperbolicCosineIntegral),
    206                                                           OpCodes.HyperbolicCosineIntegral
    207                                                           },
    208                                                         {
    209                                                           typeof (HyperbolicSineIntegral), OpCodes.HyperbolicSineIntegral
    210                                                           },
    211                                                         {typeof (FresnelCosineIntegral), OpCodes.FresnelCosineIntegral},
    212                                                         {typeof (FresnelSineIntegral), OpCodes.FresnelSineIntegral},
    213                                                         {typeof (AiryA), OpCodes.AiryA},
    214                                                         {typeof (AiryB), OpCodes.AiryB},
    215                                                         {typeof (Norm), OpCodes.Norm},
    216                                                         {typeof (Erf), OpCodes.Erf},
    217                                                         {typeof (Bessel), OpCodes.Bessel}
    218                                                       };
    21972
    22073    public override bool CanChangeName {
     
    254107
    255108    [StorableConstructor]
    256     private SymbolicDataAnalysisExpressionTreeILEmittingInterpreter(bool deserializing)
    257       : base(deserializing) {
    258     }
    259 
    260     private SymbolicDataAnalysisExpressionTreeILEmittingInterpreter(
    261       SymbolicDataAnalysisExpressionTreeILEmittingInterpreter original, Cloner cloner)
    262       : base(original, cloner) {
    263     }
    264 
     109    private SymbolicDataAnalysisExpressionTreeILEmittingInterpreter(bool deserializing) : base(deserializing) { }
     110
     111    private SymbolicDataAnalysisExpressionTreeILEmittingInterpreter(SymbolicDataAnalysisExpressionTreeILEmittingInterpreter original, Cloner cloner) : base(original, cloner) { }
    265112    public override IDeepCloneable Clone(Cloner cloner) {
    266113      return new SymbolicDataAnalysisExpressionTreeILEmittingInterpreter(this, cloner);
     
    269116    public SymbolicDataAnalysisExpressionTreeILEmittingInterpreter()
    270117      : base("SymbolicDataAnalysisExpressionTreeILEmittingInterpreter", "Interpreter for symbolic expression trees.") {
    271       Parameters.Add(new ValueParameter<BoolValue>(CheckExpressionsWithIntervalArithmeticParameterName,
    272                                                    "Switch that determines if the interpreter checks the validity of expressions with interval arithmetic before evaluating the expression.",
    273                                                    new BoolValue(false)));
    274       Parameters.Add(new ValueParameter<IntValue>(EvaluatedSolutionsParameterName,
    275                                                   "A counter for the total number of solutions the interpreter has evaluated",
    276                                                   new IntValue(0)));
     118      Parameters.Add(new ValueParameter<BoolValue>(CheckExpressionsWithIntervalArithmeticParameterName, "Switch that determines if the interpreter checks the validity of expressions with interval arithmetic before evaluating the expression.", new BoolValue(false)));
     119      Parameters.Add(new ValueParameter<IntValue>(EvaluatedSolutionsParameterName, "A counter for the total number of solutions the interpreter has evaluated", new IntValue(0)));
    277120    }
    278121
     
    280123    private void AfterDeserialization() {
    281124      if (!Parameters.ContainsKey(EvaluatedSolutionsParameterName))
    282         Parameters.Add(new ValueParameter<IntValue>(EvaluatedSolutionsParameterName,
    283                                                     "A counter for the total number of solutions the interpreter has evaluated",
    284                                                     new IntValue(0)));
     125        Parameters.Add(new ValueParameter<IntValue>(EvaluatedSolutionsParameterName, "A counter for the total number of solutions the interpreter has evaluated", new IntValue(0)));
    285126    }
    286127
     
    297138    #endregion
    298139
    299     public IEnumerable<double> GetSymbolicExpressionTreeValues(ISymbolicExpressionTree tree, Dataset dataset,
    300                                                                IEnumerable<int> rows) {
    301       return GetSymbolicExpressionTreeValues(tree, dataset, new string[] { "#NOTHING#" }, rows);
    302     }
    303     public IEnumerable<double> GetSymbolicExpressionTreeValues(ISymbolicExpressionTree tree, Dataset dataset, string[] targetVariables, IEnumerable<int> rows) {
    304       return GetSymbolicExpressionTreeValues(tree, dataset, targetVariables, rows, 1);
    305     }
    306     // for each row for each horizon for each target variable one value
    307     public IEnumerable<double> GetSymbolicExpressionTreeValues(ISymbolicExpressionTree tree, Dataset dataset, string[] targetVariables, IEnumerable<int> rows, int horizon) {
     140    public IEnumerable<double> GetSymbolicExpressionTreeValues(ISymbolicExpressionTree tree, Dataset dataset, IEnumerable<int> rows) {
    308141      if (CheckExpressionsWithIntervalArithmetic.Value)
    309         throw new NotSupportedException(
    310           "Interval arithmetic is not yet supported in the symbolic data analysis interpreter.");
     142        throw new NotSupportedException("Interval arithmetic is not yet supported in the symbolic data analysis interpreter.");
     143
    311144      EvaluatedSolutions.Value++; // increment the evaluated solutions counter
    312       var compiler = new SymbolicExpressionTreeCompiler();
    313       Instruction[] code = compiler.Compile(tree, MapSymbolToOpCode);
     145      var state = PrepareInterpreterState(tree, dataset);
     146
     147      Type[] methodArgs = { typeof(int), typeof(IList<double>[]) };
     148      DynamicMethod testFun = new DynamicMethod("TestFun", typeof(double), methodArgs, typeof(SymbolicDataAnalysisExpressionTreeILEmittingInterpreter).Module);
     149
     150      ILGenerator il = testFun.GetILGenerator();
     151      CompileInstructions(il, state, dataset);
     152      il.Emit(System.Reflection.Emit.OpCodes.Conv_R8);
     153      il.Emit(System.Reflection.Emit.OpCodes.Ret);
     154      var function = (CompiledFunction)testFun.CreateDelegate(typeof(CompiledFunction));
     155
     156      IList<double>[] columns = dataset.DoubleVariables.Select(v => dataset.GetReadOnlyDoubleValues(v)).ToArray();
     157
     158      foreach (var row in rows) {
     159        yield return function(row, columns);
     160      }
     161    }
     162
     163    private InterpreterState PrepareInterpreterState(ISymbolicExpressionTree tree, Dataset dataset) {
     164      Instruction[] code = SymbolicExpressionTreeCompiler.Compile(tree, OpCodes.MapSymbolToOpCode);
     165      Dictionary<string, int> doubleVariableNames = dataset.DoubleVariables.Select((x, i) => new { x, i }).ToDictionary(e => e.x, e => e.i);
    314166      int necessaryArgStackSize = 0;
    315 
    316       Dictionary<string, int> doubleVariableNames =
    317         dataset.DoubleVariables.Select((x, i) => new { x, i }).ToDictionary(e => e.x, e => e.i);
    318 
    319       for (int i = 0; i < code.Length; i++) {
    320         Instruction instr = code[i];
     167      foreach (Instruction instr in code) {
    321168        if (instr.opCode == OpCodes.Variable) {
    322           var variableTreeNode = instr.dynamicNode as VariableTreeNode;
     169          var variableTreeNode = (VariableTreeNode)instr.dynamicNode;
    323170          instr.iArg0 = doubleVariableNames[variableTreeNode.VariableName];
    324           code[i] = instr;
    325171        } else if (instr.opCode == OpCodes.LagVariable) {
    326           var variableTreeNode = instr.dynamicNode as LaggedVariableTreeNode;
    327           instr.iArg0 = doubleVariableNames[variableTreeNode.VariableName];
    328           code[i] = instr;
     172          var laggedVariableTreeNode = (LaggedVariableTreeNode)instr.dynamicNode;
     173          instr.iArg0 = doubleVariableNames[laggedVariableTreeNode.VariableName];
    329174        } else if (instr.opCode == OpCodes.VariableCondition) {
    330           var variableConditionTreeNode = instr.dynamicNode as VariableConditionTreeNode;
     175          var variableConditionTreeNode = (VariableConditionTreeNode)instr.dynamicNode;
    331176          instr.iArg0 = doubleVariableNames[variableConditionTreeNode.VariableName];
    332177        } else if (instr.opCode == OpCodes.Call) {
     
    334179        }
    335180      }
    336       var state = new InterpreterState(code);
    337       Type[] methodArgs = { typeof(int), typeof(IList<double>[]), typeof(IList<double>[]), typeof(int) };
    338 
    339       CompiledFunction[] function = new CompiledFunction[targetVariables.Length];
    340       for (int i = 0; i < function.Length; i++) {
    341         DynamicMethod testFun = new DynamicMethod("TestFun", typeof(double), methodArgs, typeof(SymbolicDataAnalysisExpressionTreeILEmittingInterpreter).Module);
    342         ILGenerator il = testFun.GetILGenerator();
    343         CompileInstructions(il, state, dataset);
    344         il.Emit(System.Reflection.Emit.OpCodes.Conv_R8);
    345         il.Emit(System.Reflection.Emit.OpCodes.Ret);
    346         function[i] = (CompiledFunction)testFun.CreateDelegate(typeof(CompiledFunction));
    347       }
    348       var values = doubleVariableNames.Keys
    349         .Select(v => dataset.GetReadOnlyDoubleValues(v))
    350         .ToArray();
    351       var cachedValues = (from var in doubleVariableNames.Keys
    352                           select new double[horizon]).ToArray();
    353       foreach (var row in rows) {
    354         // init first line of cache
    355         int c = 0;
    356         foreach (var var in doubleVariableNames.Keys)
    357           cachedValues[c++][0] = dataset.GetDoubleValue(var, row);
    358         for (int horizonRow = row; horizonRow < row + horizon; horizonRow++) {
    359           for (int i = 0; i < function.Length; i++) {
    360             var componentProg = function[i](horizonRow, values, cachedValues, row);
    361             // set cachedValues for prognosis of future values
    362             if (horizon > 1)
    363               cachedValues[doubleVariableNames[targetVariables[i]]][horizonRow - row] = componentProg;
    364             yield return componentProg;
    365           }
    366         }
    367       }
     181      return new InterpreterState(code, necessaryArgStackSize);
    368182    }
    369183
     
    865679    }
    866680
    867     private byte MapSymbolToOpCode(ISymbolicExpressionTreeNode treeNode) {
    868       byte opCode;
    869       if (!symbolToOpcode.TryGetValue(treeNode.Symbol.GetType(), out opCode))
    870         throw new NotSupportedException("Symbol: " + treeNode.Symbol);
    871       return opCode;
    872     }
    873 
    874 
    875681    public static double AiryA(double x) {
    876682      if (double.IsNaN(x)) return double.NaN;
  • branches/HeuristicLab.TimeSeries/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/Interpreter/SymbolicDataAnalysisExpressionTreeInterpreter.cs

    r8432 r8436  
    2222using System;
    2323using System.Collections.Generic;
    24 using System.Linq;
    2524using HeuristicLab.Common;
    2625using HeuristicLab.Core;
     
    3332  [StorableClass]
    3433  [Item("SymbolicDataAnalysisExpressionTreeInterpreter", "Interpreter for symbolic expression trees including automatically defined functions.")]
    35   public sealed class SymbolicDataAnalysisExpressionTreeInterpreter : ParameterizedNamedItem,
    36     ISymbolicDataAnalysisExpressionTreeInterpreter, ISymbolicTimeSeriesPrognosisExpressionTreeInterpreter {
     34  public class SymbolicDataAnalysisExpressionTreeInterpreter : ParameterizedNamedItem, ISymbolicDataAnalysisExpressionTreeInterpreter {
    3735    private const string CheckExpressionsWithIntervalArithmeticParameterName = "CheckExpressionsWithIntervalArithmetic";
    3836    private const string EvaluatedSolutionsParameterName = "EvaluatedSolutions";
    39     #region private classes
    40     private class InterpreterState {
    41       private double[] argumentStack;
    42       private int argumentStackPointer;
    43       private Instruction[] code;
    44       private int pc;
    45       public int ProgramCounter {
    46         get { return pc; }
    47         set { pc = value; }
    48       }
    49       internal InterpreterState(Instruction[] code, int argumentStackSize) {
    50         this.code = code;
    51         this.pc = 0;
    52         if (argumentStackSize > 0) {
    53           this.argumentStack = new double[argumentStackSize];
    54         }
    55         this.argumentStackPointer = 0;
    56       }
    57 
    58       internal void Reset() {
    59         this.pc = 0;
    60         this.argumentStackPointer = 0;
    61       }
    62 
    63       internal Instruction NextInstruction() {
    64         return code[pc++];
    65       }
    66       private void Push(double val) {
    67         argumentStack[argumentStackPointer++] = val;
    68       }
    69       private double Pop() {
    70         return argumentStack[--argumentStackPointer];
    71       }
    72 
    73       internal void CreateStackFrame(double[] argValues) {
    74         // push in reverse order to make indexing easier
    75         for (int i = argValues.Length - 1; i >= 0; i--) {
    76           argumentStack[argumentStackPointer++] = argValues[i];
    77         }
    78         Push(argValues.Length);
    79       }
    80 
    81       internal void RemoveStackFrame() {
    82         int size = (int)Pop();
    83         argumentStackPointer -= size;
    84       }
    85 
    86       internal double GetStackFrameValue(ushort index) {
    87         // layout of stack:
    88         // [0]   <- argumentStackPointer
    89         // [StackFrameSize = N + 1]
    90         // [Arg0] <- argumentStackPointer - 2 - 0
    91         // [Arg1] <- argumentStackPointer - 2 - 1
    92         // [...]
    93         // [ArgN] <- argumentStackPointer - 2 - N
    94         // <Begin of stack frame>
    95         return argumentStack[argumentStackPointer - index - 2];
    96       }
    97     }
    98     private class OpCodes {
    99       public const byte Add = 1;
    100       public const byte Sub = 2;
    101       public const byte Mul = 3;
    102       public const byte Div = 4;
    103 
    104       public const byte Sin = 5;
    105       public const byte Cos = 6;
    106       public const byte Tan = 7;
    107 
    108       public const byte Log = 8;
    109       public const byte Exp = 9;
    110 
    111       public const byte IfThenElse = 10;
    112 
    113       public const byte GT = 11;
    114       public const byte LT = 12;
    115 
    116       public const byte AND = 13;
    117       public const byte OR = 14;
    118       public const byte NOT = 15;
    119 
    120 
    121       public const byte Average = 16;
    122 
    123       public const byte Call = 17;
    124 
    125       public const byte Variable = 18;
    126       public const byte LagVariable = 19;
    127       public const byte Constant = 20;
    128       public const byte Arg = 21;
    129 
    130       public const byte Power = 22;
    131       public const byte Root = 23;
    132       public const byte TimeLag = 24;
    133       public const byte Integral = 25;
    134       public const byte Derivative = 26;
    135 
    136       public const byte VariableCondition = 27;
    137 
    138       public const byte Square = 28;
    139       public const byte SquareRoot = 29;
    140       public const byte Gamma = 30;
    141       public const byte Psi = 31;
    142       public const byte Dawson = 32;
    143       public const byte ExponentialIntegralEi = 33;
    144       public const byte CosineIntegral = 34;
    145       public const byte SineIntegral = 35;
    146       public const byte HyperbolicCosineIntegral = 36;
    147       public const byte HyperbolicSineIntegral = 37;
    148       public const byte FresnelCosineIntegral = 38;
    149       public const byte FresnelSineIntegral = 39;
    150       public const byte AiryA = 40;
    151       public const byte AiryB = 41;
    152       public const byte Norm = 42;
    153       public const byte Erf = 43;
    154       public const byte Bessel = 44;
    155     }
    156     #endregion
    157 
    158     private Dictionary<Type, byte> symbolToOpcode = new Dictionary<Type, byte>() {
    159       { typeof(Addition), OpCodes.Add },
    160       { typeof(Subtraction), OpCodes.Sub },
    161       { typeof(Multiplication), OpCodes.Mul },
    162       { typeof(Division), OpCodes.Div },
    163       { typeof(Sine), OpCodes.Sin },
    164       { typeof(Cosine), OpCodes.Cos },
    165       { typeof(Tangent), OpCodes.Tan },
    166       { typeof(Logarithm), OpCodes.Log },
    167       { typeof(Exponential), OpCodes.Exp },
    168       { typeof(IfThenElse), OpCodes.IfThenElse },
    169       { typeof(GreaterThan), OpCodes.GT },
    170       { typeof(LessThan), OpCodes.LT },
    171       { typeof(And), OpCodes.AND },
    172       { typeof(Or), OpCodes.OR },
    173       { typeof(Not), OpCodes.NOT},
    174       { typeof(Average), OpCodes.Average},
    175       { typeof(InvokeFunction), OpCodes.Call },
    176       { typeof(Variable), OpCodes.Variable },
    177       { typeof(LaggedVariable), OpCodes.LagVariable },
    178       { typeof(Constant), OpCodes.Constant },
    179       { typeof(Argument), OpCodes.Arg },
    180       { typeof(Power),OpCodes.Power},
    181       { typeof(Root),OpCodes.Root},
    182       { typeof(TimeLag), OpCodes.TimeLag},
    183       { typeof(Integral), OpCodes.Integral},
    184       { typeof(Derivative), OpCodes.Derivative},
    185       { typeof(VariableCondition),OpCodes.VariableCondition},
    186       { typeof(Square),OpCodes.Square},
    187       { typeof(SquareRoot),OpCodes.SquareRoot},
    188       { typeof(Gamma), OpCodes.Gamma },
    189       { typeof(Psi), OpCodes.Psi },
    190       { typeof(Dawson), OpCodes.Dawson},
    191       { typeof(ExponentialIntegralEi), OpCodes.ExponentialIntegralEi },
    192       { typeof(CosineIntegral), OpCodes.CosineIntegral },
    193       { typeof(SineIntegral), OpCodes.SineIntegral },
    194       { typeof(HyperbolicCosineIntegral), OpCodes.HyperbolicCosineIntegral },
    195       { typeof(HyperbolicSineIntegral), OpCodes.HyperbolicSineIntegral },
    196       { typeof(FresnelCosineIntegral), OpCodes.FresnelCosineIntegral },
    197       { typeof(FresnelSineIntegral), OpCodes.FresnelSineIntegral },
    198       { typeof(AiryA), OpCodes.AiryA },
    199       { typeof(AiryB), OpCodes.AiryB },
    200       { typeof(Norm), OpCodes.Norm},
    201       { typeof(Erf), OpCodes.Erf},
    202       { typeof(Bessel), OpCodes.Bessel}
    203     };
    204 
    205     public override bool CanChangeName {
    206       get { return false; }
    207     }
    208     public override bool CanChangeDescription {
    209       get { return false; }
    210     }
     37
     38    public override bool CanChangeName { get { return false; } }
     39    public override bool CanChangeDescription { get { return false; } }
    21140
    21241    #region parameter properties
     
    23362
    23463    [StorableConstructor]
    235     private SymbolicDataAnalysisExpressionTreeInterpreter(bool deserializing) : base(deserializing) { }
    236     private SymbolicDataAnalysisExpressionTreeInterpreter(SymbolicDataAnalysisExpressionTreeInterpreter original, Cloner cloner) : base(original, cloner) { }
     64    protected SymbolicDataAnalysisExpressionTreeInterpreter(bool deserializing) : base(deserializing) { }
     65    protected SymbolicDataAnalysisExpressionTreeInterpreter(SymbolicDataAnalysisExpressionTreeInterpreter original, Cloner cloner) : base(original, cloner) { }
    23766    public override IDeepCloneable Clone(Cloner cloner) {
    23867      return new SymbolicDataAnalysisExpressionTreeInterpreter(this, cloner);
     
    24574    }
    24675
     76    protected SymbolicDataAnalysisExpressionTreeInterpreter(string name, string description)
     77      : base(name, description) {
     78      Parameters.Add(new ValueParameter<BoolValue>(CheckExpressionsWithIntervalArithmeticParameterName, "Switch that determines if the interpreter checks the validity of expressions with interval arithmetic before evaluating the expression.", new BoolValue(false)));
     79      Parameters.Add(new ValueParameter<IntValue>(EvaluatedSolutionsParameterName, "A counter for the total number of solutions the interpreter has evaluated", new IntValue(0)));
     80    }
     81
    24782    [StorableHook(HookType.AfterDeserialization)]
    24883    private void AfterDeserialization() {
     
    26196
    26297    public IEnumerable<double> GetSymbolicExpressionTreeValues(ISymbolicExpressionTree tree, Dataset dataset, IEnumerable<int> rows) {
    263       return GetSymbolicExpressionTreeValues(tree, dataset, new string[] { "#NOTHING#" }, rows);
    264     }
    265 
    266     public IEnumerable<double> GetSymbolicExpressionTreeValues(ISymbolicExpressionTree tree, Dataset dataset, string[] targetVariables, IEnumerable<int> rows) {
    267       return GetSymbolicExpressionTreeValues(tree, dataset, targetVariables, rows, 1);
    268     }
    269 
    270 
    271     // for each row for each horizon for each target variable one value
    272     public IEnumerable<double> GetSymbolicExpressionTreeValues(ISymbolicExpressionTree tree, Dataset dataset, string[] targetVariables, IEnumerable<int> rows, int horizon) {
    27398      if (CheckExpressionsWithIntervalArithmetic.Value)
    27499        throw new NotSupportedException("Interval arithmetic is not yet supported in the symbolic data analysis interpreter.");
     100
    275101      EvaluatedSolutions.Value++; // increment the evaluated solutions counter
    276       var compiler = new SymbolicExpressionTreeCompiler();
    277       Instruction[] code = compiler.Compile(tree, MapSymbolToOpCode);
     102      var state = PrepareInterpreterState(tree, dataset);
     103
     104      foreach (var rowEnum in rows) {
     105        int row = rowEnum;
     106        yield return Evaluate(dataset, ref row, state);
     107        state.Reset();
     108      }
     109    }
     110
     111    private InterpreterState PrepareInterpreterState(ISymbolicExpressionTree tree, Dataset dataset) {
     112      Instruction[] code = SymbolicExpressionTreeCompiler.Compile(tree, OpCodes.MapSymbolToOpCode);
    278113      int necessaryArgStackSize = 0;
    279       for (int i = 0; i < code.Length; i++) {
    280         Instruction instr = code[i];
     114      foreach (Instruction instr in code) {
    281115        if (instr.opCode == OpCodes.Variable) {
    282           var variableTreeNode = instr.dynamicNode as VariableTreeNode;
     116          var variableTreeNode = (VariableTreeNode)instr.dynamicNode;
    283117          instr.iArg0 = dataset.GetReadOnlyDoubleValues(variableTreeNode.VariableName);
    284           code[i] = instr;
    285118        } else if (instr.opCode == OpCodes.LagVariable) {
    286           var laggedVariableTreeNode = instr.dynamicNode as LaggedVariableTreeNode;
     119          var laggedVariableTreeNode = (LaggedVariableTreeNode)instr.dynamicNode;
    287120          instr.iArg0 = dataset.GetReadOnlyDoubleValues(laggedVariableTreeNode.VariableName);
    288           code[i] = instr;
    289121        } else if (instr.opCode == OpCodes.VariableCondition) {
    290           var variableConditionTreeNode = instr.dynamicNode as VariableConditionTreeNode;
     122          var variableConditionTreeNode = (VariableConditionTreeNode)instr.dynamicNode;
    291123          instr.iArg0 = dataset.GetReadOnlyDoubleValues(variableConditionTreeNode.VariableName);
    292124        } else if (instr.opCode == OpCodes.Call) {
     
    294126        }
    295127      }
    296       var state = new InterpreterState(code, necessaryArgStackSize);
    297 
    298       int nComponents = tree.Root.GetSubtree(0).SubtreeCount;
    299       // produce a n-step forecast for each target variable for all rows
    300       var cachedPrognosedValues = new Dictionary<string, double[]>();
    301       foreach (var targetVariable in targetVariables)
    302         cachedPrognosedValues[targetVariable] = new double[horizon];
    303       foreach (var rowEnum in rows) {
    304         int row = rowEnum;
    305         foreach (var horizonRow in Enumerable.Range(row, horizon)) {
    306           int localRow = horizonRow; // create a local variable for the ref parameter
    307           for (int c = 0; c < nComponents; c++) {
    308             var prog = Evaluate(dataset, ref localRow, row - 1, state, cachedPrognosedValues);
    309             yield return prog;
    310             cachedPrognosedValues[targetVariables[c]][horizonRow - row] = prog;
    311           }
    312 
    313           state.Reset();
    314         }
    315       }
    316     }
    317 
    318     private double Evaluate(Dataset dataset, ref int row, int lastObservedRow, InterpreterState state, Dictionary<string, double[]> cachedPrognosedValues) {
     128      return new InterpreterState(code, necessaryArgStackSize);
     129    }
     130
     131
     132    protected virtual double Evaluate(Dataset dataset, ref int row, InterpreterState state) {
    319133      Instruction currentInstr = state.NextInstruction();
    320134      switch (currentInstr.opCode) {
    321135        case OpCodes.Add: {
    322             double s = Evaluate(dataset, ref row, lastObservedRow, state, cachedPrognosedValues);
    323             for (int i = 1; i < currentInstr.nArguments; i++) {
    324               s += Evaluate(dataset, ref row, lastObservedRow, state, cachedPrognosedValues);
     136            double s = Evaluate(dataset, ref row, state);
     137            for (int i = 1; i < currentInstr.nArguments; i++) {
     138              s += Evaluate(dataset, ref row, state);
    325139            }
    326140            return s;
    327141          }
    328142        case OpCodes.Sub: {
    329             double s = Evaluate(dataset, ref row, lastObservedRow, state, cachedPrognosedValues);
    330             for (int i = 1; i < currentInstr.nArguments; i++) {
    331               s -= Evaluate(dataset, ref row, lastObservedRow, state, cachedPrognosedValues);
     143            double s = Evaluate(dataset, ref row, state);
     144            for (int i = 1; i < currentInstr.nArguments; i++) {
     145              s -= Evaluate(dataset, ref row, state);
    332146            }
    333147            if (currentInstr.nArguments == 1) s = -s;
     
    335149          }
    336150        case OpCodes.Mul: {
    337             double p = Evaluate(dataset, ref row, lastObservedRow, state, cachedPrognosedValues);
    338             for (int i = 1; i < currentInstr.nArguments; i++) {
    339               p *= Evaluate(dataset, ref row, lastObservedRow, state, cachedPrognosedValues);
     151            double p = Evaluate(dataset, ref row, state);
     152            for (int i = 1; i < currentInstr.nArguments; i++) {
     153              p *= Evaluate(dataset, ref row, state);
    340154            }
    341155            return p;
    342156          }
    343157        case OpCodes.Div: {
    344             double p = Evaluate(dataset, ref row, lastObservedRow, state, cachedPrognosedValues);
    345             for (int i = 1; i < currentInstr.nArguments; i++) {
    346               p /= Evaluate(dataset, ref row, lastObservedRow, state, cachedPrognosedValues);
     158            double p = Evaluate(dataset, ref row, state);
     159            for (int i = 1; i < currentInstr.nArguments; i++) {
     160              p /= Evaluate(dataset, ref row, state);
    347161            }
    348162            if (currentInstr.nArguments == 1) p = 1.0 / p;
     
    350164          }
    351165        case OpCodes.Average: {
    352             double sum = Evaluate(dataset, ref row, lastObservedRow, state, cachedPrognosedValues);
    353             for (int i = 1; i < currentInstr.nArguments; i++) {
    354               sum += Evaluate(dataset, ref row, lastObservedRow, state, cachedPrognosedValues);
     166            double sum = Evaluate(dataset, ref row, state);
     167            for (int i = 1; i < currentInstr.nArguments; i++) {
     168              sum += Evaluate(dataset, ref row, state);
    355169            }
    356170            return sum / currentInstr.nArguments;
    357171          }
    358172        case OpCodes.Cos: {
    359             return Math.Cos(Evaluate(dataset, ref row, lastObservedRow, state, cachedPrognosedValues));
     173            return Math.Cos(Evaluate(dataset, ref row, state));
    360174          }
    361175        case OpCodes.Sin: {
    362             return Math.Sin(Evaluate(dataset, ref row, lastObservedRow, state, cachedPrognosedValues));
     176            return Math.Sin(Evaluate(dataset, ref row, state));
    363177          }
    364178        case OpCodes.Tan: {
    365             return Math.Tan(Evaluate(dataset, ref row, lastObservedRow, state, cachedPrognosedValues));
     179            return Math.Tan(Evaluate(dataset, ref row, state));
    366180          }
    367181        case OpCodes.Square: {
    368             return Math.Pow(Evaluate(dataset, ref row, lastObservedRow, state, cachedPrognosedValues), 2);
     182            return Math.Pow(Evaluate(dataset, ref row, state), 2);
    369183          }
    370184        case OpCodes.Power: {
    371             double x = Evaluate(dataset, ref row, lastObservedRow, state, cachedPrognosedValues);
    372             double y = Math.Round(Evaluate(dataset, ref row, lastObservedRow, state, cachedPrognosedValues));
     185            double x = Evaluate(dataset, ref row, state);
     186            double y = Math.Round(Evaluate(dataset, ref row, state));
    373187            return Math.Pow(x, y);
    374188          }
    375189        case OpCodes.SquareRoot: {
    376             return Math.Sqrt(Evaluate(dataset, ref row, lastObservedRow, state, cachedPrognosedValues));
     190            return Math.Sqrt(Evaluate(dataset, ref row, state));
    377191          }
    378192        case OpCodes.Root: {
    379             double x = Evaluate(dataset, ref row, lastObservedRow, state, cachedPrognosedValues);
    380             double y = Math.Round(Evaluate(dataset, ref row, lastObservedRow, state, cachedPrognosedValues));
     193            double x = Evaluate(dataset, ref row, state);
     194            double y = Math.Round(Evaluate(dataset, ref row, state));
    381195            return Math.Pow(x, 1 / y);
    382196          }
    383197        case OpCodes.Exp: {
    384             return Math.Exp(Evaluate(dataset, ref row, lastObservedRow, state, cachedPrognosedValues));
     198            return Math.Exp(Evaluate(dataset, ref row, state));
    385199          }
    386200        case OpCodes.Log: {
    387             return Math.Log(Evaluate(dataset, ref row, lastObservedRow, state, cachedPrognosedValues));
     201            return Math.Log(Evaluate(dataset, ref row, state));
    388202          }
    389203        case OpCodes.Gamma: {
    390             var x = Evaluate(dataset, ref row, lastObservedRow, state, cachedPrognosedValues);
     204            var x = Evaluate(dataset, ref row, state);
    391205            if (double.IsNaN(x)) return double.NaN;
    392206            else return alglib.gammafunction(x);
    393207          }
    394208        case OpCodes.Psi: {
    395             var x = Evaluate(dataset, ref row, lastObservedRow, state, cachedPrognosedValues);
     209            var x = Evaluate(dataset, ref row, state);
    396210            if (double.IsNaN(x)) return double.NaN;
    397211            else if (x <= 0 && (Math.Floor(x) - x).IsAlmost(0)) return double.NaN;
     
    399213          }
    400214        case OpCodes.Dawson: {
    401             var x = Evaluate(dataset, ref row, lastObservedRow, state, cachedPrognosedValues);
     215            var x = Evaluate(dataset, ref row, state);
    402216            if (double.IsNaN(x)) return double.NaN;
    403217            return alglib.dawsonintegral(x);
    404218          }
    405219        case OpCodes.ExponentialIntegralEi: {
    406             var x = Evaluate(dataset, ref row, lastObservedRow, state, cachedPrognosedValues);
     220            var x = Evaluate(dataset, ref row, state);
    407221            if (double.IsNaN(x)) return double.NaN;
    408222            return alglib.exponentialintegralei(x);
     
    410224        case OpCodes.SineIntegral: {
    411225            double si, ci;
    412             var x = Evaluate(dataset, ref row, lastObservedRow, state, cachedPrognosedValues);
     226            var x = Evaluate(dataset, ref row, state);
    413227            if (double.IsNaN(x)) return double.NaN;
    414228            else {
     
    419233        case OpCodes.CosineIntegral: {
    420234            double si, ci;
    421             var x = Evaluate(dataset, ref row, lastObservedRow, state, cachedPrognosedValues);
     235            var x = Evaluate(dataset, ref row, state);
    422236            if (double.IsNaN(x)) return double.NaN;
    423237            else {
     
    428242        case OpCodes.HyperbolicSineIntegral: {
    429243            double shi, chi;
    430             var x = Evaluate(dataset, ref row, lastObservedRow, state, cachedPrognosedValues);
     244            var x = Evaluate(dataset, ref row, state);
    431245            if (double.IsNaN(x)) return double.NaN;
    432246            else {
     
    437251        case OpCodes.HyperbolicCosineIntegral: {
    438252            double shi, chi;
    439             var x = Evaluate(dataset, ref row, lastObservedRow, state, cachedPrognosedValues);
     253            var x = Evaluate(dataset, ref row, state);
    440254            if (double.IsNaN(x)) return double.NaN;
    441255            else {
     
    446260        case OpCodes.FresnelCosineIntegral: {
    447261            double c = 0, s = 0;
    448             var x = Evaluate(dataset, ref row, lastObservedRow, state, cachedPrognosedValues);
     262            var x = Evaluate(dataset, ref row, state);
    449263            if (double.IsNaN(x)) return double.NaN;
    450264            else {
     
    455269        case OpCodes.FresnelSineIntegral: {
    456270            double c = 0, s = 0;
    457             var x = Evaluate(dataset, ref row, lastObservedRow, state, cachedPrognosedValues);
     271            var x = Evaluate(dataset, ref row, state);
    458272            if (double.IsNaN(x)) return double.NaN;
    459273            else {
     
    464278        case OpCodes.AiryA: {
    465279            double ai, aip, bi, bip;
    466             var x = Evaluate(dataset, ref row, lastObservedRow, state, cachedPrognosedValues);
     280            var x = Evaluate(dataset, ref row, state);
    467281            if (double.IsNaN(x)) return double.NaN;
    468282            else {
     
    473287        case OpCodes.AiryB: {
    474288            double ai, aip, bi, bip;
    475             var x = Evaluate(dataset, ref row, lastObservedRow, state, cachedPrognosedValues);
     289            var x = Evaluate(dataset, ref row, state);
    476290            if (double.IsNaN(x)) return double.NaN;
    477291            else {
     
    481295          }
    482296        case OpCodes.Norm: {
    483             var x = Evaluate(dataset, ref row, lastObservedRow, state, cachedPrognosedValues);
     297            var x = Evaluate(dataset, ref row, state);
    484298            if (double.IsNaN(x)) return double.NaN;
    485299            else return alglib.normaldistribution(x);
    486300          }
    487301        case OpCodes.Erf: {
    488             var x = Evaluate(dataset, ref row, lastObservedRow, state, cachedPrognosedValues);
     302            var x = Evaluate(dataset, ref row, state);
    489303            if (double.IsNaN(x)) return double.NaN;
    490304            else return alglib.errorfunction(x);
    491305          }
    492306        case OpCodes.Bessel: {
    493             var x = Evaluate(dataset, ref row, lastObservedRow, state, cachedPrognosedValues);
     307            var x = Evaluate(dataset, ref row, state);
    494308            if (double.IsNaN(x)) return double.NaN;
    495309            else return alglib.besseli0(x);
    496310          }
    497311        case OpCodes.IfThenElse: {
    498             double condition = Evaluate(dataset, ref row, lastObservedRow, state, cachedPrognosedValues);
     312            double condition = Evaluate(dataset, ref row, state);
    499313            double result;
    500314            if (condition > 0.0) {
    501               result = Evaluate(dataset, ref row, lastObservedRow, state, cachedPrognosedValues); SkipInstructions(state);
     315              result = Evaluate(dataset, ref row, state); state.SkipInstructions();
    502316            } else {
    503               SkipInstructions(state); result = Evaluate(dataset, ref row, lastObservedRow, state, cachedPrognosedValues);
     317              state.SkipInstructions(); result = Evaluate(dataset, ref row, state);
    504318            }
    505319            return result;
    506320          }
    507321        case OpCodes.AND: {
    508             double result = Evaluate(dataset, ref row, lastObservedRow, state, cachedPrognosedValues);
    509             for (int i = 1; i < currentInstr.nArguments; i++) {
    510               if (result > 0.0) result = Evaluate(dataset, ref row, lastObservedRow, state, cachedPrognosedValues);
     322            double result = Evaluate(dataset, ref row, state);
     323            for (int i = 1; i < currentInstr.nArguments; i++) {
     324              if (result > 0.0) result = Evaluate(dataset, ref row, state);
    511325              else {
    512                 SkipInstructions(state);
     326                state.SkipInstructions();
    513327              }
    514328            }
     
    516330          }
    517331        case OpCodes.OR: {
    518             double result = Evaluate(dataset, ref row, lastObservedRow, state, cachedPrognosedValues);
    519             for (int i = 1; i < currentInstr.nArguments; i++) {
    520               if (result <= 0.0) result = Evaluate(dataset, ref row, lastObservedRow, state, cachedPrognosedValues);
     332            double result = Evaluate(dataset, ref row, state);
     333            for (int i = 1; i < currentInstr.nArguments; i++) {
     334              if (result <= 0.0) result = Evaluate(dataset, ref row, state);
    521335              else {
    522                 SkipInstructions(state);
     336                state.SkipInstructions();
    523337              }
    524338            }
     
    526340          }
    527341        case OpCodes.NOT: {
    528             return Evaluate(dataset, ref row, lastObservedRow, state, cachedPrognosedValues) > 0.0 ? -1.0 : 1.0;
     342            return Evaluate(dataset, ref row, state) > 0.0 ? -1.0 : 1.0;
    529343          }
    530344        case OpCodes.GT: {
    531             double x = Evaluate(dataset, ref row, lastObservedRow, state, cachedPrognosedValues);
    532             double y = Evaluate(dataset, ref row, lastObservedRow, state, cachedPrognosedValues);
     345            double x = Evaluate(dataset, ref row, state);
     346            double y = Evaluate(dataset, ref row, state);
    533347            if (x > y) return 1.0;
    534348            else return -1.0;
    535349          }
    536350        case OpCodes.LT: {
    537             double x = Evaluate(dataset, ref row, lastObservedRow, state, cachedPrognosedValues);
    538             double y = Evaluate(dataset, ref row, lastObservedRow, state, cachedPrognosedValues);
     351            double x = Evaluate(dataset, ref row, state);
     352            double y = Evaluate(dataset, ref row, state);
    539353            if (x < y) return 1.0;
    540354            else return -1.0;
     
    543357            var timeLagTreeNode = (LaggedTreeNode)currentInstr.dynamicNode;
    544358            row += timeLagTreeNode.Lag;
    545             double result = Evaluate(dataset, ref row, lastObservedRow, state, cachedPrognosedValues);
     359            double result = Evaluate(dataset, ref row, state);
    546360            row -= timeLagTreeNode.Lag;
    547361            return result;
     
    553367            for (int i = 0; i < Math.Abs(timeLagTreeNode.Lag); i++) {
    554368              row += Math.Sign(timeLagTreeNode.Lag);
    555               sum += Evaluate(dataset, ref row, lastObservedRow, state, cachedPrognosedValues);
     369              sum += Evaluate(dataset, ref row, state);
    556370              state.ProgramCounter = savedPc;
    557371            }
    558372            row -= timeLagTreeNode.Lag;
    559             sum += Evaluate(dataset, ref row, lastObservedRow, state, cachedPrognosedValues);
     373            sum += Evaluate(dataset, ref row, state);
    560374            return sum;
    561375          }
     
    567381        case OpCodes.Derivative: {
    568382            int savedPc = state.ProgramCounter;
    569             double f_0 = Evaluate(dataset, ref row, lastObservedRow, state, cachedPrognosedValues); row--;
     383            double f_0 = Evaluate(dataset, ref row, state); row--;
    570384            state.ProgramCounter = savedPc;
    571             double f_1 = Evaluate(dataset, ref row, lastObservedRow, state, cachedPrognosedValues); row -= 2;
     385            double f_1 = Evaluate(dataset, ref row, state); row -= 2;
    572386            state.ProgramCounter = savedPc;
    573             double f_3 = Evaluate(dataset, ref row, lastObservedRow, state, cachedPrognosedValues); row--;
     387            double f_3 = Evaluate(dataset, ref row, state); row--;
    574388            state.ProgramCounter = savedPc;
    575             double f_4 = Evaluate(dataset, ref row, lastObservedRow, state, cachedPrognosedValues);
     389            double f_4 = Evaluate(dataset, ref row, state);
    576390            row += 4;
    577391
     
    582396            double[] argValues = new double[currentInstr.nArguments];
    583397            for (int i = 0; i < currentInstr.nArguments; i++) {
    584               argValues[i] = Evaluate(dataset, ref row, lastObservedRow, state, cachedPrognosedValues);
     398              argValues[i] = Evaluate(dataset, ref row, state);
    585399            }
    586400            // push on argument values on stack
     
    592406            state.ProgramCounter = (ushort)currentInstr.iArg0;
    593407            // evaluate the function
    594             double v = Evaluate(dataset, ref row, lastObservedRow, state, cachedPrognosedValues);
     408            double v = Evaluate(dataset, ref row, state);
    595409
    596410            // delete the stack frame
     
    608422              return double.NaN;
    609423            var variableTreeNode = (VariableTreeNode)currentInstr.dynamicNode;
    610             if (row <= lastObservedRow || !cachedPrognosedValues.ContainsKey(variableTreeNode.VariableName)) return ((IList<double>)currentInstr.iArg0)[row] * variableTreeNode.Weight;
    611             else return cachedPrognosedValues[variableTreeNode.VariableName][row - lastObservedRow - 1] * variableTreeNode.Weight;
     424            return ((IList<double>)currentInstr.iArg0)[row] * variableTreeNode.Weight;
    612425          }
    613426        case OpCodes.LagVariable: {
     
    616429            if (actualRow < 0 || actualRow >= dataset.Rows)
    617430              return double.NaN;
    618             if (actualRow <= lastObservedRow || !cachedPrognosedValues.ContainsKey(laggedVariableTreeNode.VariableName)) return ((IList<double>)currentInstr.iArg0)[actualRow] * laggedVariableTreeNode.Weight;
    619             else return cachedPrognosedValues[laggedVariableTreeNode.VariableName][actualRow - lastObservedRow - 1] * laggedVariableTreeNode.Weight;
     431            return ((IList<double>)currentInstr.iArg0)[actualRow] * laggedVariableTreeNode.Weight;
    620432          }
    621433        case OpCodes.Constant: {
    622             var constTreeNode = currentInstr.dynamicNode as ConstantTreeNode;
     434            var constTreeNode = (ConstantTreeNode)currentInstr.dynamicNode;
    623435            return constTreeNode.Value;
    624436          }
     
    630442              return double.NaN;
    631443            var variableConditionTreeNode = (VariableConditionTreeNode)currentInstr.dynamicNode;
    632             double variableValue;
    633             if (row <= lastObservedRow || !cachedPrognosedValues.ContainsKey(variableConditionTreeNode.VariableName))
    634               variableValue = ((IList<double>)currentInstr.iArg0)[row];
    635             else
    636               variableValue = cachedPrognosedValues[variableConditionTreeNode.VariableName][row - lastObservedRow - 1];
    637 
     444            double variableValue = ((IList<double>)currentInstr.iArg0)[row];
    638445            double x = variableValue - variableConditionTreeNode.Threshold;
    639446            double p = 1 / (1 + Math.Exp(-variableConditionTreeNode.Slope * x));
    640447
    641             double trueBranch = Evaluate(dataset, ref row, lastObservedRow, state, cachedPrognosedValues);
    642             double falseBranch = Evaluate(dataset, ref row, lastObservedRow, state, cachedPrognosedValues);
     448            double trueBranch = Evaluate(dataset, ref row, state);
     449            double falseBranch = Evaluate(dataset, ref row, state);
    643450
    644451            return trueBranch * p + falseBranch * (1 - p);
     
    647454      }
    648455    }
    649 
    650     private byte MapSymbolToOpCode(ISymbolicExpressionTreeNode treeNode) {
    651       byte opCode;
    652       if (!symbolToOpcode.TryGetValue(treeNode.Symbol.GetType(), out opCode))
    653         throw new NotSupportedException("Symbol: " + treeNode.Symbol);
    654       return opCode;
    655     }
    656 
    657     // skips a whole branch
    658     private void SkipInstructions(InterpreterState state) {
    659       int i = 1;
    660       while (i > 0) {
    661         i += state.NextInstruction().nArguments;
    662         i--;
    663       }
    664     }
    665456  }
    666457}
Note: See TracChangeset for help on using the changeset viewer.