Free cookie consent management tool by TermsFeed Policy Generator

Ignore:
Timestamp:
03/07/13 14:49:11 (12 years ago)
Author:
bburlacu
Message:

#2021: Reverted r9290 as it is actually slower than the initial implementation.

File:
1 edited

Legend:

Unmodified
Added
Removed
  • branches/HeuristicLab.DataAnalysis.Symbolic.LinearInterpreter/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/Interpreter/SymbolicDataAnalysisExpressionTreeLinearInterpreter.cs

    r9290 r9292  
    124124      }
    125125
    126       double[] values = new double[code.Length];
    127 
    128126      foreach (var rowEnum in rows) {
    129127        int row = rowEnum;
    130         yield return Evaluate(dataset, ref row, code, values);
     128        yield return Evaluate(dataset, ref row, code);
    131129      }
    132130    }
    133131
    134     protected virtual double Evaluate(Dataset dataset, ref int row, Instruction[] code, double[] values) {
     132    protected virtual double Evaluate(Dataset dataset, ref int row, Instruction[] code) {
    135133      int count = 0;
    136134      for (int j = 0; j != code.Length; ++j) {
    137135        Instruction currentInstr = code[j];
    138 
    139         #region switch
     136  int narg = currentInstr.nArguments;
     137
    140138        switch (currentInstr.opCode) {
    141139          case OpCodes.Add: {
    142               double s = values[j - currentInstr.nArguments];
    143               for (int i = j - currentInstr.nArguments + 1; i < j; i++) {
    144                 s += values[i];
    145               }
    146               values[j] = s;
     140              double s = code[j - narg].value;
     141              for (int i = j - narg + 1; i < j; i++) {
     142                s += code[i].value;
     143              }
     144              currentInstr.value = s;
    147145            }
    148146            break;
    149147          case OpCodes.Sub: {
    150               double s = values[j - currentInstr.nArguments];
    151               for (int i = j - currentInstr.nArguments + 1; i < j; i++) {
    152                 s -= values[i];
    153               }
    154               if (currentInstr.nArguments == 1) s = -s;
    155               values[j] = s;
     148              double s = code[j - narg].value;
     149              for (int i = j - narg + 1; i < j; i++) {
     150                s -= code[i].value;
     151              }
     152              if (narg == 1) s = -s;
     153              currentInstr.value = s;
    156154            }
    157155            break;
    158156          case OpCodes.Mul: {
    159               double p = values[j - currentInstr.nArguments];
    160               for (int i = j - currentInstr.nArguments + 1; i < j; i++) {
    161                 p *= values[i];
    162               }
    163               values[j] = p;
     157              double p = code[j - narg].value;
     158              for (int i = j - narg + 1; i < j; i++) {
     159                p *= code[i].value;
     160              }
     161              currentInstr.value = p;
    164162            }
    165163            break;
    166164          case OpCodes.Div: {
    167               double p = values[j - currentInstr.nArguments];
    168               for (int i = j - currentInstr.nArguments + 1; i < j; i++) {
    169                 p /= values[i];
    170               }
    171               if (currentInstr.nArguments == 1) p = 1.0 / p;
    172               values[j] = p;
     165              double p = code[j - narg].value;
     166              for (int i = j - narg + 1; i < j; i++) {
     167                p /= code[i].value;
     168              }
     169              if (narg == 1) p = 1.0 / p;
     170              currentInstr.value = p;
    173171            }
    174172            break;
    175173          case OpCodes.Average: {
    176               double sum = values[j - currentInstr.nArguments];
    177               for (int i = j - currentInstr.nArguments + 1; i < j; i++) {
    178                 sum += values[i];
    179               }
    180               values[j] = sum / currentInstr.nArguments;
     174              double sum = code[j - narg].value;
     175              for (int i = j - narg + 1; i < j; i++) {
     176                sum += code[i].value;
     177              }
     178              currentInstr.value = sum / narg;
    181179            }
    182180            break;
    183181          case OpCodes.Cos: {
    184               values[j] = Math.Cos(values[j - currentInstr.nArguments]);
     182              currentInstr.value = Math.Cos(code[j - 1].value);
    185183            }
    186184            break;
    187185          case OpCodes.Sin: {
    188               values[j] = Math.Sin(values[j - currentInstr.nArguments]);
     186              currentInstr.value = Math.Sin(code[j - 1].value);
    189187              break;
    190188            }
    191189          case OpCodes.Tan: {
    192               values[j] = Math.Tan(values[j - currentInstr.nArguments]);
     190              currentInstr.value = Math.Tan(code[j - 1].value);
    193191            }
    194192            break;
    195193          case OpCodes.Square: {
    196               values[j] = Math.Pow(values[j - currentInstr.nArguments], 2);
     194              currentInstr.value = Math.Pow(code[j - 1].value, 2);
    197195            }
    198196            break;
    199197          case OpCodes.Power: {
    200               double x = values[j - currentInstr.nArguments];
    201               double y = Math.Round(values[j - currentInstr.nArguments + 1]);
    202               values[j] = Math.Pow(x, y);
     198              double x = code[j - 2].value;
     199              double y = Math.Round(code[j - 1].value);
     200              currentInstr.value = Math.Pow(x, y);
    203201            }
    204202            break;
    205203          case OpCodes.SquareRoot: {
    206               values[j] = Math.Sqrt(values[j - currentInstr.nArguments]);
     204              currentInstr.value = Math.Sqrt(code[j - 1].value);
    207205            }
    208206            break;
    209207          case OpCodes.Root: {
    210               double x = values[j - currentInstr.nArguments];
    211               double y = Math.Round(values[j - currentInstr.nArguments + 1]);
    212               values[j] = Math.Pow(x, 1 / y);
     208              double x = code[j - 2].value;
     209              double y = Math.Round(code[j - 1].value);
     210              currentInstr.value = Math.Pow(x, 1 / y);
    213211            }
    214212            break;
    215213          case OpCodes.Exp: {
    216               values[j] = Math.Exp(values[j - currentInstr.nArguments]);
     214              currentInstr.value = Math.Exp(code[j - 1].value);
    217215            }
    218216            break;
    219217          case OpCodes.Log: {
    220               values[j] = Math.Log(values[j - currentInstr.nArguments]);
     218              currentInstr.value = Math.Log(code[j - 1].value);
    221219            }
    222220            break;
    223221          case OpCodes.Gamma: {
    224               values[j] = double.IsNaN(values[j - currentInstr.nArguments]) ? double.NaN : alglib.gammafunction(values[j - currentInstr.nArguments]);
     222              currentInstr.value = double.IsNaN(code[j - 1].value) ? double.NaN : alglib.gammafunction(code[j - 1].value);
    225223            }
    226224            break;
    227225          case OpCodes.Psi: {
    228               var x = values[j - currentInstr.nArguments];
    229               if (double.IsNaN(x)) values[j] = double.NaN;
    230               else if (x <= 0 && (Math.Floor(x) - x).IsAlmost(0)) values[j] = double.NaN;
    231               else values[j] = alglib.psi(x);
     226              var x = code[j - 1].value;
     227              if (double.IsNaN(x)) currentInstr.value = double.NaN;
     228              else if (x <= 0 && (Math.Floor(x) - x).IsAlmost(0)) currentInstr.value = double.NaN;
     229              else currentInstr.value = alglib.psi(x);
    232230            }
    233231            break;
    234232          case OpCodes.Dawson: {
    235               var x = values[j - currentInstr.nArguments];
    236               values[j] = double.IsNaN(x) ? double.NaN : alglib.dawsonintegral(x);
     233              var x = code[j - 1].value;
     234              currentInstr.value = double.IsNaN(x) ? double.NaN : alglib.dawsonintegral(x);
    237235            }
    238236            break;
    239237          case OpCodes.ExponentialIntegralEi: {
    240               var x = values[j - currentInstr.nArguments];
    241               values[j] = double.IsNaN(x) ? double.NaN : alglib.exponentialintegralei(x);
     238              var x = code[j - 1].value;
     239              currentInstr.value = double.IsNaN(x) ? double.NaN : alglib.exponentialintegralei(x);
    242240            }
    243241            break;
    244242          case OpCodes.SineIntegral: {
    245243              double si, ci;
    246               var x = values[j - currentInstr.nArguments];
    247               if (double.IsNaN(x)) values[j] = double.NaN;
     244              var x = code[j - 1].value;
     245              if (double.IsNaN(x)) currentInstr.value = double.NaN;
    248246              else {
    249247                alglib.sinecosineintegrals(x, out si, out ci);
    250                 values[j] = si;
     248                currentInstr.value = si;
    251249              }
    252250            }
     
    254252          case OpCodes.CosineIntegral: {
    255253              double si, ci;
    256               var x = values[j - currentInstr.nArguments];
    257               if (double.IsNaN(x)) values[j] = double.NaN;
     254              var x = code[j - 1].value;
     255              if (double.IsNaN(x)) currentInstr.value = double.NaN;
    258256              else {
    259257                alglib.sinecosineintegrals(x, out si, out ci);
    260                 values[j] = ci;
     258                currentInstr.value = ci;
    261259              }
    262260            }
     
    264262          case OpCodes.HyperbolicSineIntegral: {
    265263              double shi, chi;
    266               var x = values[j - currentInstr.nArguments];
    267               if (double.IsNaN(x)) values[j] = double.NaN;
     264              var x = code[j - 1].value;
     265              if (double.IsNaN(x)) currentInstr.value = double.NaN;
    268266              else {
    269267                alglib.hyperbolicsinecosineintegrals(x, out shi, out chi);
    270                 values[j] = shi;
     268                currentInstr.value = shi;
    271269              }
    272270            }
     
    274272          case OpCodes.HyperbolicCosineIntegral: {
    275273              double shi, chi;
    276               var x = values[j - currentInstr.nArguments];
    277               if (double.IsNaN(x)) values[j] = double.NaN;
     274              var x = code[j - 1].value;
     275              if (double.IsNaN(x)) currentInstr.value = double.NaN;
    278276              else {
    279277                alglib.hyperbolicsinecosineintegrals(x, out shi, out chi);
    280                 values[j] = chi;
     278                currentInstr.value = chi;
    281279              }
    282280            }
     
    284282          case OpCodes.FresnelCosineIntegral: {
    285283              double c = 0, s = 0;
    286               var x = values[j - currentInstr.nArguments];
    287               if (double.IsNaN(x)) values[j] = double.NaN;
     284              var x = code[j - 1].value;
     285              if (double.IsNaN(x)) currentInstr.value = double.NaN;
    288286              else {
    289287                alglib.fresnelintegral(x, ref c, ref s);
    290                 values[j] = c;
     288                currentInstr.value = c;
    291289              }
    292290            }
     
    294292          case OpCodes.FresnelSineIntegral: {
    295293              double c = 0, s = 0;
    296               var x = values[j - currentInstr.nArguments];
    297               if (double.IsNaN(x)) values[j] = double.NaN;
     294              var x = code[j - 1].value;
     295              if (double.IsNaN(x)) currentInstr.value = double.NaN;
    298296              else {
    299297                alglib.fresnelintegral(x, ref c, ref s);
    300                 values[j] = s;
     298                currentInstr.value = s;
    301299              }
    302300            }
     
    304302          case OpCodes.AiryA: {
    305303              double ai, aip, bi, bip;
    306               var x = values[j - currentInstr.nArguments];
    307               if (double.IsNaN(x)) values[j] = double.NaN;
     304              var x = code[j - 1].value;
     305              if (double.IsNaN(x)) currentInstr.value = double.NaN;
    308306              else {
    309307                alglib.airy(x, out ai, out aip, out bi, out bip);
    310                 values[j] = ai;
     308                currentInstr.value = ai;
    311309              }
    312310            }
     
    314312          case OpCodes.AiryB: {
    315313              double ai, aip, bi, bip;
    316               var x = values[j - currentInstr.nArguments];
    317               if (double.IsNaN(x)) values[j] = double.NaN;
     314              var x = code[j - 1].value;
     315              if (double.IsNaN(x)) currentInstr.value = double.NaN;
    318316              else {
    319317                alglib.airy(x, out ai, out aip, out bi, out bip);
    320                 values[j] = bi;
     318                currentInstr.value = bi;
    321319              }
    322320            }
    323321            break;
    324322          case OpCodes.Norm: {
    325               var x = values[j - currentInstr.nArguments];
    326               values[j] = double.IsNaN(x) ? double.NaN : alglib.normaldistribution(x);
     323              var x = code[j - 1].value;
     324              currentInstr.value = double.IsNaN(x) ? double.NaN : alglib.normaldistribution(x);
    327325            }
    328326            break;
    329327          case OpCodes.Erf: {
    330               var x = values[j - currentInstr.nArguments];
    331               values[j] = double.IsNaN(x) ? double.NaN : alglib.errorfunction(x);
     328              var x = code[j - 1].value;
     329              currentInstr.value = double.IsNaN(x) ? double.NaN : alglib.errorfunction(x);
    332330            }
    333331            break;
    334332          case OpCodes.Bessel: {
    335               var x = values[j - currentInstr.nArguments];
    336               values[j] = double.IsNaN(x) ? double.NaN : alglib.besseli0(x);
     333              var x = code[j - 1].value;
     334              currentInstr.value = double.IsNaN(x) ? double.NaN : alglib.besseli0(x);
    337335            }
    338336            break;
    339337          case OpCodes.IfThenElse: {
    340               double condition = values[j - currentInstr.nArguments];
    341               double result = condition > 0.0 ? values[j - currentInstr.nArguments] : values[j - currentInstr.nArguments + 1];
    342               values[j] = result;
     338              double condition = code[j - narg].value;
     339              double result = condition > 0.0 ? code[j - 2].value : code[j - 1].value;
     340              currentInstr.value = result;
    343341            }
    344342            break;
    345343          case OpCodes.AND: {
    346               double result = values[j - currentInstr.nArguments];
    347               for (int i = j - currentInstr.nArguments + 1; i < j; i++) {
    348                 if (result > 0.0) result = values[i];
    349               }
    350               values[j] = result > 0.0 ? 1.0 : -1.0;
     344              double result = code[j - narg].value;
     345              for (int i = j - narg + 1; i < j; i++) {
     346                if (result > 0.0) result = code[i].value;
     347              }
     348              currentInstr.value = result > 0.0 ? 1.0 : -1.0;
    351349            }
    352350            break;
    353351          case OpCodes.OR: {
    354               double result = values[j - currentInstr.nArguments];
    355               for (int i = 1; i < currentInstr.nArguments; i++) {
    356                 if (result <= 0.0) result = values[i]; ;
    357               }
    358               values[j] = result > 0.0 ? 1.0 : -1.0;
     352              double result = code[j - narg].value;
     353              for (int i = j - narg + 1; i < j; i++) {
     354                if (result <= 0.0) result = code[i].value; ;
     355              }
     356              currentInstr.value = result > 0.0 ? 1.0 : -1.0;
    359357            }
    360358            break;
    361359          case OpCodes.NOT: {
    362               values[j] = values[j - currentInstr.nArguments] > 0.0 ? -1.0 : 1.0;
     360              currentInstr.value = code[j - 1].value > 0.0 ? -1.0 : 1.0;
    363361            }
    364362            break;
    365363          case OpCodes.GT: {
    366               double x = values[j - currentInstr.nArguments];
    367               double y = values[j - currentInstr.nArguments + 1];
    368               values[j] = x > y ? 1.0 : -1.0;
     364              double x = code[j - 2].value;
     365              double y = code[j - 1].value;
     366              currentInstr.value = x > y ? 1.0 : -1.0;
    369367            }
    370368            break;
    371369          case OpCodes.LT: {
    372               double x = values[j - currentInstr.nArguments];
    373               double y = values[j - currentInstr.nArguments + 1];
    374               values[j] = x < y ? 1.0 : -1.0;
     370              double x = code[j - 2].value;
     371              double y = code[j - 1].value;
     372              currentInstr.value = x < y ? 1.0 : -1.0;
    375373            }
    376374            break;
     
    396394            }
    397395          case OpCodes.Variable: {
    398               if (row < 0 || row >= dataset.Rows) values[j] = double.NaN;
     396              if (row < 0 || row >= dataset.Rows) currentInstr.value = double.NaN;
    399397              else {
    400398                var variableTreeNode = (VariableTreeNode)currentInstr.dynamicNode;
    401                 values[j] = ((IList<double>)currentInstr.iArg0)[row] * variableTreeNode.Weight;
     399                currentInstr.value = ((IList<double>)currentInstr.iArg0)[row] * variableTreeNode.Weight;
    402400              }
    403401            }
     
    406404              var laggedVariableTreeNode = (LaggedVariableTreeNode)currentInstr.dynamicNode;
    407405              int actualRow = row + laggedVariableTreeNode.Lag;
    408               if (actualRow < 0 || actualRow >= dataset.Rows) values[j] = double.NaN;
    409               else {
    410                 values[j] = ((IList<double>)currentInstr.iArg0)[actualRow] * laggedVariableTreeNode.Weight;
     406              if (actualRow < 0 || actualRow >= dataset.Rows) currentInstr.value = double.NaN;
     407              else {
     408                currentInstr.value = ((IList<double>)currentInstr.iArg0)[actualRow] * laggedVariableTreeNode.Weight;
    411409              }
    412410            }
     
    414412          case OpCodes.Constant: {
    415413              var constTreeNode = (ConstantTreeNode)currentInstr.dynamicNode;
    416               values[j] = constTreeNode.Value;
     414              currentInstr.value = constTreeNode.Value;
    417415            }
    418416            break;
     
    421419          //to determine the relative amounts of the true and false branch see http://en.wikipedia.org/wiki/Logistic_function
    422420          case OpCodes.VariableCondition: {
    423               if (row < 0 || row >= dataset.Rows) values[j] = double.NaN;
     421              if (row < 0 || row >= dataset.Rows) currentInstr.value = double.NaN;
    424422              else {
    425423                var variableConditionTreeNode = (VariableConditionTreeNode)currentInstr.dynamicNode;
     
    428426                double p = 1 / (1 + Math.Exp(-variableConditionTreeNode.Slope * x));
    429427
    430                 double trueBranch = values[j - currentInstr.nArguments];
    431                 double falseBranch = values[j - currentInstr.nArguments + 1];
    432 
    433                 values[j] = trueBranch * p + falseBranch * (1 - p);
     428                double trueBranch = code[j - narg].value;
     429                double falseBranch = code[j - narg + 1].value;
     430
     431                currentInstr.value = trueBranch * p + falseBranch * (1 - p);
    434432              }
    435433            }
     
    438436            throw new NotSupportedException();
    439437        }
    440         #endregion
    441 
    442         // book-keeping in order to keep all the values correct
    443         int narg = currentInstr.nArguments;
    444438
    445439        // we count the values before the next function is encountered
     
    448442        if (count > narg) {
    449443          for (int i = 1; i <= count - narg; ++i)
    450             values[j - i] = values[j - i - narg];
     444            code[j - i].value = code[j - i - narg].value;
    451445        }
    452446
     
    454448      }
    455449
    456       return values[values.Length - 1];
     450      return code[code.Length - 1].value;
    457451    }
    458452  }
Note: See TracChangeset for help on using the changeset viewer.