Free cookie consent management tool by TermsFeed Policy Generator

source: trunk/sources/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/SymbolicDataAnalysisExpressionTreeILEmittingInterpreter.cs @ 6868

Last change on this file since 6868 was 6849, checked in by gkronber, 13 years ago

#1480 experimental change to potentially improve performance of interpreters.

File size: 27.7 KB
RevLine 
[6732]1#region License Information
2/* HeuristicLab
3 * Copyright (C) 2002-2011 Heuristic and Evolutionary Algorithms Laboratory (HEAL)
4 *
5 * This file is part of HeuristicLab.
6 *
7 * HeuristicLab is free software: you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation, either version 3 of the License, or
10 * (at your option) any later version.
11 *
12 * HeuristicLab is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15 * GNU General Public License for more details.
16 *
17 * You should have received a copy of the GNU General Public License
18 * along with HeuristicLab. If not, see <http://www.gnu.org/licenses/>.
19 */
20#endregion
21
22using System;
[6741]23using System.Collections.ObjectModel;
24using System.Linq;
[6732]25using System.Collections.Generic;
26using System.Reflection;
27using System.Reflection.Emit;
28using HeuristicLab.Common;
29using HeuristicLab.Core;
[6740]30using HeuristicLab.Data;
[6732]31using HeuristicLab.Encodings.SymbolicExpressionTreeEncoding;
[6740]32using HeuristicLab.Parameters;
[6732]33using HeuristicLab.Persistence.Default.CompositeSerializers.Storable;
34
35namespace HeuristicLab.Problems.DataAnalysis.Symbolic {
36  [StorableClass]
37  [Item("SymbolicDataAnalysisExpressionTreeILEmittingInterpreter", "Interpreter for symbolic expression trees.")]
38  public sealed class SymbolicDataAnalysisExpressionTreeILEmittingInterpreter : ParameterizedNamedItem, ISymbolicDataAnalysisExpressionTreeInterpreter {
[6741]39    private static MethodInfo listGetValue = typeof(IList<double>).GetProperty("Item", new Type[] { typeof(int) }).GetGetMethod();
[6732]40    private static MethodInfo cos = typeof(Math).GetMethod("Cos", new Type[] { typeof(double) });
41    private static MethodInfo sin = typeof(Math).GetMethod("Sin", new Type[] { typeof(double) });
42    private static MethodInfo tan = typeof(Math).GetMethod("Tan", new Type[] { typeof(double) });
43    private static MethodInfo exp = typeof(Math).GetMethod("Exp", new Type[] { typeof(double) });
44    private static MethodInfo log = typeof(Math).GetMethod("Log", new Type[] { typeof(double) });
45    private static MethodInfo power = typeof(Math).GetMethod("Pow", new Type[] { typeof(double), typeof(double) });
[6755]46    private static MethodInfo round = typeof(Math).GetMethod("Round", new Type[] { typeof(double) });
[6732]47
[6741]48    internal delegate double CompiledFunction(int sampleIndex, IList<double>[] columns);
[6732]49    private const string CheckExpressionsWithIntervalArithmeticParameterName = "CheckExpressionsWithIntervalArithmetic";
50    #region private classes
51    private class InterpreterState {
52      private Instruction[] code;
53      private int pc;
[6849]54
[6732]55      public int ProgramCounter {
56        get { return pc; }
57        set { pc = value; }
58      }
[6849]59
60      private bool inLaggedContext;
61      public bool InLaggedContext {
62        get { return inLaggedContext; }
63        set { inLaggedContext = value; }
64      }
65      internal InterpreterState(Instruction[] code) {
66        this.inLaggedContext = false;
[6732]67        this.code = code;
68        this.pc = 0;
69      }
70
71      internal Instruction NextInstruction() {
72        return code[pc++];
73      }
74    }
75    private class OpCodes {
76      public const byte Add = 1;
77      public const byte Sub = 2;
78      public const byte Mul = 3;
79      public const byte Div = 4;
80
81      public const byte Sin = 5;
82      public const byte Cos = 6;
83      public const byte Tan = 7;
84
85      public const byte Log = 8;
86      public const byte Exp = 9;
87
88      public const byte IfThenElse = 10;
89
90      public const byte GT = 11;
91      public const byte LT = 12;
92
93      public const byte AND = 13;
94      public const byte OR = 14;
95      public const byte NOT = 15;
96
97
98      public const byte Average = 16;
99
100      public const byte Call = 17;
101
102      public const byte Variable = 18;
103      public const byte LagVariable = 19;
104      public const byte Constant = 20;
105      public const byte Arg = 21;
106
107      public const byte Power = 22;
108      public const byte Root = 23;
109      public const byte TimeLag = 24;
110      public const byte Integral = 25;
111      public const byte Derivative = 26;
112
113      public const byte VariableCondition = 27;
114    }
115    #endregion
116
117    private Dictionary<Type, byte> symbolToOpcode = new Dictionary<Type, byte>() {
118      { typeof(Addition), OpCodes.Add },
119      { typeof(Subtraction), OpCodes.Sub },
120      { typeof(Multiplication), OpCodes.Mul },
121      { typeof(Division), OpCodes.Div },
122      { typeof(Sine), OpCodes.Sin },
123      { typeof(Cosine), OpCodes.Cos },
124      { typeof(Tangent), OpCodes.Tan },
125      { typeof(Logarithm), OpCodes.Log },
126      { typeof(Exponential), OpCodes.Exp },
127      { typeof(IfThenElse), OpCodes.IfThenElse },
128      { typeof(GreaterThan), OpCodes.GT },
129      { typeof(LessThan), OpCodes.LT },
130      { typeof(And), OpCodes.AND },
131      { typeof(Or), OpCodes.OR },
132      { typeof(Not), OpCodes.NOT},
133      { typeof(Average), OpCodes.Average},
134      { typeof(InvokeFunction), OpCodes.Call },
135      { typeof(HeuristicLab.Problems.DataAnalysis.Symbolic.Variable), OpCodes.Variable },
136      { typeof(LaggedVariable), OpCodes.LagVariable },
137      { typeof(Constant), OpCodes.Constant },
138      { typeof(Argument), OpCodes.Arg },
139      { typeof(Power),OpCodes.Power},
140      { typeof(Root),OpCodes.Root},
141      { typeof(TimeLag), OpCodes.TimeLag},
142      { typeof(Integral), OpCodes.Integral},
143      { typeof(Derivative), OpCodes.Derivative},
144      { typeof(VariableCondition),OpCodes.VariableCondition}
145    };
146
147    public override bool CanChangeName {
148      get { return false; }
149    }
150    public override bool CanChangeDescription {
151      get { return false; }
152    }
153
154    #region parameter properties
155    public IValueParameter<BoolValue> CheckExpressionsWithIntervalArithmeticParameter {
156      get { return (IValueParameter<BoolValue>)Parameters[CheckExpressionsWithIntervalArithmeticParameterName]; }
157    }
158    #endregion
159
160    #region properties
161    public BoolValue CheckExpressionsWithIntervalArithmetic {
162      get { return CheckExpressionsWithIntervalArithmeticParameter.Value; }
163      set { CheckExpressionsWithIntervalArithmeticParameter.Value = value; }
164    }
165    #endregion
166
167
168    [StorableConstructor]
169    private SymbolicDataAnalysisExpressionTreeILEmittingInterpreter(bool deserializing) : base(deserializing) { }
170    private SymbolicDataAnalysisExpressionTreeILEmittingInterpreter(SymbolicDataAnalysisExpressionTreeILEmittingInterpreter original, Cloner cloner) : base(original, cloner) { }
171    public override IDeepCloneable Clone(Cloner cloner) {
172      return new SymbolicDataAnalysisExpressionTreeILEmittingInterpreter(this, cloner);
173    }
174
175    public SymbolicDataAnalysisExpressionTreeILEmittingInterpreter()
176      : base("SymbolicDataAnalysisExpressionTreeILEmittingInterpreter", "Interpreter for symbolic expression trees.") {
177      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)));
178    }
179
180    public IEnumerable<double> GetSymbolicExpressionTreeValues(ISymbolicExpressionTree tree, Dataset dataset, IEnumerable<int> rows) {
181      if (CheckExpressionsWithIntervalArithmetic.Value)
182        throw new NotSupportedException("Interval arithmetic is not yet supported in the symbolic data analysis interpreter.");
183      var compiler = new SymbolicExpressionTreeCompiler();
184      Instruction[] code = compiler.Compile(tree, MapSymbolToOpCode);
185      int necessaryArgStackSize = 0;
[6741]186
187      Dictionary<string, int> doubleVariableNames = dataset.DoubleVariables.Select((x, i) => new { x, i }).ToDictionary(e => e.x, e => e.i);
188      IList<double>[] columns = (from v in doubleVariableNames.Keys
189                                 select dataset.GetReadOnlyDoubleValues(v))
190                                .ToArray();
191
[6732]192      for (int i = 0; i < code.Length; i++) {
193        Instruction instr = code[i];
194        if (instr.opCode == OpCodes.Variable) {
195          var variableTreeNode = instr.dynamicNode as VariableTreeNode;
[6741]196          instr.iArg0 = doubleVariableNames[variableTreeNode.VariableName];
[6732]197          code[i] = instr;
198        } else if (instr.opCode == OpCodes.LagVariable) {
199          var variableTreeNode = instr.dynamicNode as LaggedVariableTreeNode;
[6741]200          instr.iArg0 = doubleVariableNames[variableTreeNode.VariableName];
[6732]201          code[i] = instr;
202        } else if (instr.opCode == OpCodes.VariableCondition) {
203          var variableConditionTreeNode = instr.dynamicNode as VariableConditionTreeNode;
[6741]204          instr.iArg0 = doubleVariableNames[variableConditionTreeNode.VariableName];
[6732]205        } else if (instr.opCode == OpCodes.Call) {
206          necessaryArgStackSize += instr.nArguments + 1;
207        }
208      }
[6849]209      var state = new InterpreterState(code);
[6732]210
[6741]211      Type[] methodArgs = { typeof(int), typeof(IList<double>[]) };
[6732]212      DynamicMethod testFun = new DynamicMethod("TestFun", typeof(double), methodArgs, typeof(SymbolicDataAnalysisExpressionTreeILEmittingInterpreter).Module);
213
214      ILGenerator il = testFun.GetILGenerator();
[6809]215      CompileInstructions(il, state, dataset);
[6732]216      il.Emit(System.Reflection.Emit.OpCodes.Conv_R8);
217      il.Emit(System.Reflection.Emit.OpCodes.Ret);
218      var function = (CompiledFunction)testFun.CreateDelegate(typeof(CompiledFunction));
219
220      foreach (var row in rows) {
[6741]221        yield return function(row, columns);
[6732]222      }
223    }
224
[6809]225    private void CompileInstructions(ILGenerator il, InterpreterState state, Dataset ds) {
[6732]226      Instruction currentInstr = state.NextInstruction();
227      int nArgs = currentInstr.nArguments;
228
229      switch (currentInstr.opCode) {
230        case OpCodes.Add: {
231            if (nArgs > 0) {
[6809]232              CompileInstructions(il, state, ds);
[6732]233            }
234            for (int i = 1; i < nArgs; i++) {
[6809]235              CompileInstructions(il, state, ds);
[6732]236              il.Emit(System.Reflection.Emit.OpCodes.Add);
237            }
238            return;
239          }
240        case OpCodes.Sub: {
241            if (nArgs == 1) {
[6809]242              CompileInstructions(il, state, ds);
[6732]243              il.Emit(System.Reflection.Emit.OpCodes.Neg);
244              return;
245            }
246            if (nArgs > 0) {
[6809]247              CompileInstructions(il, state, ds);
[6732]248            }
249            for (int i = 1; i < nArgs; i++) {
[6809]250              CompileInstructions(il, state, ds);
[6732]251              il.Emit(System.Reflection.Emit.OpCodes.Sub);
252            }
253            return;
254          }
255        case OpCodes.Mul: {
256            if (nArgs > 0) {
[6809]257              CompileInstructions(il, state, ds);
[6732]258            }
259            for (int i = 1; i < nArgs; i++) {
[6809]260              CompileInstructions(il, state, ds);
[6732]261              il.Emit(System.Reflection.Emit.OpCodes.Mul);
262            }
263            return;
264          }
265        case OpCodes.Div: {
266            if (nArgs == 1) {
267              il.Emit(System.Reflection.Emit.OpCodes.Ldc_R8, 1.0);
[6809]268              CompileInstructions(il, state, ds);
[6732]269              il.Emit(System.Reflection.Emit.OpCodes.Div);
270              return;
271            }
272            if (nArgs > 0) {
[6809]273              CompileInstructions(il, state, ds);
[6732]274            }
275            for (int i = 1; i < nArgs; i++) {
[6809]276              CompileInstructions(il, state, ds);
[6732]277              il.Emit(System.Reflection.Emit.OpCodes.Div);
278            }
279            return;
280          }
281        case OpCodes.Average: {
[6809]282            CompileInstructions(il, state, ds);
[6732]283            for (int i = 1; i < nArgs; i++) {
[6809]284              CompileInstructions(il, state, ds);
[6732]285              il.Emit(System.Reflection.Emit.OpCodes.Add);
286            }
287            il.Emit(System.Reflection.Emit.OpCodes.Ldc_I4, nArgs);
288            il.Emit(System.Reflection.Emit.OpCodes.Div);
289            return;
290          }
291        case OpCodes.Cos: {
[6809]292            CompileInstructions(il, state, ds);
[6732]293            il.Emit(System.Reflection.Emit.OpCodes.Call, cos);
294            return;
295          }
296        case OpCodes.Sin: {
[6809]297            CompileInstructions(il, state, ds);
[6732]298            il.Emit(System.Reflection.Emit.OpCodes.Call, sin);
299            return;
300          }
301        case OpCodes.Tan: {
[6809]302            CompileInstructions(il, state, ds);
[6732]303            il.Emit(System.Reflection.Emit.OpCodes.Call, tan);
304            return;
305          }
306        case OpCodes.Power: {
[6809]307            CompileInstructions(il, state, ds);
308            CompileInstructions(il, state, ds);
[6755]309            il.Emit(System.Reflection.Emit.OpCodes.Call, round);
[6732]310            il.Emit(System.Reflection.Emit.OpCodes.Call, power);
311            return;
312          }
313        case OpCodes.Root: {
[6809]314            CompileInstructions(il, state, ds);
[6755]315            il.Emit(System.Reflection.Emit.OpCodes.Ldc_R8, 1.0); // 1 / round(...)
[6809]316            CompileInstructions(il, state, ds);
[6755]317            il.Emit(System.Reflection.Emit.OpCodes.Call, round);
318            il.Emit(System.Reflection.Emit.OpCodes.Div);
319            il.Emit(System.Reflection.Emit.OpCodes.Call, power);
320            return;
[6732]321          }
322        case OpCodes.Exp: {
[6809]323            CompileInstructions(il, state, ds);
[6732]324            il.Emit(System.Reflection.Emit.OpCodes.Call, exp);
325            return;
326          }
327        case OpCodes.Log: {
[6809]328            CompileInstructions(il, state, ds);
[6732]329            il.Emit(System.Reflection.Emit.OpCodes.Call, log);
330            return;
331          }
332        case OpCodes.IfThenElse: {
333            Label end = il.DefineLabel();
334            Label c1 = il.DefineLabel();
[6809]335            CompileInstructions(il, state, ds);
[6732]336            il.Emit(System.Reflection.Emit.OpCodes.Ldc_I4_0); // > 0
337            il.Emit(System.Reflection.Emit.OpCodes.Cgt);
338            il.Emit(System.Reflection.Emit.OpCodes.Brfalse, c1);
[6809]339            CompileInstructions(il, state, ds);
[6732]340            il.Emit(System.Reflection.Emit.OpCodes.Br, end);
341            il.MarkLabel(c1);
[6809]342            CompileInstructions(il, state, ds);
[6732]343            il.MarkLabel(end);
344            return;
345          }
346        case OpCodes.AND: {
347            Label falseBranch = il.DefineLabel();
348            Label end = il.DefineLabel();
[6809]349            CompileInstructions(il, state, ds);
[6732]350            for (int i = 1; i < nArgs; i++) {
351              il.Emit(System.Reflection.Emit.OpCodes.Ldc_I4_0); // > 0
352              il.Emit(System.Reflection.Emit.OpCodes.Cgt);
353              il.Emit(System.Reflection.Emit.OpCodes.Brfalse, falseBranch);
[6809]354              CompileInstructions(il, state, ds);
[6732]355            }
356            il.Emit(System.Reflection.Emit.OpCodes.Ldc_I4_0); // > 0
357            il.Emit(System.Reflection.Emit.OpCodes.Cgt);
358            il.Emit(System.Reflection.Emit.OpCodes.Brfalse, falseBranch);
359            il.Emit(System.Reflection.Emit.OpCodes.Ldc_R8, 1.0); // 1
360            il.Emit(System.Reflection.Emit.OpCodes.Br, end);
361            il.MarkLabel(falseBranch);
362            il.Emit(System.Reflection.Emit.OpCodes.Ldc_R8, 1.0); // -1
363            il.Emit(System.Reflection.Emit.OpCodes.Neg);
364            il.MarkLabel(end);
365            return;
366          }
367        case OpCodes.OR: {
368            Label trueBranch = il.DefineLabel();
369            Label end = il.DefineLabel();
370            Label resultBranch = il.DefineLabel();
[6809]371            CompileInstructions(il, state, ds);
[6732]372            for (int i = 1; i < nArgs; i++) {
373              Label nextArgBranch = il.DefineLabel();
374              // complex definition because of special properties of NaN 
375              il.Emit(System.Reflection.Emit.OpCodes.Dup);
376              il.Emit(System.Reflection.Emit.OpCodes.Ldc_I4_0); // <= 0       
377              il.Emit(System.Reflection.Emit.OpCodes.Ble, nextArgBranch);
378              il.Emit(System.Reflection.Emit.OpCodes.Br, resultBranch);
379              il.MarkLabel(nextArgBranch);
380              il.Emit(System.Reflection.Emit.OpCodes.Pop);
[6809]381              CompileInstructions(il, state, ds);
[6732]382            }
383            il.MarkLabel(resultBranch);
384            il.Emit(System.Reflection.Emit.OpCodes.Ldc_I4_0); // > 0
385            il.Emit(System.Reflection.Emit.OpCodes.Cgt);
386            il.Emit(System.Reflection.Emit.OpCodes.Brtrue, trueBranch);
387            il.Emit(System.Reflection.Emit.OpCodes.Ldc_R8, 1.0); // -1
388            il.Emit(System.Reflection.Emit.OpCodes.Neg);
389            il.Emit(System.Reflection.Emit.OpCodes.Br, end);
390            il.MarkLabel(trueBranch);
391            il.Emit(System.Reflection.Emit.OpCodes.Ldc_R8, 1.0); // 1
392            il.MarkLabel(end);
393            return;
394          }
395        case OpCodes.NOT: {
[6809]396            CompileInstructions(il, state, ds);
[6732]397            il.Emit(System.Reflection.Emit.OpCodes.Ldc_I4_0); // > 0
398            il.Emit(System.Reflection.Emit.OpCodes.Cgt);
399            il.Emit(System.Reflection.Emit.OpCodes.Ldc_R8, 2.0); // * 2
400            il.Emit(System.Reflection.Emit.OpCodes.Mul);
401            il.Emit(System.Reflection.Emit.OpCodes.Ldc_R8, 1.0); // - 1
402            il.Emit(System.Reflection.Emit.OpCodes.Sub);
403            il.Emit(System.Reflection.Emit.OpCodes.Neg); // * -1
404            return;
405          }
406        case OpCodes.GT: {
[6809]407            CompileInstructions(il, state, ds);
408            CompileInstructions(il, state, ds);
409
[6732]410            il.Emit(System.Reflection.Emit.OpCodes.Cgt); // 1 (>) / 0 (otherwise)
411            il.Emit(System.Reflection.Emit.OpCodes.Ldc_R8, 2.0); // * 2
412            il.Emit(System.Reflection.Emit.OpCodes.Mul);
413            il.Emit(System.Reflection.Emit.OpCodes.Ldc_R8, 1.0); // - 1
414            il.Emit(System.Reflection.Emit.OpCodes.Sub);
415            return;
416          }
417        case OpCodes.LT: {
[6809]418            CompileInstructions(il, state, ds);
419            CompileInstructions(il, state, ds);
[6732]420            il.Emit(System.Reflection.Emit.OpCodes.Clt);
421            il.Emit(System.Reflection.Emit.OpCodes.Ldc_R8, 2.0); // * 2
422            il.Emit(System.Reflection.Emit.OpCodes.Mul);
423            il.Emit(System.Reflection.Emit.OpCodes.Ldc_R8, 1.0); // - 1
424            il.Emit(System.Reflection.Emit.OpCodes.Sub);
425            return;
426          }
427        case OpCodes.TimeLag: {
[6809]428            LaggedTreeNode laggedTreeNode = (LaggedTreeNode)currentInstr.dynamicNode;
429            il.Emit(System.Reflection.Emit.OpCodes.Ldarg_0); // row -= lag
430            il.Emit(System.Reflection.Emit.OpCodes.Ldc_I4, laggedTreeNode.Lag);
431            il.Emit(System.Reflection.Emit.OpCodes.Add);
432            il.Emit(System.Reflection.Emit.OpCodes.Starg, 0);
[6849]433            var prevLaggedContext = state.InLaggedContext;
434            state.InLaggedContext = true;
[6809]435            CompileInstructions(il, state, ds);
436            il.Emit(System.Reflection.Emit.OpCodes.Ldarg_0); // row += lag
437            il.Emit(System.Reflection.Emit.OpCodes.Ldc_I4, laggedTreeNode.Lag);
438            il.Emit(System.Reflection.Emit.OpCodes.Sub);
439            il.Emit(System.Reflection.Emit.OpCodes.Starg, 0);
[6849]440            state.InLaggedContext = prevLaggedContext;
[6809]441            return;
[6732]442          }
443        case OpCodes.Integral: {
[6809]444            int savedPc = state.ProgramCounter;
445            LaggedTreeNode laggedTreeNode = (LaggedTreeNode)currentInstr.dynamicNode;
446            il.Emit(System.Reflection.Emit.OpCodes.Ldarg_0); // row -= lag
447            il.Emit(System.Reflection.Emit.OpCodes.Ldc_I4, laggedTreeNode.Lag);
448            il.Emit(System.Reflection.Emit.OpCodes.Add);
449            il.Emit(System.Reflection.Emit.OpCodes.Starg, 0);
[6849]450            var prevLaggedContext = state.InLaggedContext;
451            state.InLaggedContext = true;
[6809]452            CompileInstructions(il, state, ds);
453            for (int l = laggedTreeNode.Lag; l < 0; l++) {
454              il.Emit(System.Reflection.Emit.OpCodes.Ldarg_0); // row += lag
455              il.Emit(System.Reflection.Emit.OpCodes.Ldc_I4_1);
456              il.Emit(System.Reflection.Emit.OpCodes.Add);
457              il.Emit(System.Reflection.Emit.OpCodes.Starg, 0);
458              state.ProgramCounter = savedPc;
459              CompileInstructions(il, state, ds);
460              il.Emit(System.Reflection.Emit.OpCodes.Add);
461            }
[6849]462            state.InLaggedContext = prevLaggedContext;
[6809]463            return;
[6732]464          }
465
466        //mkommend: derivate calculation taken from:
467        //http://www.holoborodko.com/pavel/numerical-methods/numerical-derivative/smooth-low-noise-differentiators/
468        //one sided smooth differentiatior, N = 4
469        // y' = 1/8h (f_i + 2f_i-1, -2 f_i-3 - f_i-4)
470        case OpCodes.Derivative: {
[6809]471            int savedPc = state.ProgramCounter;
472            CompileInstructions(il, state, ds);
473            il.Emit(System.Reflection.Emit.OpCodes.Ldarg_0); // row --
474            il.Emit(System.Reflection.Emit.OpCodes.Ldc_I4_M1);
475            il.Emit(System.Reflection.Emit.OpCodes.Add);
476            il.Emit(System.Reflection.Emit.OpCodes.Starg, 0);
477            state.ProgramCounter = savedPc;
[6849]478            var prevLaggedContext = state.InLaggedContext;
479            state.InLaggedContext = true;
[6809]480            CompileInstructions(il, state, ds);
481            il.Emit(System.Reflection.Emit.OpCodes.Ldc_R8, 2.0); // f_0 + 2 * f_1
482            il.Emit(System.Reflection.Emit.OpCodes.Mul);
483            il.Emit(System.Reflection.Emit.OpCodes.Add);
484
485            il.Emit(System.Reflection.Emit.OpCodes.Ldarg_0); // row -=2
486            il.Emit(System.Reflection.Emit.OpCodes.Ldc_I4_2);
487            il.Emit(System.Reflection.Emit.OpCodes.Sub);
488            il.Emit(System.Reflection.Emit.OpCodes.Starg, 0);
489            state.ProgramCounter = savedPc;
490            CompileInstructions(il, state, ds);
491            il.Emit(System.Reflection.Emit.OpCodes.Ldc_R8, 2.0); // f_0 + 2 * f_1 - 2 * f_3
492            il.Emit(System.Reflection.Emit.OpCodes.Mul);
493            il.Emit(System.Reflection.Emit.OpCodes.Sub);
494
495            il.Emit(System.Reflection.Emit.OpCodes.Ldarg_0); // row --
496            il.Emit(System.Reflection.Emit.OpCodes.Ldc_I4_M1);
497            il.Emit(System.Reflection.Emit.OpCodes.Add);
498            il.Emit(System.Reflection.Emit.OpCodes.Starg, 0);
499            state.ProgramCounter = savedPc;
500            CompileInstructions(il, state, ds);
501            il.Emit(System.Reflection.Emit.OpCodes.Sub); // f_0 + 2 * f_1 - 2 * f_3 - f_4
502            il.Emit(System.Reflection.Emit.OpCodes.Ldc_R8, 8.0); // / 8
503            il.Emit(System.Reflection.Emit.OpCodes.Div);
504
505            il.Emit(System.Reflection.Emit.OpCodes.Ldarg_0); // row +=4
506            il.Emit(System.Reflection.Emit.OpCodes.Ldc_I4_4);
507            il.Emit(System.Reflection.Emit.OpCodes.Add);
508            il.Emit(System.Reflection.Emit.OpCodes.Starg, 0);
[6849]509            state.InLaggedContext = prevLaggedContext;
[6809]510            return;
[6732]511          }
512        case OpCodes.Call: {
[6770]513            throw new NotSupportedException("Automatically defined functions are not supported by the SymbolicDataAnalysisTreeILEmittingInterpreter. Either turn of ADFs or change the interpeter.");
[6732]514          }
515        case OpCodes.Arg: {
[6770]516            throw new NotSupportedException("Automatically defined functions are not supported by the SymbolicDataAnalysisTreeILEmittingInterpreter. Either turn of ADFs or change the interpeter.");
[6732]517          }
518        case OpCodes.Variable: {
[6741]519            VariableTreeNode varNode = (VariableTreeNode)currentInstr.dynamicNode;
520            il.Emit(System.Reflection.Emit.OpCodes.Ldarg_1); // load columns array
[6849]521            il.Emit(System.Reflection.Emit.OpCodes.Ldc_I4, (int)currentInstr.iArg0);
522            // load correct column of the current variable
[6741]523            il.Emit(System.Reflection.Emit.OpCodes.Ldelem_Ref);
[6849]524            il.Emit(System.Reflection.Emit.OpCodes.Ldarg_0); // rowIndex
525            if (!state.InLaggedContext) {
526              il.Emit(System.Reflection.Emit.OpCodes.Call, listGetValue);
527              il.Emit(System.Reflection.Emit.OpCodes.Ldc_R8, varNode.Weight); // load weight
528              il.Emit(System.Reflection.Emit.OpCodes.Mul);
529            } else {
530              var nanResult = il.DefineLabel();
531              var normalResult = il.DefineLabel();
532              il.Emit(System.Reflection.Emit.OpCodes.Dup);
533              il.Emit(System.Reflection.Emit.OpCodes.Ldc_I4_0);
534              il.Emit(System.Reflection.Emit.OpCodes.Blt, nanResult);
535              il.Emit(System.Reflection.Emit.OpCodes.Dup);
536              il.Emit(System.Reflection.Emit.OpCodes.Ldc_I4, ds.Rows);
537              il.Emit(System.Reflection.Emit.OpCodes.Bge, nanResult);
538              il.Emit(System.Reflection.Emit.OpCodes.Call, listGetValue);
539              il.Emit(System.Reflection.Emit.OpCodes.Ldc_R8, varNode.Weight); // load weight
540              il.Emit(System.Reflection.Emit.OpCodes.Mul);
541              il.Emit(System.Reflection.Emit.OpCodes.Br, normalResult);
542              il.MarkLabel(nanResult);
543              il.Emit(System.Reflection.Emit.OpCodes.Pop); // rowIndex
544              il.Emit(System.Reflection.Emit.OpCodes.Pop); // column reference
545              il.Emit(System.Reflection.Emit.OpCodes.Ldc_R8, double.NaN);
546              il.MarkLabel(normalResult);
547            }
[6732]548            return;
549          }
550        case OpCodes.LagVariable: {
[6809]551            var nanResult = il.DefineLabel();
552            var normalResult = il.DefineLabel();
[6770]553            LaggedVariableTreeNode varNode = (LaggedVariableTreeNode)currentInstr.dynamicNode;
554            il.Emit(System.Reflection.Emit.OpCodes.Ldarg_1); // load columns array
555            il.Emit(System.Reflection.Emit.OpCodes.Ldc_I4, (int)currentInstr.iArg0); // load correct column of the current variable
556            il.Emit(System.Reflection.Emit.OpCodes.Ldelem_Ref);
557            il.Emit(System.Reflection.Emit.OpCodes.Ldc_I4, varNode.Lag); // lag
[6849]558            il.Emit(System.Reflection.Emit.OpCodes.Ldarg_0); // rowIndex
559            il.Emit(System.Reflection.Emit.OpCodes.Add); // actualRowIndex = rowIndex + sampleOffset
[6809]560            il.Emit(System.Reflection.Emit.OpCodes.Dup);
561            il.Emit(System.Reflection.Emit.OpCodes.Ldc_I4_0);
562            il.Emit(System.Reflection.Emit.OpCodes.Blt, nanResult);
563            il.Emit(System.Reflection.Emit.OpCodes.Dup);
564            il.Emit(System.Reflection.Emit.OpCodes.Ldc_I4, ds.Rows);
565            il.Emit(System.Reflection.Emit.OpCodes.Bge, nanResult);
[6770]566            il.Emit(System.Reflection.Emit.OpCodes.Call, listGetValue);
567            il.Emit(System.Reflection.Emit.OpCodes.Ldc_R8, varNode.Weight); // load weight
568            il.Emit(System.Reflection.Emit.OpCodes.Mul);
[6809]569            il.Emit(System.Reflection.Emit.OpCodes.Br, normalResult);
570            il.MarkLabel(nanResult);
571            il.Emit(System.Reflection.Emit.OpCodes.Pop); // sample index
572            il.Emit(System.Reflection.Emit.OpCodes.Pop); // column reference
573            il.Emit(System.Reflection.Emit.OpCodes.Ldc_R8, double.NaN);
574            il.MarkLabel(normalResult);
[6770]575            return;
[6732]576          }
577        case OpCodes.Constant: {
578            ConstantTreeNode constNode = (ConstantTreeNode)currentInstr.dynamicNode;
579            il.Emit(System.Reflection.Emit.OpCodes.Ldc_R8, constNode.Value);
580            return;
581          }
582
583        //mkommend: this symbol uses the logistic function f(x) = 1 / (1 + e^(-alpha * x) )
584        //to determine the relative amounts of the true and false branch see http://en.wikipedia.org/wiki/Logistic_function
585        case OpCodes.VariableCondition: {
586            throw new NotImplementedException();
587          }
588        default: throw new NotSupportedException();
589      }
590    }
591
592    private byte MapSymbolToOpCode(ISymbolicExpressionTreeNode treeNode) {
593      if (symbolToOpcode.ContainsKey(treeNode.Symbol.GetType()))
594        return symbolToOpcode[treeNode.Symbol.GetType()];
595      else
596        throw new NotSupportedException("Symbol: " + treeNode.Symbol);
597    }
598  }
599}
Note: See TracBrowser for help on using the repository browser.