Changeset 13139


Ignore:
Timestamp:
11/12/15 11:10:22 (3 years ago)
Author:
bburlacu
Message:

#2442: Commit code version using an IDataset as a parameter for the returned lambda

File:
1 edited

Legend:

Unmodified
Added
Removed
  • branches/HeuristicLab.LinqExpressionTreeInterpreter/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/Interpreter/SymbolicDataAnalysisExpressionCompiledTreeInterpreter.cs

    r13039 r13139  
    2222using System;
    2323using System.Collections.Generic;
    24 using System.Collections.ObjectModel;
    2524using System.Linq;
    2625using System.Linq.Expressions;
     
    6261    #endregion
    6362
    64     private static readonly Func<ReadOnlyCollection<double>, IList<double>> ReadOnlyCollectionRetrieveList = GetField<ReadOnlyCollection<double>, IList<double>>("list"); // retrieve underlying field of type List from a ReadOnlyCollection
    65     private static readonly Func<List<double>, double[]> ListRetrieveItems = GetField<List<double>, double[]>("_items"); // retrieve underlying field of type double[] from a List<double>
     63    private static readonly MethodInfo ListGetValue = typeof(IList<double>).GetProperty("Item", new Type[] { typeof(int) }).GetGetMethod();
     64    private static readonly MethodInfo DatasetGetReadOnlyDoubleValues = typeof(IDataset).GetMethod("GetReadOnlyDoubleValues", new[] { typeof(string) });
    6665
    6766    public override bool CanChangeName { get { return false; } }
     
    123122        EvaluatedSolutions.Value++; // increment the evaluated solutions counter
    124123      }
    125 
    126       var columns = dataset.DoubleVariables.Select(x => ListRetrieveItems((List<double>)ReadOnlyCollectionRetrieveList(dataset.GetReadOnlyDoubleValues(x)))).ToArray();
    127124      var compiled = CompileTree(tree, dataset);
    128       return rows.Select(x => compiled(x, columns));
    129     }
    130 
    131     public static Func<int, double[][], double> CompileTree(ISymbolicExpressionTree tree, IDataset dataset) {
     125      return rows.Select(x => compiled(x, dataset));
     126    }
     127
     128    public static Func<int, IDataset, double> CompileTree(ISymbolicExpressionTree tree, IDataset dataset) {
    132129      var row = Expression.Parameter(typeof(int));
    133       var columns = Expression.Parameter(typeof(double[][]));
    134       var variableIndices = dataset.DoubleVariables.Select((x, i) => new { x, i }).ToDictionary(e => e.x, e => e.i);
    135       var expr = MakeExpr(tree, variableIndices, row, columns);
    136       var lambda = Expression.Lambda<Func<int, double[][], double>>(expr, row, columns);
     130      var ds = Expression.Parameter(typeof(IDataset));
     131      var expr = MakeExpr(tree, row, ds);
     132      var lambda = Expression.Lambda<Func<int, IDataset, double>>(expr, row, ds);
    137133      return lambda.Compile();
    138134    }
    139135
    140     private static Expression MakeExpr(ISymbolicExpressionTree tree, Dictionary<string, int> variableIndices, ParameterExpression row, ParameterExpression columns) {
     136    private static Expression MakeExpr(ISymbolicExpressionTree tree, ParameterExpression row, ParameterExpression ds) {
    141137      var actualRoot = tree.Root.GetSubtree(0).GetSubtree(0);
    142       return MakeExpr(actualRoot, variableIndices, row, columns);
    143     }
    144 
    145     private static Expression MakeExpr(ISymbolicExpressionTreeNode node, Dictionary<string, int> variableIndices, ParameterExpression row, ParameterExpression columns) {
     138      return MakeExpr(actualRoot, row, ds);
     139    }
     140
     141    private static Expression MakeExpr(ISymbolicExpressionTreeNode node, ParameterExpression row, ParameterExpression ds) {
    146142      var opcode = OpCodes.MapSymbolToOpCode(node);
    147143      switch (opcode) {
     
    149145          {
    150146            var functionSymbol = (FunctionSymbol)node.Symbol;
    151             return Expression.Call(functionSymbol.MethodInfo, node.Subtrees.Select(x => MakeExpr(x, variableIndices, row, columns)));
     147            return Expression.Call(functionSymbol.MethodInfo, node.Subtrees.Select(x => MakeExpr(x, row, ds)));
    152148          }
    153149        case OpCodes.Constant:
     
    160156            var variableTreeNode = (VariableTreeNode)node;
    161157            var variableWeight = Expression.Constant(variableTreeNode.Weight);
    162             var variableName = variableTreeNode.VariableName;
    163             var indexExpr = Expression.Constant(variableIndices[variableName]);
    164             var valuesExpr = Expression.ArrayIndex(columns, indexExpr);
    165             var variableValue = Expression.ArrayIndex(valuesExpr, row);
     158            var variableName = Expression.Constant(variableTreeNode.VariableName);
     159            var valuesExpr = Expression.Call(ds, DatasetGetReadOnlyDoubleValues, variableName);
     160            var variableValue = Expression.Call(valuesExpr, ListGetValue, row);
    166161            return Expression.Multiply(variableWeight, variableValue);
    167162          }
    168163        case OpCodes.Add:
    169164          {
    170             Expression result = MakeExpr(node.GetSubtree(0), variableIndices, row, columns);
     165            Expression result = MakeExpr(node.GetSubtree(0), row, ds);
    171166            for (int i = 1; i < node.SubtreeCount; ++i) {
    172               result = Expression.Add(result, MakeExpr(node.GetSubtree(i), variableIndices, row, columns));
     167              result = Expression.Add(result, MakeExpr(node.GetSubtree(i), row, ds));
    173168            }
    174169            return result;
     
    176171        case OpCodes.Sub:
    177172          {
    178             Expression result = MakeExpr(node.GetSubtree(0), variableIndices, row, columns);
     173            Expression result = MakeExpr(node.GetSubtree(0), row, ds);
    179174            if (node.SubtreeCount == 1)
    180175              return Expression.Negate(result);
    181176            for (int i = 1; i < node.SubtreeCount; ++i) {
    182               result = Expression.Subtract(result, MakeExpr(node.GetSubtree(i), variableIndices, row, columns));
     177              result = Expression.Subtract(result, MakeExpr(node.GetSubtree(i), row, ds));
    183178            }
    184179            return result;
     
    186181        case OpCodes.Mul:
    187182          {
    188             Expression result = MakeExpr(node.GetSubtree(0), variableIndices, row, columns);
     183            Expression result = MakeExpr(node.GetSubtree(0), row, ds);
    189184            for (int i = 1; i < node.SubtreeCount; ++i) {
    190               result = Expression.Multiply(result, MakeExpr(node.GetSubtree(i), variableIndices, row, columns));
     185              result = Expression.Multiply(result, MakeExpr(node.GetSubtree(i), row, ds));
    191186            }
    192187            return result;
     
    194189        case OpCodes.Div:
    195190          {
    196             Expression result = MakeExpr(node.GetSubtree(0), variableIndices, row, columns);
     191            Expression result = MakeExpr(node.GetSubtree(0), row, ds);
    197192            if (node.SubtreeCount == 1)
    198193              return Expression.Divide(Expression.Constant(1.0), result);
    199194            for (int i = 1; i < node.SubtreeCount; ++i) {
    200               result = Expression.Divide(result, MakeExpr(node.GetSubtree(i), variableIndices, row, columns));
     195              result = Expression.Divide(result, MakeExpr(node.GetSubtree(i), row, ds));
    201196            }
    202197            return result;
     
    204199        case OpCodes.Average:
    205200          {
    206             Expression result = MakeExpr(node.GetSubtree(0), variableIndices, row, columns);
     201            Expression result = MakeExpr(node.GetSubtree(0), row, ds);
    207202            for (int i = 1; i < node.SubtreeCount; ++i) {
    208               result = Expression.Add(result, MakeExpr(node.GetSubtree(i), variableIndices, row, columns));
     203              result = Expression.Add(result, MakeExpr(node.GetSubtree(i), row, ds));
    209204            }
    210205            return Expression.Divide(result, Expression.Constant((double)node.SubtreeCount));
     
    212207        case OpCodes.Cos:
    213208          {
    214             var arg = MakeExpr(node.GetSubtree(0), variableIndices, row, columns);
     209            var arg = MakeExpr(node.GetSubtree(0), row, ds);
    215210            return Expression.Call(Cos, arg);
    216211          }
    217212        case OpCodes.Sin:
    218213          {
    219             var arg = MakeExpr(node.GetSubtree(0), variableIndices, row, columns);
     214            var arg = MakeExpr(node.GetSubtree(0), row, ds);
    220215            return Expression.Call(Sin, arg);
    221216          }
    222217        case OpCodes.Tan:
    223218          {
    224             var arg = MakeExpr(node.GetSubtree(0), variableIndices, row, columns);
     219            var arg = MakeExpr(node.GetSubtree(0), row, ds);
    225220            return Expression.Call(Tan, arg);
    226221          }
    227222        case OpCodes.Square:
    228223          {
    229             var arg = MakeExpr(node.GetSubtree(0), variableIndices, row, columns);
     224            var arg = MakeExpr(node.GetSubtree(0), row, ds);
    230225            return Expression.Power(arg, Expression.Constant(2));
    231226          }
    232227        case OpCodes.Power:
    233228          {
    234             var arg = MakeExpr(node.GetSubtree(0), variableIndices, row, columns);
    235             var power = MakeExpr(node.GetSubtree(1), variableIndices, row, columns);
     229            var arg = MakeExpr(node.GetSubtree(0), row, ds);
     230            var power = MakeExpr(node.GetSubtree(1), row, ds);
    236231            return Expression.Power(arg, Expression.Call(Floor, power));
    237232          }
    238233        case OpCodes.SquareRoot:
    239234          {
    240             var arg = MakeExpr(node.GetSubtree(0), variableIndices, row, columns);
     235            var arg = MakeExpr(node.GetSubtree(0), row, ds);
    241236            return Expression.Call(Sqrt, arg);
    242237          }
    243238        case OpCodes.Root:
    244239          {
    245             var arg = MakeExpr(node.GetSubtree(0), variableIndices, row, columns);
    246             var power = MakeExpr(node.GetSubtree(1), variableIndices, row, columns);
     240            var arg = MakeExpr(node.GetSubtree(0), row, ds);
     241            var power = MakeExpr(node.GetSubtree(1), row, ds);
    247242            return Expression.Power(arg, Expression.Divide(Expression.Constant(1.0), power));
    248243          }
    249244        case OpCodes.Exp:
    250245          {
    251             var arg = MakeExpr(node.GetSubtree(0), variableIndices, row, columns);
     246            var arg = MakeExpr(node.GetSubtree(0), row, ds);
    252247            return Expression.Call(Exp, arg);
    253248          }
    254249        case OpCodes.Log:
    255250          {
    256             var arg = MakeExpr(node.GetSubtree(0), variableIndices, row, columns);
     251            var arg = MakeExpr(node.GetSubtree(0), row, ds);
    257252            return Expression.Call(Log, arg);
    258253          }
    259254        case OpCodes.Gamma:
    260255          {
    261             var arg = MakeExpr(node.GetSubtree(0), variableIndices, row, columns);
     256            var arg = MakeExpr(node.GetSubtree(0), row, ds);
    262257            var isNaN = Expression.Call(IsNaN, arg);
    263258            var gamma = Expression.Call(Gamma, arg);
     
    277272        case OpCodes.Psi:
    278273          {
    279             var arg = MakeExpr(node.GetSubtree(0), variableIndices, row, columns);
     274            var arg = MakeExpr(node.GetSubtree(0), row, ds);
    280275            var isNaN = Expression.Call(IsNaN, arg);
    281276            var psi = Expression.Call(Psi, arg);
     
    300295        case OpCodes.Dawson:
    301296          {
    302             var arg = MakeExpr(node.GetSubtree(0), variableIndices, row, columns);
     297            var arg = MakeExpr(node.GetSubtree(0), row, ds);
    303298            var isNaN = Expression.Call(IsNaN, arg);
    304299            var exprDawsonIntegral = Expression.Call(DawsonIntegral, arg);
     
    317312        case OpCodes.ExponentialIntegralEi:
    318313          {
    319             var arg = MakeExpr(node.GetSubtree(0), variableIndices, row, columns);
     314            var arg = MakeExpr(node.GetSubtree(0), row, ds);
    320315            var isNaN = Expression.Call(IsNaN, arg);
    321316            var expIntegrapEi =
     
    334329        case OpCodes.SineIntegral:
    335330          {
    336             var arg = MakeExpr(node.GetSubtree(0), variableIndices, row, columns);
     331            var arg = MakeExpr(node.GetSubtree(0), row, ds);
    337332            var isNaN = Expression.Call(IsNaN, arg);
    338333            var si = Expression.Variable(typeof(double));
     
    356351        case OpCodes.CosineIntegral:
    357352          {
    358             var arg = MakeExpr(node.GetSubtree(0), variableIndices, row, columns);
     353            var arg = MakeExpr(node.GetSubtree(0), row, ds);
    359354            var isNaN = Expression.Call(IsNaN, arg);
    360355            var si = Expression.Variable(typeof(double));
     
    378373        case OpCodes.HyperbolicSineIntegral:
    379374          {
    380             var arg = MakeExpr(node.GetSubtree(0), variableIndices, row, columns);
     375            var arg = MakeExpr(node.GetSubtree(0), row, ds);
    381376            var isNaN = Expression.Call(IsNaN, arg);
    382377            var shi = Expression.Variable(typeof(double));
     
    400395        case OpCodes.HyperbolicCosineIntegral:
    401396          {
    402             var arg = MakeExpr(node.GetSubtree(0), variableIndices, row, columns);
     397            var arg = MakeExpr(node.GetSubtree(0), row, ds);
    403398            var isNaN = Expression.Call(IsNaN, arg);
    404399            var shi = Expression.Variable(typeof(double));
     
    422417        case OpCodes.FresnelSineIntegral:
    423418          {
    424             var arg = MakeExpr(node.GetSubtree(0), variableIndices, row, columns);
     419            var arg = MakeExpr(node.GetSubtree(0), row, ds);
    425420            var isNaN = Expression.Call(IsNaN, arg);
    426421            var s = Expression.Variable(typeof(double));
     
    440435        case OpCodes.FresnelCosineIntegral:
    441436          {
    442             var arg = MakeExpr(node.GetSubtree(0), variableIndices, row, columns);
     437            var arg = MakeExpr(node.GetSubtree(0), row, ds);
    443438            var isNaN = Expression.Call(IsNaN, arg);
    444439            var s = Expression.Variable(typeof(double));
     
    458453        case OpCodes.AiryA:
    459454          {
    460             var arg = MakeExpr(node.GetSubtree(0), variableIndices, row, columns);
     455            var arg = MakeExpr(node.GetSubtree(0), row, ds);
    461456            var isNaN = Expression.Call(IsNaN, arg);
    462457            var ai = Expression.Variable(typeof(double));
     
    478473        case OpCodes.AiryB:
    479474          {
    480             var arg = MakeExpr(node.GetSubtree(0), variableIndices, row, columns);
     475            var arg = MakeExpr(node.GetSubtree(0), row, ds);
    481476            var isNaN = Expression.Call(IsNaN, arg);
    482477            var ai = Expression.Variable(typeof(double));
     
    498493        case OpCodes.Norm:
    499494          {
    500             var arg = MakeExpr(node.GetSubtree(0), variableIndices, row, columns);
     495            var arg = MakeExpr(node.GetSubtree(0), row, ds);
    501496            var isNaN = Expression.Call(IsNaN, arg);
    502497            var result = Expression.Variable(typeof(double));
     
    511506        case OpCodes.Erf:
    512507          {
    513             var arg = MakeExpr(node.GetSubtree(0), variableIndices, row, columns);
     508            var arg = MakeExpr(node.GetSubtree(0), row, ds);
    514509            var isNaN = Expression.Call(IsNaN, arg);
    515510            var result = Expression.Variable(typeof(double));
     
    524519        case OpCodes.Bessel:
    525520          {
    526             var arg = MakeExpr(node.GetSubtree(0), variableIndices, row, columns);
     521            var arg = MakeExpr(node.GetSubtree(0), row, ds);
    527522            var isNaN = Expression.Call(IsNaN, arg);
    528523            var result = Expression.Variable(typeof(double));
     
    540535        case OpCodes.IfThenElse:
    541536          {
    542             var test = MakeExpr(node.GetSubtree(0), variableIndices, row, columns);
     537            var test = MakeExpr(node.GetSubtree(0), row, ds);
    543538            var result = Expression.Variable(typeof(double));
    544539            var condition = Expression.IfThenElse(Expression.GreaterThan(test, Expression.Constant(0.0)),
    545               Expression.Assign(result, MakeExpr(node.GetSubtree(1), variableIndices, row, columns)),
    546               Expression.Assign(result, MakeExpr(node.GetSubtree(2), variableIndices, row, columns)));
     540              Expression.Assign(result, MakeExpr(node.GetSubtree(1), row, ds)),
     541              Expression.Assign(result, MakeExpr(node.GetSubtree(2), row, ds)));
    547542            return Expression.Block(new[] { result }, condition, result);
    548543          }
     
    550545          {
    551546            var result = Expression.Variable(typeof(double));
    552             var expr = MakeExpr(node.GetSubtree(0), variableIndices, row, columns);
     547            var expr = MakeExpr(node.GetSubtree(0), row, ds);
    553548
    554549            for (int i = 1; i < node.SubtreeCount; ++i) {
     
    556551                Expression.IfThenElse(
    557552                  Expression.GreaterThan(expr, Expression.Constant(0.0)),
    558                   Expression.Assign(result, MakeExpr(node.GetSubtree(i), variableIndices, row, columns)),
     553                  Expression.Assign(result, MakeExpr(node.GetSubtree(i), row, ds)),
    559554                  Expression.Assign(result, expr)),
    560555                result
     
    576571          {
    577572            var result = Expression.Variable(typeof(double));
    578             var expr = MakeExpr(node.GetSubtree(0), variableIndices, row, columns);
     573            var expr = MakeExpr(node.GetSubtree(0), row, ds);
    579574
    580575            for (int i = 1; i < node.SubtreeCount; ++i) {
     
    582577                Expression.IfThenElse(
    583578                  Expression.LessThanOrEqual(expr, Expression.Constant(0.0)),
    584                   Expression.Assign(result, MakeExpr(node.GetSubtree(i), variableIndices, row, columns)),
     579                  Expression.Assign(result, MakeExpr(node.GetSubtree(i), row, ds)),
    585580                  Expression.Assign(result, expr)),
    586581                result
     
    601596        case OpCodes.NOT:
    602597          {
    603             var value = MakeExpr(node.GetSubtree(0), variableIndices, row, columns);
     598            var value = MakeExpr(node.GetSubtree(0), row, ds);
    604599            var result = Expression.Variable(typeof(double));
    605600            var condition = Expression.IfThenElse(Expression.GreaterThan(value, Expression.Constant(0.0)),
     
    618613
    619614            foreach (var subtree in node.Subtrees) {
    620               var expr = MakeExpr(subtree, variableIndices, row, columns);
     615              var expr = MakeExpr(subtree, row, ds);
    621616              block = Expression.Block(
    622617                new[] { ps },
     
    642637        case OpCodes.GT:
    643638          {
    644             var left = MakeExpr(node.GetSubtree(0), variableIndices, row, columns);
    645             var right = MakeExpr(node.GetSubtree(1), variableIndices, row, columns);
     639            var left = MakeExpr(node.GetSubtree(0), row, ds);
     640            var right = MakeExpr(node.GetSubtree(1), row, ds);
    646641            var result = Expression.Variable(typeof(double));
    647642
     
    655650        case OpCodes.LT:
    656651          {
    657             var left = MakeExpr(node.GetSubtree(0), variableIndices, row, columns);
    658             var right = MakeExpr(node.GetSubtree(1), variableIndices, row, columns);
     652            var left = MakeExpr(node.GetSubtree(0), row, ds);
     653            var right = MakeExpr(node.GetSubtree(1), row, ds);
    659654            var result = Expression.Variable(typeof(double));
    660655
     
    666661          {
    667662            var variableConditionTreeNode = (VariableConditionTreeNode)node;
    668             var variableName = variableConditionTreeNode.VariableName;
    669             var indexExpr = Expression.Constant(variableIndices[variableName]);
    670             var valuesExpr = Expression.ArrayIndex(columns, indexExpr);
    671             var variableValue = Expression.ArrayIndex(valuesExpr, row);
     663            var variableName = Expression.Constant(variableConditionTreeNode.VariableName);
     664            var valuesExpr = Expression.Call(ds, DatasetGetReadOnlyDoubleValues, variableName);
     665            var variableValue = Expression.Call(valuesExpr, ListGetValue, row);
    672666            var variableThreshold = Expression.Constant(variableConditionTreeNode.Threshold);
    673667            var variableSlope = Expression.Constant(variableConditionTreeNode.Slope);
     
    677671            var xSlopeExp = Expression.Call(Exp, xSlope);
    678672            var p = Expression.Divide(Expression.Constant(1), Expression.Add(Expression.Constant(1), xSlopeExp));
    679             var trueBranch = MakeExpr(node.GetSubtree(0), variableIndices, row, columns);
    680             var falseBranch = MakeExpr(node.GetSubtree(1), variableIndices, row, columns);
     673            var trueBranch = MakeExpr(node.GetSubtree(0), row, ds);
     674            var falseBranch = MakeExpr(node.GetSubtree(1), row, ds);
    681675            return Expression.Add(
    682676              Expression.Multiply(trueBranch, p),
Note: See TracChangeset for help on using the changeset viewer.