Free cookie consent management tool by TermsFeed Policy Generator

source: branches/RegressionBenchmarks/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/SymbolicDataAnalysisExpressionTreeILEmittingInterpreter.cs @ 7485

Last change on this file since 7485 was 7485, checked in by sforsten, 12 years ago

#1708:

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