Free cookie consent management tool by TermsFeed Policy Generator

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

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

File:
1 edited

Legend:

Unmodified
Added
Removed
  • 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.