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/SymbolicDataAnalysisExpressionTreeILEmittingInterpreter.cs

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