Changeset 13140


Ignore:
Timestamp:
11/12/15 11:16:03 (4 years ago)
Author:
bburlacu
Message:

#2442: Commit code version using a List instead of double array (makes code slightly simpler since the underlying double array need not be retrieved from the list)

File:
1 edited

Legend:

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

    r13139 r13140  
    6262
    6363    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) });
    6564
    6665    public override bool CanChangeName { get { return false; } }
     
    122121        EvaluatedSolutions.Value++; // increment the evaluated solutions counter
    123122      }
     123
     124      var columns = dataset.DoubleVariables.Select(x => (IList<double>)dataset.GetReadOnlyDoubleValues(x)).ToArray();
    124125      var compiled = CompileTree(tree, dataset);
    125       return rows.Select(x => compiled(x, dataset));
    126     }
    127 
    128     public static Func<int, IDataset, double> CompileTree(ISymbolicExpressionTree tree, IDataset dataset) {
     126      return rows.Select(x => compiled(x, columns));
     127    }
     128
     129    public static Func<int, IList<double>[], double> CompileTree(ISymbolicExpressionTree tree, IDataset dataset) {
    129130      var row = Expression.Parameter(typeof(int));
    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);
     131      var columns = Expression.Parameter(typeof(IList<double>[]));
     132      var variableIndices = dataset.DoubleVariables.Select((x, i) => new { x, i }).ToDictionary(e => e.x, e => e.i);
     133      var expr = MakeExpr(tree, variableIndices, row, columns);
     134      var lambda = Expression.Lambda<Func<int, IList<double>[], double>>(expr, row, columns);
    133135      return lambda.Compile();
    134136    }
    135137
    136     private static Expression MakeExpr(ISymbolicExpressionTree tree, ParameterExpression row, ParameterExpression ds) {
     138    private static Expression MakeExpr(ISymbolicExpressionTree tree, Dictionary<string, int> variableIndices, ParameterExpression row, ParameterExpression columns) {
    137139      var actualRoot = tree.Root.GetSubtree(0).GetSubtree(0);
    138       return MakeExpr(actualRoot, row, ds);
    139     }
    140 
    141     private static Expression MakeExpr(ISymbolicExpressionTreeNode node, ParameterExpression row, ParameterExpression ds) {
     140      return MakeExpr(actualRoot, variableIndices, row, columns);
     141    }
     142
     143    private static Expression MakeExpr(ISymbolicExpressionTreeNode node, Dictionary<string, int> variableIndices, ParameterExpression row, ParameterExpression columns) {
    142144      var opcode = OpCodes.MapSymbolToOpCode(node);
    143145      switch (opcode) {
     
    145147          {
    146148            var functionSymbol = (FunctionSymbol)node.Symbol;
    147             return Expression.Call(functionSymbol.MethodInfo, node.Subtrees.Select(x => MakeExpr(x, row, ds)));
     149            return Expression.Call(functionSymbol.MethodInfo, node.Subtrees.Select(x => MakeExpr(x, variableIndices, row, columns)));
    148150          }
    149151        case OpCodes.Constant:
     
    156158            var variableTreeNode = (VariableTreeNode)node;
    157159            var variableWeight = Expression.Constant(variableTreeNode.Weight);
    158             var variableName = Expression.Constant(variableTreeNode.VariableName);
    159             var valuesExpr = Expression.Call(ds, DatasetGetReadOnlyDoubleValues, variableName);
     160            var variableName = variableTreeNode.VariableName;
     161            var indexExpr = Expression.Constant(variableIndices[variableName]);
     162            var valuesExpr = Expression.ArrayIndex(columns, indexExpr);
    160163            var variableValue = Expression.Call(valuesExpr, ListGetValue, row);
    161164            return Expression.Multiply(variableWeight, variableValue);
     
    163166        case OpCodes.Add:
    164167          {
    165             Expression result = MakeExpr(node.GetSubtree(0), row, ds);
     168            Expression result = MakeExpr(node.GetSubtree(0), variableIndices, row, columns);
    166169            for (int i = 1; i < node.SubtreeCount; ++i) {
    167               result = Expression.Add(result, MakeExpr(node.GetSubtree(i), row, ds));
     170              result = Expression.Add(result, MakeExpr(node.GetSubtree(i), variableIndices, row, columns));
    168171            }
    169172            return result;
     
    171174        case OpCodes.Sub:
    172175          {
    173             Expression result = MakeExpr(node.GetSubtree(0), row, ds);
     176            Expression result = MakeExpr(node.GetSubtree(0), variableIndices, row, columns);
    174177            if (node.SubtreeCount == 1)
    175178              return Expression.Negate(result);
    176179            for (int i = 1; i < node.SubtreeCount; ++i) {
    177               result = Expression.Subtract(result, MakeExpr(node.GetSubtree(i), row, ds));
     180              result = Expression.Subtract(result, MakeExpr(node.GetSubtree(i), variableIndices, row, columns));
    178181            }
    179182            return result;
     
    181184        case OpCodes.Mul:
    182185          {
    183             Expression result = MakeExpr(node.GetSubtree(0), row, ds);
     186            Expression result = MakeExpr(node.GetSubtree(0), variableIndices, row, columns);
    184187            for (int i = 1; i < node.SubtreeCount; ++i) {
    185               result = Expression.Multiply(result, MakeExpr(node.GetSubtree(i), row, ds));
     188              result = Expression.Multiply(result, MakeExpr(node.GetSubtree(i), variableIndices, row, columns));
    186189            }
    187190            return result;
     
    189192        case OpCodes.Div:
    190193          {
    191             Expression result = MakeExpr(node.GetSubtree(0), row, ds);
     194            Expression result = MakeExpr(node.GetSubtree(0), variableIndices, row, columns);
    192195            if (node.SubtreeCount == 1)
    193196              return Expression.Divide(Expression.Constant(1.0), result);
    194197            for (int i = 1; i < node.SubtreeCount; ++i) {
    195               result = Expression.Divide(result, MakeExpr(node.GetSubtree(i), row, ds));
     198              result = Expression.Divide(result, MakeExpr(node.GetSubtree(i), variableIndices, row, columns));
    196199            }
    197200            return result;
     
    199202        case OpCodes.Average:
    200203          {
    201             Expression result = MakeExpr(node.GetSubtree(0), row, ds);
     204            Expression result = MakeExpr(node.GetSubtree(0), variableIndices, row, columns);
    202205            for (int i = 1; i < node.SubtreeCount; ++i) {
    203               result = Expression.Add(result, MakeExpr(node.GetSubtree(i), row, ds));
     206              result = Expression.Add(result, MakeExpr(node.GetSubtree(i), variableIndices, row, columns));
    204207            }
    205208            return Expression.Divide(result, Expression.Constant((double)node.SubtreeCount));
     
    207210        case OpCodes.Cos:
    208211          {
    209             var arg = MakeExpr(node.GetSubtree(0), row, ds);
     212            var arg = MakeExpr(node.GetSubtree(0), variableIndices, row, columns);
    210213            return Expression.Call(Cos, arg);
    211214          }
    212215        case OpCodes.Sin:
    213216          {
    214             var arg = MakeExpr(node.GetSubtree(0), row, ds);
     217            var arg = MakeExpr(node.GetSubtree(0), variableIndices, row, columns);
    215218            return Expression.Call(Sin, arg);
    216219          }
    217220        case OpCodes.Tan:
    218221          {
    219             var arg = MakeExpr(node.GetSubtree(0), row, ds);
     222            var arg = MakeExpr(node.GetSubtree(0), variableIndices, row, columns);
    220223            return Expression.Call(Tan, arg);
    221224          }
    222225        case OpCodes.Square:
    223226          {
    224             var arg = MakeExpr(node.GetSubtree(0), row, ds);
     227            var arg = MakeExpr(node.GetSubtree(0), variableIndices, row, columns);
    225228            return Expression.Power(arg, Expression.Constant(2));
    226229          }
    227230        case OpCodes.Power:
    228231          {
    229             var arg = MakeExpr(node.GetSubtree(0), row, ds);
    230             var power = MakeExpr(node.GetSubtree(1), row, ds);
     232            var arg = MakeExpr(node.GetSubtree(0), variableIndices, row, columns);
     233            var power = MakeExpr(node.GetSubtree(1), variableIndices, row, columns);
    231234            return Expression.Power(arg, Expression.Call(Floor, power));
    232235          }
    233236        case OpCodes.SquareRoot:
    234237          {
    235             var arg = MakeExpr(node.GetSubtree(0), row, ds);
     238            var arg = MakeExpr(node.GetSubtree(0), variableIndices, row, columns);
    236239            return Expression.Call(Sqrt, arg);
    237240          }
    238241        case OpCodes.Root:
    239242          {
    240             var arg = MakeExpr(node.GetSubtree(0), row, ds);
    241             var power = MakeExpr(node.GetSubtree(1), row, ds);
     243            var arg = MakeExpr(node.GetSubtree(0), variableIndices, row, columns);
     244            var power = MakeExpr(node.GetSubtree(1), variableIndices, row, columns);
    242245            return Expression.Power(arg, Expression.Divide(Expression.Constant(1.0), power));
    243246          }
    244247        case OpCodes.Exp:
    245248          {
    246             var arg = MakeExpr(node.GetSubtree(0), row, ds);
     249            var arg = MakeExpr(node.GetSubtree(0), variableIndices, row, columns);
    247250            return Expression.Call(Exp, arg);
    248251          }
    249252        case OpCodes.Log:
    250253          {
    251             var arg = MakeExpr(node.GetSubtree(0), row, ds);
     254            var arg = MakeExpr(node.GetSubtree(0), variableIndices, row, columns);
    252255            return Expression.Call(Log, arg);
    253256          }
    254257        case OpCodes.Gamma:
    255258          {
    256             var arg = MakeExpr(node.GetSubtree(0), row, ds);
     259            var arg = MakeExpr(node.GetSubtree(0), variableIndices, row, columns);
    257260            var isNaN = Expression.Call(IsNaN, arg);
    258261            var gamma = Expression.Call(Gamma, arg);
     
    272275        case OpCodes.Psi:
    273276          {
    274             var arg = MakeExpr(node.GetSubtree(0), row, ds);
     277            var arg = MakeExpr(node.GetSubtree(0), variableIndices, row, columns);
    275278            var isNaN = Expression.Call(IsNaN, arg);
    276279            var psi = Expression.Call(Psi, arg);
     
    295298        case OpCodes.Dawson:
    296299          {
    297             var arg = MakeExpr(node.GetSubtree(0), row, ds);
     300            var arg = MakeExpr(node.GetSubtree(0), variableIndices, row, columns);
    298301            var isNaN = Expression.Call(IsNaN, arg);
    299302            var exprDawsonIntegral = Expression.Call(DawsonIntegral, arg);
     
    312315        case OpCodes.ExponentialIntegralEi:
    313316          {
    314             var arg = MakeExpr(node.GetSubtree(0), row, ds);
     317            var arg = MakeExpr(node.GetSubtree(0), variableIndices, row, columns);
    315318            var isNaN = Expression.Call(IsNaN, arg);
    316319            var expIntegrapEi =
     
    329332        case OpCodes.SineIntegral:
    330333          {
    331             var arg = MakeExpr(node.GetSubtree(0), row, ds);
     334            var arg = MakeExpr(node.GetSubtree(0), variableIndices, row, columns);
    332335            var isNaN = Expression.Call(IsNaN, arg);
    333336            var si = Expression.Variable(typeof(double));
     
    351354        case OpCodes.CosineIntegral:
    352355          {
    353             var arg = MakeExpr(node.GetSubtree(0), row, ds);
     356            var arg = MakeExpr(node.GetSubtree(0), variableIndices, row, columns);
    354357            var isNaN = Expression.Call(IsNaN, arg);
    355358            var si = Expression.Variable(typeof(double));
     
    373376        case OpCodes.HyperbolicSineIntegral:
    374377          {
    375             var arg = MakeExpr(node.GetSubtree(0), row, ds);
     378            var arg = MakeExpr(node.GetSubtree(0), variableIndices, row, columns);
    376379            var isNaN = Expression.Call(IsNaN, arg);
    377380            var shi = Expression.Variable(typeof(double));
     
    395398        case OpCodes.HyperbolicCosineIntegral:
    396399          {
    397             var arg = MakeExpr(node.GetSubtree(0), row, ds);
     400            var arg = MakeExpr(node.GetSubtree(0), variableIndices, row, columns);
    398401            var isNaN = Expression.Call(IsNaN, arg);
    399402            var shi = Expression.Variable(typeof(double));
     
    417420        case OpCodes.FresnelSineIntegral:
    418421          {
    419             var arg = MakeExpr(node.GetSubtree(0), row, ds);
     422            var arg = MakeExpr(node.GetSubtree(0), variableIndices, row, columns);
    420423            var isNaN = Expression.Call(IsNaN, arg);
    421424            var s = Expression.Variable(typeof(double));
     
    435438        case OpCodes.FresnelCosineIntegral:
    436439          {
    437             var arg = MakeExpr(node.GetSubtree(0), row, ds);
     440            var arg = MakeExpr(node.GetSubtree(0), variableIndices, row, columns);
    438441            var isNaN = Expression.Call(IsNaN, arg);
    439442            var s = Expression.Variable(typeof(double));
     
    453456        case OpCodes.AiryA:
    454457          {
    455             var arg = MakeExpr(node.GetSubtree(0), row, ds);
     458            var arg = MakeExpr(node.GetSubtree(0), variableIndices, row, columns);
    456459            var isNaN = Expression.Call(IsNaN, arg);
    457460            var ai = Expression.Variable(typeof(double));
     
    473476        case OpCodes.AiryB:
    474477          {
    475             var arg = MakeExpr(node.GetSubtree(0), row, ds);
     478            var arg = MakeExpr(node.GetSubtree(0), variableIndices, row, columns);
    476479            var isNaN = Expression.Call(IsNaN, arg);
    477480            var ai = Expression.Variable(typeof(double));
     
    493496        case OpCodes.Norm:
    494497          {
    495             var arg = MakeExpr(node.GetSubtree(0), row, ds);
     498            var arg = MakeExpr(node.GetSubtree(0), variableIndices, row, columns);
    496499            var isNaN = Expression.Call(IsNaN, arg);
    497500            var result = Expression.Variable(typeof(double));
     
    506509        case OpCodes.Erf:
    507510          {
    508             var arg = MakeExpr(node.GetSubtree(0), row, ds);
     511            var arg = MakeExpr(node.GetSubtree(0), variableIndices, row, columns);
    509512            var isNaN = Expression.Call(IsNaN, arg);
    510513            var result = Expression.Variable(typeof(double));
     
    519522        case OpCodes.Bessel:
    520523          {
    521             var arg = MakeExpr(node.GetSubtree(0), row, ds);
     524            var arg = MakeExpr(node.GetSubtree(0), variableIndices, row, columns);
    522525            var isNaN = Expression.Call(IsNaN, arg);
    523526            var result = Expression.Variable(typeof(double));
     
    535538        case OpCodes.IfThenElse:
    536539          {
    537             var test = MakeExpr(node.GetSubtree(0), row, ds);
     540            var test = MakeExpr(node.GetSubtree(0), variableIndices, row, columns);
    538541            var result = Expression.Variable(typeof(double));
    539542            var condition = Expression.IfThenElse(Expression.GreaterThan(test, Expression.Constant(0.0)),
    540               Expression.Assign(result, MakeExpr(node.GetSubtree(1), row, ds)),
    541               Expression.Assign(result, MakeExpr(node.GetSubtree(2), row, ds)));
     543              Expression.Assign(result, MakeExpr(node.GetSubtree(1), variableIndices, row, columns)),
     544              Expression.Assign(result, MakeExpr(node.GetSubtree(2), variableIndices, row, columns)));
    542545            return Expression.Block(new[] { result }, condition, result);
    543546          }
     
    545548          {
    546549            var result = Expression.Variable(typeof(double));
    547             var expr = MakeExpr(node.GetSubtree(0), row, ds);
     550            var expr = MakeExpr(node.GetSubtree(0), variableIndices, row, columns);
    548551
    549552            for (int i = 1; i < node.SubtreeCount; ++i) {
     
    551554                Expression.IfThenElse(
    552555                  Expression.GreaterThan(expr, Expression.Constant(0.0)),
    553                   Expression.Assign(result, MakeExpr(node.GetSubtree(i), row, ds)),
     556                  Expression.Assign(result, MakeExpr(node.GetSubtree(i), variableIndices, row, columns)),
    554557                  Expression.Assign(result, expr)),
    555558                result
     
    571574          {
    572575            var result = Expression.Variable(typeof(double));
    573             var expr = MakeExpr(node.GetSubtree(0), row, ds);
     576            var expr = MakeExpr(node.GetSubtree(0), variableIndices, row, columns);
    574577
    575578            for (int i = 1; i < node.SubtreeCount; ++i) {
     
    577580                Expression.IfThenElse(
    578581                  Expression.LessThanOrEqual(expr, Expression.Constant(0.0)),
    579                   Expression.Assign(result, MakeExpr(node.GetSubtree(i), row, ds)),
     582                  Expression.Assign(result, MakeExpr(node.GetSubtree(i), variableIndices, row, columns)),
    580583                  Expression.Assign(result, expr)),
    581584                result
     
    596599        case OpCodes.NOT:
    597600          {
    598             var value = MakeExpr(node.GetSubtree(0), row, ds);
     601            var value = MakeExpr(node.GetSubtree(0), variableIndices, row, columns);
    599602            var result = Expression.Variable(typeof(double));
    600603            var condition = Expression.IfThenElse(Expression.GreaterThan(value, Expression.Constant(0.0)),
     
    613616
    614617            foreach (var subtree in node.Subtrees) {
    615               var expr = MakeExpr(subtree, row, ds);
     618              var expr = MakeExpr(subtree, variableIndices, row, columns);
    616619              block = Expression.Block(
    617620                new[] { ps },
     
    637640        case OpCodes.GT:
    638641          {
    639             var left = MakeExpr(node.GetSubtree(0), row, ds);
    640             var right = MakeExpr(node.GetSubtree(1), row, ds);
     642            var left = MakeExpr(node.GetSubtree(0), variableIndices, row, columns);
     643            var right = MakeExpr(node.GetSubtree(1), variableIndices, row, columns);
    641644            var result = Expression.Variable(typeof(double));
    642645
     
    650653        case OpCodes.LT:
    651654          {
    652             var left = MakeExpr(node.GetSubtree(0), row, ds);
    653             var right = MakeExpr(node.GetSubtree(1), row, ds);
     655            var left = MakeExpr(node.GetSubtree(0), variableIndices, row, columns);
     656            var right = MakeExpr(node.GetSubtree(1), variableIndices, row, columns);
    654657            var result = Expression.Variable(typeof(double));
    655658
     
    661664          {
    662665            var variableConditionTreeNode = (VariableConditionTreeNode)node;
    663             var variableName = Expression.Constant(variableConditionTreeNode.VariableName);
    664             var valuesExpr = Expression.Call(ds, DatasetGetReadOnlyDoubleValues, variableName);
     666            var variableName = variableConditionTreeNode.VariableName;
     667            var indexExpr = Expression.Constant(variableIndices[variableName]);
     668            var valuesExpr = Expression.ArrayIndex(columns, indexExpr);
    665669            var variableValue = Expression.Call(valuesExpr, ListGetValue, row);
    666670            var variableThreshold = Expression.Constant(variableConditionTreeNode.Threshold);
     
    671675            var xSlopeExp = Expression.Call(Exp, xSlope);
    672676            var p = Expression.Divide(Expression.Constant(1), Expression.Add(Expression.Constant(1), xSlopeExp));
    673             var trueBranch = MakeExpr(node.GetSubtree(0), row, ds);
    674             var falseBranch = MakeExpr(node.GetSubtree(1), row, ds);
     677            var trueBranch = MakeExpr(node.GetSubtree(0), variableIndices, row, columns);
     678            var falseBranch = MakeExpr(node.GetSubtree(1), variableIndices, row, columns);
    675679            return Expression.Add(
    676680              Expression.Multiply(trueBranch, p),
Note: See TracChangeset for help on using the changeset viewer.