Free cookie consent management tool by TermsFeed Policy Generator

source: branches/HeuristicLab.Crossovers/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/SymbolicDataAnalysisExpressionTreeILEmittingInterpreter.cs @ 7477

Last change on this file since 7477 was 7477, checked in by bburlacu, 12 years ago

#1682: Added missing files (that were previously incorrectly referencing the old branch), added unit tests, recommitted lost changes.

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