Changeset 14811


Ignore:
Timestamp:
03/31/17 14:49:21 (2 years ago)
Author:
mkommend
Message:

#2442: Merged r12807, r13039, r13139, r13140, r13141, r13222, r13247, r13248, r13251, r13254, r13255, r13256, r1326, r13288, r13313, r13314, r13315, r13318, r14282, r14809, r14810 into stable.

Location:
stable
Files:
12 edited
1 copied

Legend:

Unmodified
Added
Removed
  • stable

  • stable/HeuristicLab.Problems.DataAnalysis.Symbolic

  • stable/HeuristicLab.Problems.DataAnalysis.Symbolic.TimeSeriesPrognosis

  • stable/HeuristicLab.Problems.DataAnalysis.Symbolic.TimeSeriesPrognosis/3.4/SymbolicTimeSeriesPrognosisExpressionTreeInterpreter.cs

    r14186 r14811  
    7373    }
    7474
     75    private readonly object syncRoot = new object();
    7576    public IEnumerable<IEnumerable<double>> GetSymbolicExpressionTreeValues(ISymbolicExpressionTree tree, IDataset dataset, IEnumerable<int> rows, IEnumerable<int> horizons) {
    76       if (CheckExpressionsWithIntervalArithmetic.Value)
     77      if (CheckExpressionsWithIntervalArithmetic)
    7778        throw new NotSupportedException("Interval arithmetic is not yet supported in the symbolic data analysis interpreter.");
    7879      if (targetVariableCache == null || targetVariableCache.GetLength(0) < dataset.Rows)
     
    8283
    8384      string targetVariable = TargetVariable;
    84       lock (EvaluatedSolutions) {
    85         EvaluatedSolutions.Value++; // increment the evaluated solutions counter
     85      lock (syncRoot) {
     86        EvaluatedSolutions++; // increment the evaluated solutions counter
    8687      }
    8788      var state = PrepareInterpreterState(tree, dataset, targetVariableCache, TargetVariable);
  • stable/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/HeuristicLab.Problems.DataAnalysis.Symbolic-3.4.csproj

    r14116 r14811  
    140140    <Compile Include="Importer\Token.cs" />
    141141    <Compile Include="Interfaces\IModelBacktransformator.cs" />
     142    <Compile Include="Interpreter\SymbolicDataAnalysisExpressionCompiledTreeInterpreter.cs" />
    142143    <Compile Include="SymbolicDataAnalysisExpressionTreeSimplificationOperator.cs" />
    143144    <Compile Include="SymbolicDataAnalysisModelComplexityCalculator.cs" />
  • stable/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/Interfaces/ISymbolicDataAnalysisExpressionTreeInterpreter.cs

    r14186 r14811  
    2222using System.Collections.Generic;
    2323using HeuristicLab.Core;
    24 using HeuristicLab.Data;
    2524using HeuristicLab.Encodings.SymbolicExpressionTreeEncoding;
    2625
     
    2827  public interface ISymbolicDataAnalysisExpressionTreeInterpreter : INamedItem, IStatefulItem {
    2928    IEnumerable<double> GetSymbolicExpressionTreeValues(ISymbolicExpressionTree tree, IDataset dataset, IEnumerable<int> rows);
    30     IntValue EvaluatedSolutions { get; set; }
     29    int EvaluatedSolutions { get; set; }
    3130  }
    3231}
  • stable/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/Interpreter/SymbolicDataAnalysisExpressionCompiledTreeInterpreter.cs

    r13248 r14811  
    4646    private static readonly MethodInfo Sqrt = typeof(Math).GetMethod("Sqrt", new[] { typeof(double) });
    4747    private static readonly MethodInfo Floor = typeof(Math).GetMethod("Floor", new[] { typeof(double) });
     48    private static readonly MethodInfo Round = typeof(Math).GetMethod("Round", new[] { typeof(double) });
    4849    private static readonly MethodInfo Exp = typeof(Math).GetMethod("Exp", new[] { typeof(double) });
    4950    private static readonly MethodInfo Log = typeof(Math).GetMethod("Log", new[] { typeof(double) });
    5051    private static readonly MethodInfo IsNaN = typeof(double).GetMethod("IsNaN");
     52    private static readonly MethodInfo IsAlmost = typeof(DoubleExtensions).GetMethod("IsAlmost");
    5153    private static readonly MethodInfo Gamma = typeof(alglib).GetMethod("gammafunction", new[] { typeof(double) });
    5254    private static readonly MethodInfo Psi = typeof(alglib).GetMethod("psi", new[] { typeof(double) });
     
    117119    public void ClearState() { }
    118120
     121    private readonly object syncRoot = new object();
    119122    public IEnumerable<double> GetSymbolicExpressionTreeValues(ISymbolicExpressionTree tree, IDataset dataset, IEnumerable<int> rows) {
    120123      if (CheckExpressionsWithIntervalArithmetic)
    121124        throw new NotSupportedException("Interval arithmetic is not yet supported in the symbolic data analysis interpreter.");
    122125
    123       lock (EvaluatedSolutionsParameter.Value) {
     126      lock (syncRoot) {
    124127        EvaluatedSolutions++; // increment the evaluated solutions counter
    125128      }
     
    130133
    131134    public static Func<int, IList<double>[], double> CompileTree(ISymbolicExpressionTree tree, IDataset dataset) {
     135      var lambda = CreateDelegate(tree, dataset);
     136      return lambda.Compile();
     137    }
     138
     139    public static Expression<Func<int, IList<double>[], double>> CreateDelegate(ISymbolicExpressionTree tree, IDataset dataset) {
    132140      var row = Expression.Parameter(typeof(int));
    133141      var columns = Expression.Parameter(typeof(IList<double>[]));
     
    135143      var expr = MakeExpr(tree, variableIndices, row, columns);
    136144      var lambda = Expression.Lambda<Func<int, IList<double>[], double>>(expr, row, columns);
    137       return lambda.Compile();
     145      return lambda;
    138146    }
    139147
     
    158166            var indexExpr = Expression.Constant(variableIndices[variableName]);
    159167            var valuesExpr = Expression.ArrayIndex(columns, indexExpr);
    160             var variableValue = Expression.Property(valuesExpr, Indexer, row);
    161             return Expression.Multiply(variableWeight, variableValue);
     168            return Expression.Multiply(variableWeight, Expression.Property(valuesExpr, Indexer, row));
    162169          }
    163170        case OpCodes.Add: {
     
    214221        case OpCodes.Square: {
    215222            var arg = MakeExpr(node.GetSubtree(0), variableIndices, row, columns);
    216             return Expression.Power(arg, Expression.Constant(2));
     223            return Expression.Power(arg, Expression.Constant(2.0));
    217224          }
    218225        case OpCodes.Power: {
    219226            var arg = MakeExpr(node.GetSubtree(0), variableIndices, row, columns);
    220227            var power = MakeExpr(node.GetSubtree(1), variableIndices, row, columns);
    221             return Expression.Power(arg, Expression.Call(Floor, power));
     228            return Expression.Power(arg, Expression.Call(Round, power));
    222229          }
    223230        case OpCodes.SquareRoot: {
     
    228235            var arg = MakeExpr(node.GetSubtree(0), variableIndices, row, columns);
    229236            var power = MakeExpr(node.GetSubtree(1), variableIndices, row, columns);
    230             return Expression.Power(arg, Expression.Divide(Expression.Constant(1.0), power));
     237            return Expression.Power(arg, Expression.Divide(Expression.Constant(1.0), Expression.Call(Round, power)));
    231238          }
    232239        case OpCodes.Exp: {
     
    241248            var arg = MakeExpr(node.GetSubtree(0), variableIndices, row, columns);
    242249            var isNaN = Expression.Call(IsNaN, arg);
    243             var gamma = Expression.Call(Gamma, arg);
    244250
    245251            var result = Expression.Variable(typeof(double));
     
    249255                isNaN,
    250256                Expression.Assign(result, Expression.Constant(double.NaN)),
    251                 Expression.Assign(result, gamma)
     257                Expression.Assign(result, Expression.Call(Gamma, arg))
    252258                ),
    253259              result
     
    258264            var arg = MakeExpr(node.GetSubtree(0), variableIndices, row, columns);
    259265            var isNaN = Expression.Call(IsNaN, arg);
    260             var psi = Expression.Call(Psi, arg);
    261266
    262267            var result = Expression.Variable(typeof(double));
     
    268273                Expression.Assign(result, Expression.Constant(double.NaN)),
    269274                Expression.IfThenElse(
    270                   Expression.AndAlso(Expression.LessThanOrEqual(arg, Expression.Constant(0.0)),
    271                     Expression.Equal(Expression.Subtract(floor, arg), Expression.Constant(0.0))),
     275                  Expression.AndAlso(
     276                    Expression.LessThanOrEqual(arg, Expression.Constant(0.0)),
     277                    Expression.Call(IsAlmost, Expression.Subtract(floor, arg), Expression.Constant(0.0))),
    272278                  Expression.Assign(result, Expression.Constant(double.NaN)),
    273                   Expression.Assign(result, psi))
     279                  Expression.Assign(result, Expression.Call(Psi, arg)))
    274280                ),
    275281              result);
     
    280286            var arg = MakeExpr(node.GetSubtree(0), variableIndices, row, columns);
    281287            var isNaN = Expression.Call(IsNaN, arg);
    282             var exprDawsonIntegral = Expression.Call(DawsonIntegral, arg);
    283             var result = Expression.Variable(typeof(double));
    284 
     288            var result = Expression.Variable(typeof(double));
    285289            var expr = Expression.Block(
    286290              new[] { result },
    287291              Expression.IfThenElse(isNaN,
    288292                Expression.Assign(result, Expression.Constant(double.NaN)),
    289                 Expression.Assign(result, exprDawsonIntegral)),
     293                Expression.Assign(result, Expression.Call(DawsonIntegral, arg))),
    290294              result
    291295              );
     
    296300            var arg = MakeExpr(node.GetSubtree(0), variableIndices, row, columns);
    297301            var isNaN = Expression.Call(IsNaN, arg);
    298             var expIntegrapEi =
    299               Expression.Call(ExponentialIntegralEi, arg);
    300302            var result = Expression.Variable(typeof(double));
    301303            var expr = Expression.Block(
     
    303305              Expression.IfThenElse(isNaN,
    304306                Expression.Assign(result, Expression.Constant(double.NaN)),
    305                 Expression.Assign(result, expIntegrapEi)),
     307                Expression.Assign(result, Expression.Call(ExponentialIntegralEi, arg))),
    306308              result
    307309              );
     
    314316            var si = Expression.Variable(typeof(double));
    315317            var ci = Expression.Variable(typeof(double));
    316             var sinCosIntegrals = Expression.Call(SineCosineIntegrals, arg, si, ci);
    317318            var block = Expression.Block(
    318319              new[] { si, ci },
    319               sinCosIntegrals,
     320              Expression.Call(SineCosineIntegrals, arg, si, ci),
    320321              si
    321322              );
     
    335336            var si = Expression.Variable(typeof(double));
    336337            var ci = Expression.Variable(typeof(double));
    337             var sinCosIntegrals = Expression.Call(SineCosineIntegrals, arg, si, ci);
    338338            var block = Expression.Block(
    339339              new[] { si, ci },
    340               sinCosIntegrals,
     340              Expression.Call(SineCosineIntegrals, arg, si, ci),
    341341              ci
    342342              );
     
    356356            var shi = Expression.Variable(typeof(double));
    357357            var chi = Expression.Variable(typeof(double));
    358             var hypSinCosIntegrals = Expression.Call(HyperbolicSineCosineIntegrals, arg, shi, chi);
    359358            var block = Expression.Block(
    360359              new[] { shi, chi },
    361               hypSinCosIntegrals,
     360              Expression.Call(HyperbolicSineCosineIntegrals, arg, shi, chi),
    362361              shi
    363362              );
     
    377376            var shi = Expression.Variable(typeof(double));
    378377            var chi = Expression.Variable(typeof(double));
    379             var hypSinCosIntegrals = Expression.Call(HyperbolicSineCosineIntegrals, arg, shi, chi);
    380378            var block = Expression.Block(
    381379              new[] { shi, chi },
    382               hypSinCosIntegrals,
     380              Expression.Call(HyperbolicSineCosineIntegrals, arg, shi, chi),
    383381              chi
    384382              );
     
    398396            var s = Expression.Variable(typeof(double));
    399397            var c = Expression.Variable(typeof(double));
    400             var fresnel = Expression.Call(FresnelIntegral, arg, c, s);
    401             var block = Expression.Block(new[] { s, c }, fresnel, s);
     398            var block = Expression.Block(new[] { s, c }, Expression.Call(FresnelIntegral, arg, c, s), s);
    402399            var result = Expression.Variable(typeof(double));
    403400            var expr = Expression.Block(new[] { result },
     
    415412            var s = Expression.Variable(typeof(double));
    416413            var c = Expression.Variable(typeof(double));
    417             var fresnel = Expression.Call(FresnelIntegral, arg, c, s);
    418             var block = Expression.Block(new[] { s, c }, fresnel, c);
     414            var block = Expression.Block(new[] { s, c }, Expression.Call(FresnelIntegral, arg, c, s), c);
    419415            var result = Expression.Variable(typeof(double));
    420416            var expr = Expression.Block(new[] { result },
     
    434430            var bi = Expression.Variable(typeof(double));
    435431            var bip = Expression.Variable(typeof(double));
    436             var airy = Expression.Call(Airy, arg, ai, aip, bi, bip);
    437             var block = Expression.Block(new[] { ai, aip, bi, bip }, airy, ai);
     432            var block = Expression.Block(new[] { ai, aip, bi, bip }, Expression.Call(Airy, arg, ai, aip, bi, bip), ai);
    438433            var result = Expression.Variable(typeof(double));
    439434            var expr = Expression.Block(new[] { result },
     
    453448            var bi = Expression.Variable(typeof(double));
    454449            var bip = Expression.Variable(typeof(double));
    455             var airy = Expression.Call(Airy, arg, ai, aip, bi, bip);
    456             var block = Expression.Block(new[] { ai, aip, bi, bip }, airy, bi);
     450            var block = Expression.Block(new[] { ai, aip, bi, bip }, Expression.Call(Airy, arg, ai, aip, bi, bip), bi);
    457451            var result = Expression.Variable(typeof(double));
    458452            var expr = Expression.Block(new[] { result },
     
    467461        case OpCodes.Norm: {
    468462            var arg = MakeExpr(node.GetSubtree(0), variableIndices, row, columns);
    469             var isNaN = Expression.Call(IsNaN, arg);
    470             var result = Expression.Variable(typeof(double));
    471             var norm = Expression.Call(NormalDistribution, arg);
    472 
    473             var expr = Expression.Block(new[] { result },
    474               Expression.IfThenElse(isNaN, Expression.Assign(result, Expression.Constant(double.NaN)),
    475                 Expression.Assign(result, norm)), result);
    476 
    477             return expr;
     463            var result = Expression.Variable(typeof(double));
     464            return Expression.Block(
     465              new[] { result },
     466              Expression.IfThenElse(
     467                Expression.Call(IsNaN, arg),
     468                Expression.Assign(result, arg),
     469                Expression.Assign(result, Expression.Call(NormalDistribution, arg))),
     470              result);
    478471          }
    479472        case OpCodes.Erf: {
     
    481474            var isNaN = Expression.Call(IsNaN, arg);
    482475            var result = Expression.Variable(typeof(double));
    483             var erf = Expression.Call(ErrorFunction, arg);
    484 
    485             var expr = Expression.Block(new[] { result },
    486               Expression.IfThenElse(isNaN, Expression.Assign(result, Expression.Constant(double.NaN)),
    487                 Expression.Assign(result, erf)), result);
    488 
    489             return expr;
     476            return Expression.Block(
     477              new[] { result },
     478              Expression.IfThenElse(
     479                isNaN,
     480                Expression.Assign(result, Expression.Constant(double.NaN)),
     481                Expression.Assign(result, Expression.Call(ErrorFunction, arg))),
     482              result);
    490483          }
    491484        case OpCodes.Bessel: {
     
    493486            var isNaN = Expression.Call(IsNaN, arg);
    494487            var result = Expression.Variable(typeof(double));
    495             var bessel = Expression.Call(Bessel, arg);
    496             var expr = Expression.Block(
     488            return Expression.Block(
    497489              new[] { result },
    498490              Expression.IfThenElse(
    499491                isNaN,
    500492                Expression.Assign(result, Expression.Constant(double.NaN)),
    501                 Expression.Assign(result, bessel)),
     493                Expression.Assign(result, Expression.Call(Bessel, arg))),
    502494              result);
    503 
    504             return expr;
    505495          }
    506496        case OpCodes.IfThenElse: {
     
    627617            var indexExpr = Expression.Constant(variableIndices[variableName]);
    628618            var valuesExpr = Expression.ArrayIndex(columns, indexExpr);
    629             var variableValue = Expression.ArrayIndex(valuesExpr, row);
     619            var variableValue = Expression.Property(valuesExpr, Indexer, row);
    630620            var variableThreshold = Expression.Constant(variableConditionTreeNode.Threshold);
    631621            var variableSlope = Expression.Constant(variableConditionTreeNode.Slope);
     
    642632              );
    643633          }
    644         case OpCodes.LagVariable: {
    645             var laggedVariableTreeNode = (LaggedVariableTreeNode)node;
    646             var lag = Expression.Constant(laggedVariableTreeNode.Lag);
    647             var variableWeight = Expression.Constant(laggedVariableTreeNode.Weight);
    648             var variableName = laggedVariableTreeNode.VariableName;
    649             var indexExpr = Expression.Constant(variableIndices[variableName]);
    650             var valuesExpr = Expression.ArrayIndex(columns, indexExpr);
    651             var variableValue = Expression.Property(valuesExpr, Indexer, Expression.Add(row, lag));
    652             return Expression.Multiply(variableWeight, variableValue);
    653           }
    654         case OpCodes.TimeLag: {
    655             var timeLagTreeNode = (LaggedTreeNode)node;
    656             var lag = Expression.Constant(timeLagTreeNode.Lag);
    657             return MakeExpr(timeLagTreeNode.GetSubtree(0), variableIndices, Expression.Add(row, lag), columns);
    658           }
    659         case OpCodes.Integral: {
    660             var timeLagTreeNode = (LaggedTreeNode)node;
    661             var subtree = node.GetSubtree(0);
    662             var sum = MakeExpr(subtree, variableIndices, row, columns);
    663             var sign = Expression.Constant(Math.Sign(timeLagTreeNode.Lag));
    664             var lag = Expression.Add(row, sign);
    665             for (int i = 0; i < Math.Abs(timeLagTreeNode.Lag); ++i) {
    666               sum = Expression.Add(sum, MakeExpr(subtree, variableIndices, lag, columns));
    667               lag = Expression.Add(lag, sign);
    668             }
    669             return sum;
    670           }
    671         case OpCodes.Derivative: {
    672             var subtree = node.GetSubtree(0);
    673             var f0 = MakeExpr(subtree, variableIndices, row, columns);
    674             var f1 = MakeExpr(subtree, variableIndices, Expression.Subtract(row, Expression.Constant(1)), columns);
    675             var f3 = MakeExpr(subtree, variableIndices, Expression.Subtract(row, Expression.Constant(3)), columns);
    676             var f4 = MakeExpr(subtree, variableIndices, Expression.Subtract(row, Expression.Constant(4)), columns);
    677 
    678             var result = f0;
    679             result = Expression.Add(result, Expression.Multiply(Expression.Constant(2.0), f1));
    680             result = Expression.Subtract(result, Expression.Multiply(Expression.Constant(2.0), f3));
    681             result = Expression.Subtract(result, f4);
    682             return Expression.Divide(result, Expression.Constant(8.0));
    683           }
    684634        default:
    685635          throw new NotSupportedException("Unsupported symbol: " + node.Symbol);
     
    687637      #endregion
    688638    }
    689     // util stuff
    690     private static Func<T, R> GetField<T, R>(string fieldName) {
    691       ParameterExpression param = Expression.Parameter(typeof(T), "arg");
    692       MemberExpression member = Expression.Field(param, fieldName);
    693       LambdaExpression lambda = Expression.Lambda(typeof(Func<T, R>), member, param);
    694       Func<T, R> compiled = (Func<T, R>)lambda.Compile();
    695       return compiled;
    696     }
    697639  }
    698640}
  • stable/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/Interpreter/SymbolicDataAnalysisExpressionTreeILEmittingInterpreter.cs

    r14186 r14811  
    6969
    7070    private const string CheckExpressionsWithIntervalArithmeticParameterName = "CheckExpressionsWithIntervalArithmetic";
     71    private const string CheckExpressionsWithIntervalArithmeticParameterDescription = "Switch that determines if the interpreter checks the validity of expressions with interval arithmetic before evaluating the expression.";
    7172    private const string EvaluatedSolutionsParameterName = "EvaluatedSolutions";
    7273
     
    8081
    8182    #region parameter properties
    82 
    83     public IValueParameter<BoolValue> CheckExpressionsWithIntervalArithmeticParameter {
    84       get { return (IValueParameter<BoolValue>)Parameters[CheckExpressionsWithIntervalArithmeticParameterName]; }
    85     }
    86 
    87     public IValueParameter<IntValue> EvaluatedSolutionsParameter {
    88       get { return (IValueParameter<IntValue>)Parameters[EvaluatedSolutionsParameterName]; }
    89     }
    90 
     83    public IFixedValueParameter<BoolValue> CheckExpressionsWithIntervalArithmeticParameter {
     84      get { return (IFixedValueParameter<BoolValue>)Parameters[CheckExpressionsWithIntervalArithmeticParameterName]; }
     85    }
     86
     87    public IFixedValueParameter<IntValue> EvaluatedSolutionsParameter {
     88      get { return (IFixedValueParameter<IntValue>)Parameters[EvaluatedSolutionsParameterName]; }
     89    }
    9190    #endregion
    9291
    9392    #region properties
    94 
    95     public BoolValue CheckExpressionsWithIntervalArithmetic {
    96       get { return CheckExpressionsWithIntervalArithmeticParameter.Value; }
    97       set { CheckExpressionsWithIntervalArithmeticParameter.Value = value; }
    98     }
    99 
    100     public IntValue EvaluatedSolutions {
    101       get { return EvaluatedSolutionsParameter.Value; }
    102       set { EvaluatedSolutionsParameter.Value = value; }
    103     }
    104 
     93    public bool CheckExpressionsWithIntervalArithmetic {
     94      get { return CheckExpressionsWithIntervalArithmeticParameter.Value.Value; }
     95      set { CheckExpressionsWithIntervalArithmeticParameter.Value.Value = value; }
     96    }
     97    public int EvaluatedSolutions {
     98      get { return EvaluatedSolutionsParameter.Value.Value; }
     99      set { EvaluatedSolutionsParameter.Value.Value = value; }
     100    }
    105101    #endregion
    106 
    107102
    108103    [StorableConstructor]
     
    116111    public SymbolicDataAnalysisExpressionTreeILEmittingInterpreter()
    117112      : base("SymbolicDataAnalysisExpressionTreeILEmittingInterpreter", "Interpreter for symbolic expression trees.") {
    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)));
     113      Parameters.Add(new FixedValueParameter<BoolValue>(CheckExpressionsWithIntervalArithmeticParameterName,
     114        "Switch that determines if the interpreter checks the validity of expressions with interval arithmetic before evaluating the expression.", new BoolValue(false)));
     115      Parameters.Add(new FixedValueParameter<IntValue>(EvaluatedSolutionsParameterName, "A counter for the total number of solutions the interpreter has evaluated", new IntValue(0)));
     116    }
     117
     118    public SymbolicDataAnalysisExpressionTreeILEmittingInterpreter(string name, string description)
     119      : base(name, description) {
     120      Parameters.Add(new FixedValueParameter<BoolValue>(CheckExpressionsWithIntervalArithmeticParameterName,
     121        "Switch that determines if the interpreter checks the validity of expressions with interval arithmetic before evaluating the expression.", new BoolValue(false)));
     122      Parameters.Add(new FixedValueParameter<IntValue>(EvaluatedSolutionsParameterName, "A counter for the total number of solutions the interpreter has evaluated", new IntValue(0)));
    120123    }
    121124
    122125    [StorableHook(HookType.AfterDeserialization)]
    123126    private void AfterDeserialization() {
    124       if (!Parameters.ContainsKey(EvaluatedSolutionsParameterName))
    125         Parameters.Add(new ValueParameter<IntValue>(EvaluatedSolutionsParameterName, "A counter for the total number of solutions the interpreter has evaluated", new IntValue(0)));
     127      var evaluatedSolutions = new IntValue(0);
     128      var checkExpressionsWithIntervalArithmetic = new BoolValue(false);
     129      if (Parameters.ContainsKey(EvaluatedSolutionsParameterName)) {
     130        var evaluatedSolutionsParameter = (IValueParameter<IntValue>)Parameters[EvaluatedSolutionsParameterName];
     131        evaluatedSolutions = evaluatedSolutionsParameter.Value;
     132        Parameters.Remove(EvaluatedSolutionsParameterName);
     133      }
     134      Parameters.Add(new FixedValueParameter<IntValue>(EvaluatedSolutionsParameterName, "A counter for the total number of solutions the interpreter has evaluated", evaluatedSolutions));
     135      if (Parameters.ContainsKey(CheckExpressionsWithIntervalArithmeticParameterName)) {
     136        var checkExpressionsWithIntervalArithmeticParameter = (IValueParameter<BoolValue>)Parameters[CheckExpressionsWithIntervalArithmeticParameterName];
     137        Parameters.Remove(CheckExpressionsWithIntervalArithmeticParameterName);
     138        checkExpressionsWithIntervalArithmetic = checkExpressionsWithIntervalArithmeticParameter.Value;
     139      }
     140      Parameters.Add(new FixedValueParameter<BoolValue>(CheckExpressionsWithIntervalArithmeticParameterName, CheckExpressionsWithIntervalArithmeticParameterDescription, checkExpressionsWithIntervalArithmetic));
    126141    }
    127142
    128143    #region IStatefulItem
    129 
    130144    public void InitializeState() {
    131       EvaluatedSolutions.Value = 0;
     145      EvaluatedSolutions = 0;
    132146    }
    133147
    134148    public void ClearState() {
    135       EvaluatedSolutions.Value = 0;
    136     }
    137 
     149    }
    138150    #endregion
    139151
     152    private readonly object syncRoot = new object();
    140153    public IEnumerable<double> GetSymbolicExpressionTreeValues(ISymbolicExpressionTree tree, IDataset dataset, IEnumerable<int> rows) {
    141       if (CheckExpressionsWithIntervalArithmetic.Value)
     154      if (CheckExpressionsWithIntervalArithmetic)
    142155        throw new NotSupportedException("Interval arithmetic is not yet supported in the symbolic data analysis interpreter.");
    143156
    144       EvaluatedSolutions.Value++; // increment the evaluated solutions counter
     157      lock (syncRoot) {
     158        EvaluatedSolutions++; // increment the evaluated solutions counter
     159      }
    145160      var state = PrepareInterpreterState(tree, dataset);
    146161
     
    244259              il.Emit(System.Reflection.Emit.OpCodes.Add);
    245260            }
    246             il.Emit(System.Reflection.Emit.OpCodes.Ldc_I4, nArgs);
     261            il.Emit(System.Reflection.Emit.OpCodes.Ldc_R8, (double)nArgs);
    247262            il.Emit(System.Reflection.Emit.OpCodes.Div);
    248263            return;
     
    442457            il.Emit(System.Reflection.Emit.OpCodes.Ldc_I4_0); // > 0
    443458            il.Emit(System.Reflection.Emit.OpCodes.Cgt);
     459            il.Emit(System.Reflection.Emit.OpCodes.Conv_R8); // convert to float64
    444460            il.Emit(System.Reflection.Emit.OpCodes.Ldc_R8, 2.0); // * 2
    445461            il.Emit(System.Reflection.Emit.OpCodes.Mul);
     
    460476              il.Emit(System.Reflection.Emit.OpCodes.Xor);
    461477            }
     478            il.Emit(System.Reflection.Emit.OpCodes.Conv_R8); // convert to float64
     479
    462480            il.Emit(System.Reflection.Emit.OpCodes.Ldc_R8, 2.0); // * 2
    463481            il.Emit(System.Reflection.Emit.OpCodes.Mul);
     
    471489
    472490            il.Emit(System.Reflection.Emit.OpCodes.Cgt); // 1 (>) / 0 (otherwise)
     491            il.Emit(System.Reflection.Emit.OpCodes.Conv_R8); // convert to float64
    473492            il.Emit(System.Reflection.Emit.OpCodes.Ldc_R8, 2.0); // * 2
    474493            il.Emit(System.Reflection.Emit.OpCodes.Mul);
     
    481500            CompileInstructions(il, state, ds);
    482501            il.Emit(System.Reflection.Emit.OpCodes.Clt);
     502            il.Emit(System.Reflection.Emit.OpCodes.Conv_R8); // convert to float64
    483503            il.Emit(System.Reflection.Emit.OpCodes.Ldc_R8, 2.0); // * 2
    484504            il.Emit(System.Reflection.Emit.OpCodes.Mul);
  • stable/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/Interpreter/SymbolicDataAnalysisExpressionTreeInterpreter.cs

    r14186 r14811  
    3232  [StorableClass]
    3333  [Item("SymbolicDataAnalysisExpressionTreeInterpreter", "Interpreter for symbolic expression trees including automatically defined functions.")]
    34   public class SymbolicDataAnalysisExpressionTreeInterpreter : ParameterizedNamedItem, ISymbolicDataAnalysisExpressionTreeInterpreter {
     34  public class SymbolicDataAnalysisExpressionTreeInterpreter : ParameterizedNamedItem,
     35    ISymbolicDataAnalysisExpressionTreeInterpreter {
    3536    private const string CheckExpressionsWithIntervalArithmeticParameterName = "CheckExpressionsWithIntervalArithmetic";
     37    private const string CheckExpressionsWithIntervalArithmeticParameterDescription = "Switch that determines if the interpreter checks the validity of expressions with interval arithmetic before evaluating the expression.";
    3638    private const string EvaluatedSolutionsParameterName = "EvaluatedSolutions";
    3739
    38     public override bool CanChangeName { get { return false; } }
    39     public override bool CanChangeDescription { get { return false; } }
     40    public override bool CanChangeName {
     41      get { return false; }
     42    }
     43
     44    public override bool CanChangeDescription {
     45      get { return false; }
     46    }
    4047
    4148    #region parameter properties
    42     public IValueParameter<BoolValue> CheckExpressionsWithIntervalArithmeticParameter {
    43       get { return (IValueParameter<BoolValue>)Parameters[CheckExpressionsWithIntervalArithmeticParameterName]; }
    44     }
    45 
    46     public IValueParameter<IntValue> EvaluatedSolutionsParameter {
    47       get { return (IValueParameter<IntValue>)Parameters[EvaluatedSolutionsParameterName]; }
     49    public IFixedValueParameter<BoolValue> CheckExpressionsWithIntervalArithmeticParameter {
     50      get { return (IFixedValueParameter<BoolValue>)Parameters[CheckExpressionsWithIntervalArithmeticParameterName]; }
     51    }
     52
     53    public IFixedValueParameter<IntValue> EvaluatedSolutionsParameter {
     54      get { return (IFixedValueParameter<IntValue>)Parameters[EvaluatedSolutionsParameterName]; }
    4855    }
    4956    #endregion
    5057
    5158    #region properties
    52     public BoolValue CheckExpressionsWithIntervalArithmetic {
    53       get { return CheckExpressionsWithIntervalArithmeticParameter.Value; }
    54       set { CheckExpressionsWithIntervalArithmeticParameter.Value = value; }
    55     }
    56 
    57     public IntValue EvaluatedSolutions {
    58       get { return EvaluatedSolutionsParameter.Value; }
    59       set { EvaluatedSolutionsParameter.Value = value; }
     59    public bool CheckExpressionsWithIntervalArithmetic {
     60      get { return CheckExpressionsWithIntervalArithmeticParameter.Value.Value; }
     61      set { CheckExpressionsWithIntervalArithmeticParameter.Value.Value = value; }
     62    }
     63
     64    public int EvaluatedSolutions {
     65      get { return EvaluatedSolutionsParameter.Value.Value; }
     66      set { EvaluatedSolutionsParameter.Value.Value = value; }
    6067    }
    6168    #endregion
     
    6370    [StorableConstructor]
    6471    protected SymbolicDataAnalysisExpressionTreeInterpreter(bool deserializing) : base(deserializing) { }
    65     protected SymbolicDataAnalysisExpressionTreeInterpreter(SymbolicDataAnalysisExpressionTreeInterpreter original, Cloner cloner) : base(original, cloner) { }
     72
     73    protected SymbolicDataAnalysisExpressionTreeInterpreter(SymbolicDataAnalysisExpressionTreeInterpreter original,
     74      Cloner cloner)
     75      : base(original, cloner) { }
     76
    6677    public override IDeepCloneable Clone(Cloner cloner) {
    6778      return new SymbolicDataAnalysisExpressionTreeInterpreter(this, cloner);
     
    7081    public SymbolicDataAnalysisExpressionTreeInterpreter()
    7182      : base("SymbolicDataAnalysisExpressionTreeInterpreter", "Interpreter for symbolic expression trees including automatically defined functions.") {
    72       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)));
    73       Parameters.Add(new ValueParameter<IntValue>(EvaluatedSolutionsParameterName, "A counter for the total number of solutions the interpreter has evaluated", new IntValue(0)));
     83      Parameters.Add(new FixedValueParameter<BoolValue>(CheckExpressionsWithIntervalArithmeticParameterName, "Switch that determines if the interpreter checks the validity of expressions with interval arithmetic before evaluating the expression.", new BoolValue(false)));
     84      Parameters.Add(new FixedValueParameter<IntValue>(EvaluatedSolutionsParameterName, "A counter for the total number of solutions the interpreter has evaluated", new IntValue(0)));
    7485    }
    7586
    7687    protected SymbolicDataAnalysisExpressionTreeInterpreter(string name, string description)
    7788      : base(name, description) {
    78       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)));
    79       Parameters.Add(new ValueParameter<IntValue>(EvaluatedSolutionsParameterName, "A counter for the total number of solutions the interpreter has evaluated", new IntValue(0)));
     89      Parameters.Add(new FixedValueParameter<BoolValue>(CheckExpressionsWithIntervalArithmeticParameterName, "Switch that determines if the interpreter checks the validity of expressions with interval arithmetic before evaluating the expression.", new BoolValue(false)));
     90      Parameters.Add(new FixedValueParameter<IntValue>(EvaluatedSolutionsParameterName, "A counter for the total number of solutions the interpreter has evaluated", new IntValue(0)));
    8091    }
    8192
    8293    [StorableHook(HookType.AfterDeserialization)]
    8394    private void AfterDeserialization() {
    84       if (!Parameters.ContainsKey(EvaluatedSolutionsParameterName))
    85         Parameters.Add(new ValueParameter<IntValue>(EvaluatedSolutionsParameterName, "A counter for the total number of solutions the interpreter has evaluated", new IntValue(0)));
     95      var evaluatedSolutions = new IntValue(0);
     96      var checkExpressionsWithIntervalArithmetic = new BoolValue(false);
     97      if (Parameters.ContainsKey(EvaluatedSolutionsParameterName)) {
     98        var evaluatedSolutionsParameter = (IValueParameter<IntValue>)Parameters[EvaluatedSolutionsParameterName];
     99        evaluatedSolutions = evaluatedSolutionsParameter.Value;
     100        Parameters.Remove(EvaluatedSolutionsParameterName);
     101      }
     102      Parameters.Add(new FixedValueParameter<IntValue>(EvaluatedSolutionsParameterName, "A counter for the total number of solutions the interpreter has evaluated", evaluatedSolutions));
     103      if (Parameters.ContainsKey(CheckExpressionsWithIntervalArithmeticParameterName)) {
     104        var checkExpressionsWithIntervalArithmeticParameter = (IValueParameter<BoolValue>)Parameters[CheckExpressionsWithIntervalArithmeticParameterName];
     105        Parameters.Remove(CheckExpressionsWithIntervalArithmeticParameterName);
     106        checkExpressionsWithIntervalArithmetic = checkExpressionsWithIntervalArithmeticParameter.Value;
     107      }
     108      Parameters.Add(new FixedValueParameter<BoolValue>(CheckExpressionsWithIntervalArithmeticParameterName, CheckExpressionsWithIntervalArithmeticParameterDescription, checkExpressionsWithIntervalArithmetic));
    86109    }
    87110
    88111    #region IStatefulItem
    89112    public void InitializeState() {
    90       EvaluatedSolutions.Value = 0;
    91     }
    92 
    93     public void ClearState() {
    94     }
     113      EvaluatedSolutions = 0;
     114    }
     115
     116    public void ClearState() { }
    95117    #endregion
    96118
    97     public IEnumerable<double> GetSymbolicExpressionTreeValues(ISymbolicExpressionTree tree, IDataset dataset, IEnumerable<int> rows) {
    98       if (CheckExpressionsWithIntervalArithmetic.Value)
     119    private readonly object syncRoot = new object();
     120    public IEnumerable<double> GetSymbolicExpressionTreeValues(ISymbolicExpressionTree tree, IDataset dataset,
     121      IEnumerable<int> rows) {
     122      if (CheckExpressionsWithIntervalArithmetic) {
    99123        throw new NotSupportedException("Interval arithmetic is not yet supported in the symbolic data analysis interpreter.");
    100 
    101       lock (EvaluatedSolutions) {
    102         EvaluatedSolutions.Value++; // increment the evaluated solutions counter
     124      }
     125
     126      lock (syncRoot) {
     127        EvaluatedSolutions++; // increment the evaluated solutions counter
    103128      }
    104129      var state = PrepareInterpreterState(tree, dataset);
     
    131156    }
    132157
    133 
    134158    public virtual double Evaluate(IDataset dataset, ref int row, InterpreterState state) {
    135159      Instruction currentInstr = state.NextInstruction();
     
    147171              s -= Evaluate(dataset, ref row, state);
    148172            }
    149             if (currentInstr.nArguments == 1) s = -s;
     173            if (currentInstr.nArguments == 1) { s = -s; }
    150174            return s;
    151175          }
     
    162186              p /= Evaluate(dataset, ref row, state);
    163187            }
    164             if (currentInstr.nArguments == 1) p = 1.0 / p;
     188            if (currentInstr.nArguments == 1) { p = 1.0 / p; }
    165189            return p;
    166190          }
     
    205229        case OpCodes.Gamma: {
    206230            var x = Evaluate(dataset, ref row, state);
    207             if (double.IsNaN(x)) return double.NaN;
    208             else return alglib.gammafunction(x);
     231            if (double.IsNaN(x)) { return double.NaN; } else { return alglib.gammafunction(x); }
    209232          }
    210233        case OpCodes.Psi: {
     
    216239        case OpCodes.Dawson: {
    217240            var x = Evaluate(dataset, ref row, state);
    218             if (double.IsNaN(x)) return double.NaN;
     241            if (double.IsNaN(x)) { return double.NaN; }
    219242            return alglib.dawsonintegral(x);
    220243          }
    221244        case OpCodes.ExponentialIntegralEi: {
    222245            var x = Evaluate(dataset, ref row, state);
    223             if (double.IsNaN(x)) return double.NaN;
     246            if (double.IsNaN(x)) { return double.NaN; }
    224247            return alglib.exponentialintegralei(x);
    225248          }
     
    349372            int positiveSignals = 0;
    350373            for (int i = 0; i < currentInstr.nArguments; i++) {
    351               if (Evaluate(dataset, ref row, state) > 0.0) positiveSignals++;
     374              if (Evaluate(dataset, ref row, state) > 0.0) { positiveSignals++; }
    352375            }
    353376            return positiveSignals % 2 != 0 ? 1.0 : -1.0;
     
    356379            double x = Evaluate(dataset, ref row, state);
    357380            double y = Evaluate(dataset, ref row, state);
    358             if (x > y) return 1.0;
    359             else return -1.0;
     381            if (x > y) { return 1.0; } else { return -1.0; }
    360382          }
    361383        case OpCodes.LT: {
    362384            double x = Evaluate(dataset, ref row, state);
    363385            double y = Evaluate(dataset, ref row, state);
    364             if (x < y) return 1.0;
    365             else return -1.0;
     386            if (x < y) { return 1.0; } else { return -1.0; }
    366387          }
    367388        case OpCodes.TimeLag: {
     
    437458            var laggedVariableTreeNode = (LaggedVariableTreeNode)currentInstr.dynamicNode;
    438459            int actualRow = row + laggedVariableTreeNode.Lag;
    439             if (actualRow < 0 || actualRow >= dataset.Rows) return double.NaN;
     460            if (actualRow < 0 || actualRow >= dataset.Rows) { return double.NaN; }
    440461            return ((IList<double>)currentInstr.data)[actualRow] * laggedVariableTreeNode.Weight;
    441462          }
     
    459480            return trueBranch * p + falseBranch * (1 - p);
    460481          }
    461         default: throw new NotSupportedException();
     482        default:
     483          throw new NotSupportedException();
    462484      }
    463485    }
  • stable/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/Interpreter/SymbolicDataAnalysisExpressionTreeLinearInterpreter.cs

    r14306 r14811  
    3535  public sealed class SymbolicDataAnalysisExpressionTreeLinearInterpreter : ParameterizedNamedItem, ISymbolicDataAnalysisExpressionTreeInterpreter {
    3636    private const string CheckExpressionsWithIntervalArithmeticParameterName = "CheckExpressionsWithIntervalArithmetic";
     37    private const string CheckExpressionsWithIntervalArithmeticParameterDescription = "Switch that determines if the interpreter checks the validity of expressions with interval arithmetic before evaluating the expression.";
    3738    private const string EvaluatedSolutionsParameterName = "EvaluatedSolutions";
    3839
    39     private SymbolicDataAnalysisExpressionTreeInterpreter interpreter;
     40    private readonly SymbolicDataAnalysisExpressionTreeInterpreter interpreter;
    4041
    4142    public override bool CanChangeName {
     
    4849
    4950    #region parameter properties
    50     public IValueParameter<BoolValue> CheckExpressionsWithIntervalArithmeticParameter {
    51       get { return (IValueParameter<BoolValue>)Parameters[CheckExpressionsWithIntervalArithmeticParameterName]; }
    52     }
    53 
    54     public IValueParameter<IntValue> EvaluatedSolutionsParameter {
    55       get { return (IValueParameter<IntValue>)Parameters[EvaluatedSolutionsParameterName]; }
     51    public IFixedValueParameter<BoolValue> CheckExpressionsWithIntervalArithmeticParameter {
     52      get { return (IFixedValueParameter<BoolValue>)Parameters[CheckExpressionsWithIntervalArithmeticParameterName]; }
     53    }
     54
     55    public IFixedValueParameter<IntValue> EvaluatedSolutionsParameter {
     56      get { return (IFixedValueParameter<IntValue>)Parameters[EvaluatedSolutionsParameterName]; }
    5657    }
    5758    #endregion
    5859
    5960    #region properties
    60     public BoolValue CheckExpressionsWithIntervalArithmetic {
    61       get { return CheckExpressionsWithIntervalArithmeticParameter.Value; }
    62       set { CheckExpressionsWithIntervalArithmeticParameter.Value = value; }
    63     }
    64     public IntValue EvaluatedSolutions {
    65       get { return EvaluatedSolutionsParameter.Value; }
    66       set { EvaluatedSolutionsParameter.Value = value; }
     61    public bool CheckExpressionsWithIntervalArithmetic {
     62      get { return CheckExpressionsWithIntervalArithmeticParameter.Value.Value; }
     63      set { CheckExpressionsWithIntervalArithmeticParameter.Value.Value = value; }
     64    }
     65    public int EvaluatedSolutions {
     66      get { return EvaluatedSolutionsParameter.Value.Value; }
     67      set { EvaluatedSolutionsParameter.Value.Value = value; }
    6768    }
    6869    #endregion
     
    7172    private SymbolicDataAnalysisExpressionTreeLinearInterpreter(bool deserializing)
    7273      : base(deserializing) {
     74      interpreter = new SymbolicDataAnalysisExpressionTreeInterpreter();
    7375    }
    7476
     
    8486    public SymbolicDataAnalysisExpressionTreeLinearInterpreter()
    8587      : base("SymbolicDataAnalysisExpressionTreeLinearInterpreter", "Linear (non-recursive) interpreter for symbolic expression trees (does not support ADFs).") {
    86       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)));
    87       Parameters.Add(new ValueParameter<IntValue>(EvaluatedSolutionsParameterName, "A counter for the total number of solutions the interpreter has evaluated", new IntValue(0)));
     88      Parameters.Add(new FixedValueParameter<BoolValue>(CheckExpressionsWithIntervalArithmeticParameterName, CheckExpressionsWithIntervalArithmeticParameterDescription, new BoolValue(false)));
     89      Parameters.Add(new FixedValueParameter<IntValue>(EvaluatedSolutionsParameterName, "A counter for the total number of solutions the interpreter has evaluated", new IntValue(0)));
     90      interpreter = new SymbolicDataAnalysisExpressionTreeInterpreter();
     91    }
     92
     93    public SymbolicDataAnalysisExpressionTreeLinearInterpreter(string name, string description)
     94      : base(name, description) {
     95      Parameters.Add(new FixedValueParameter<BoolValue>(CheckExpressionsWithIntervalArithmeticParameterName, CheckExpressionsWithIntervalArithmeticParameterDescription, new BoolValue(false)));
     96      Parameters.Add(new FixedValueParameter<IntValue>(EvaluatedSolutionsParameterName, "A counter for the total number of solutions the interpreter has evaluated", new IntValue(0)));
    8897      interpreter = new SymbolicDataAnalysisExpressionTreeInterpreter();
    8998    }
     
    91100    [StorableHook(HookType.AfterDeserialization)]
    92101    private void AfterDeserialization() {
    93       if (interpreter == null) interpreter = new SymbolicDataAnalysisExpressionTreeInterpreter();
     102      var evaluatedSolutions = new IntValue(0);
     103      var checkExpressionsWithIntervalArithmetic = new BoolValue(false);
     104      if (Parameters.ContainsKey(EvaluatedSolutionsParameterName)) {
     105        var evaluatedSolutionsParameter = (IValueParameter<IntValue>)Parameters[EvaluatedSolutionsParameterName];
     106        evaluatedSolutions = evaluatedSolutionsParameter.Value;
     107        Parameters.Remove(EvaluatedSolutionsParameterName);
     108      }
     109      Parameters.Add(new FixedValueParameter<IntValue>(EvaluatedSolutionsParameterName, "A counter for the total number of solutions the interpreter has evaluated", evaluatedSolutions));
     110      if (Parameters.ContainsKey(CheckExpressionsWithIntervalArithmeticParameterName)) {
     111        var checkExpressionsWithIntervalArithmeticParameter = (IValueParameter<BoolValue>)Parameters[CheckExpressionsWithIntervalArithmeticParameterName];
     112        Parameters.Remove(CheckExpressionsWithIntervalArithmeticParameterName);
     113        checkExpressionsWithIntervalArithmetic = checkExpressionsWithIntervalArithmeticParameter.Value;
     114      }
     115      Parameters.Add(new FixedValueParameter<BoolValue>(CheckExpressionsWithIntervalArithmeticParameterName, CheckExpressionsWithIntervalArithmeticParameterDescription, checkExpressionsWithIntervalArithmetic));
    94116    }
    95117
    96118    #region IStatefulItem
    97119    public void InitializeState() {
    98       EvaluatedSolutions.Value = 0;
     120      EvaluatedSolutions = 0;
    99121    }
    100122
     
    102124    #endregion
    103125
     126    private readonly object syncRoot = new object();
    104127    public IEnumerable<double> GetSymbolicExpressionTreeValues(ISymbolicExpressionTree tree, IDataset dataset, IEnumerable<int> rows) {
    105       if (CheckExpressionsWithIntervalArithmetic.Value)
     128      if (CheckExpressionsWithIntervalArithmetic)
    106129        throw new NotSupportedException("Interval arithmetic is not yet supported in the symbolic data analysis interpreter.");
    107130
    108       lock (EvaluatedSolutions) {
    109         EvaluatedSolutions.Value++; // increment the evaluated solutions counter
     131      lock (syncRoot) {
     132        EvaluatedSolutions++; // increment the evaluated solutions counter
    110133      }
    111134
     
    190213        } else if (instr.opCode == OpCodes.Root) {
    191214          double x = code[instr.childIndex].value;
    192           double y = code[instr.childIndex + 1].value;
     215          double y = Math.Round(code[instr.childIndex + 1].value);
    193216          instr.value = Math.Pow(x, 1 / y);
    194217        } else if (instr.opCode == OpCodes.Exp) {
  • stable/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/Symbols/VariableCondition.cs

    r14186 r14811  
    148148          OnChanged(EventArgs.Empty);
    149149        }
     150      }
     151    }
     152
     153    public override bool Enabled {
     154      get {
     155        if (variableNames.Count == 0) return false;
     156        return base.Enabled;
     157      }
     158      set {
     159        if (variableNames.Count == 0) base.Enabled = false;
     160        else base.Enabled = value;
    150161      }
    151162    }
  • stable/HeuristicLab.Tests

  • stable/HeuristicLab.Tests/HeuristicLab.Problems.DataAnalysis.Symbolic-3.4/SymbolicDataAnalysisExpressionTreeInterpreterTest.cs

    r14186 r14811  
    7070    }
    7171
     72    [TestMethod]
     73    [TestCategory("Problems.DataAnalysis.Symbolic")]
     74    [TestProperty("Time", "long")]
     75    public void CompiledInterpreterTestTypeCoherentGrammarPerformance() {
     76      TestTypeCoherentGrammarPerformance(new SymbolicDataAnalysisExpressionCompiledTreeInterpreter(), 12.5e6);
     77    }
     78    [TestMethod]
     79    [TestCategory("Problems.DataAnalysis.Symbolic")]
     80    [TestProperty("Time", "long")]
     81    public void CompiledInterpreterTestFullGrammarPerformance() {
     82      TestFullGrammarPerformance(new SymbolicDataAnalysisExpressionCompiledTreeInterpreter(), 12.5e6);
     83    }
     84    [TestMethod]
     85    [TestCategory("Problems.DataAnalysis.Symbolic")]
     86    [TestProperty("Time", "long")]
     87    public void CompiledInterpreterTestArithmeticGrammarPerformance() {
     88      TestArithmeticGrammarPerformance(new SymbolicDataAnalysisExpressionCompiledTreeInterpreter(), 12.5e6);
     89    }
    7290
    7391    [TestMethod]
     
    8098    [TestCategory("Problems.DataAnalysis.Symbolic")]
    8199    [TestProperty("Time", "long")]
    82     public void ILEmittingInterpreterTestFullGrammarPerformance() {
    83       TestFullGrammarPerformance(new SymbolicDataAnalysisExpressionTreeILEmittingInterpreter(), 7.5e6);
    84     }
    85     [TestMethod]
    86     [TestCategory("Problems.DataAnalysis.Symbolic")]
    87     [TestProperty("Time", "long")]
    88100    public void ILEmittingInterpreterTestArithmeticGrammarPerformance() {
    89101      TestArithmeticGrammarPerformance(new SymbolicDataAnalysisExpressionTreeILEmittingInterpreter(), 7.5e6);
    90102    }
    91 
    92103
    93104    [TestMethod]
     
    113124      var twister = new MersenneTwister(31415);
    114125      var dataset = Util.CreateRandomDataset(twister, Rows, Columns);
     126
    115127      var grammar = new TypeCoherentExpressionGrammar();
    116128      grammar.ConfigureAsDefaultRegressionGrammar();
    117       grammar.MaximumFunctionArguments = 0;
    118       grammar.MaximumFunctionDefinitions = 0;
    119       grammar.MinimumFunctionArguments = 0;
    120       grammar.MinimumFunctionDefinitions = 0;
     129
    121130      var randomTrees = Util.CreateRandomTrees(twister, dataset, grammar, N, 1, 100, 0, 0);
    122131      foreach (ISymbolicExpressionTree tree in randomTrees) {
     
    131140      var twister = new MersenneTwister(31415);
    132141      var dataset = Util.CreateRandomDataset(twister, Rows, Columns);
     142
    133143      var grammar = new FullFunctionalExpressionGrammar();
    134       grammar.MaximumFunctionArguments = 0;
    135       grammar.MaximumFunctionDefinitions = 0;
    136       grammar.MinimumFunctionArguments = 0;
    137       grammar.MinimumFunctionDefinitions = 0;
    138144      var randomTrees = Util.CreateRandomTrees(twister, dataset, grammar, N, 1, 100, 0, 0);
    139145      foreach (ISymbolicExpressionTree tree in randomTrees) {
     
    148154      var twister = new MersenneTwister(31415);
    149155      var dataset = Util.CreateRandomDataset(twister, Rows, Columns);
     156
    150157      var grammar = new ArithmeticExpressionGrammar();
    151       //grammar.Symbols.OfType<Variable>().First().Enabled = false;
    152       grammar.MaximumFunctionArguments = 0;
    153       grammar.MaximumFunctionDefinitions = 0;
    154       grammar.MinimumFunctionArguments = 0;
    155       grammar.MinimumFunctionDefinitions = 0;
    156158      var randomTrees = Util.CreateRandomTrees(twister, dataset, grammar, N, 1, 100, 0, 0);
    157159      foreach (SymbolicExpressionTree tree in randomTrees) {
     
    175177      EvaluateTerminals(interpreter, ds);
    176178      EvaluateOperations(interpreter, ds);
     179      EvaluateLaggedOperations(interpreter, ds);
     180      EvaluateSpecialFunctions(interpreter, ds);
    177181      EvaluateAdf(interpreter, ds);
    178182    }
    179183
     184    /// <summary>
     185    ///A test for Evaluate
     186    ///</summary>
    180187    [TestMethod]
    181188    [TestCategory("Problems.DataAnalysis.Symbolic")]
     
    185192      EvaluateTerminals(interpreter, ds);
    186193      EvaluateOperations(interpreter, ds);
     194      EvaluateLaggedOperations(interpreter, ds);
     195      EvaluateSpecialFunctions(interpreter, ds);
     196    }
     197
     198    [TestMethod]
     199    [TestCategory("Problems.DataAnalysis.Symbolic")]
     200    [TestProperty("Time", "short")]
     201    public void CompiledInterpreterTestEvaluation() {
     202      var interpreter = new SymbolicDataAnalysisExpressionCompiledTreeInterpreter();
     203      EvaluateTerminals(interpreter, ds);
     204      EvaluateOperations(interpreter, ds);
     205      EvaluateSpecialFunctions(interpreter, ds);
    187206    }
    188207
     
    192211    public void LinearInterpreterTestEvaluation() {
    193212      var interpreter = new SymbolicDataAnalysisExpressionTreeLinearInterpreter();
    194 
    195213      //ADFs are not supported by the linear interpreter
    196214      EvaluateTerminals(interpreter, ds);
    197215      EvaluateOperations(interpreter, ds);
    198     }
    199 
    200     private void EvaluateTerminals(ISymbolicDataAnalysisExpressionTreeInterpreter interpreter, Dataset ds) {
     216      EvaluateLaggedOperations(interpreter, ds);
     217      EvaluateSpecialFunctions(interpreter, ds);
     218    }
     219
     220    [TestMethod]
     221    [TestCategory("Problems.DataAnalysis.Symbolic")]
     222    [TestProperty("Time", "long")]
     223    public void TestInterpretersEstimatedValuesConsistency() {
     224      var twister = new MersenneTwister();
     225      int seed = twister.Next(0, int.MaxValue);
     226      twister.Seed((uint)seed);
     227      const int numRows = 100;
     228      var dataset = Util.CreateRandomDataset(twister, numRows, Columns);
     229
     230      var grammar = new TypeCoherentExpressionGrammar();
     231
     232      var interpreters = new ISymbolicDataAnalysisExpressionTreeInterpreter[] {
     233        new SymbolicDataAnalysisExpressionTreeLinearInterpreter(),
     234        new SymbolicDataAnalysisExpressionTreeInterpreter(),
     235      };
     236
     237      var rows = Enumerable.Range(0, numRows).ToList();
     238      var randomTrees = Util.CreateRandomTrees(twister, dataset, grammar, N, 1, 10, 0, 0);
     239      foreach (ISymbolicExpressionTree tree in randomTrees) {
     240        Util.InitTree(tree, twister, new List<string>(dataset.VariableNames));
     241      }
     242
     243      for (int i = 0; i < randomTrees.Length; ++i) {
     244        var tree = randomTrees[i];
     245        var valuesMatrix = interpreters.Select(x => x.GetSymbolicExpressionTreeValues(tree, dataset, rows)).ToList();
     246        for (int m = 0; m < interpreters.Length - 1; ++m) {
     247          var sum = valuesMatrix[m].Sum();
     248          for (int n = m + 1; n < interpreters.Length; ++n) {
     249            var s = valuesMatrix[n].Sum();
     250            if (double.IsNaN(sum) && double.IsNaN(s)) continue;
     251
     252            string errorMessage = string.Format("Interpreters {0} and {1} do not agree on tree {2} (seed = {3}).", interpreters[m].Name, interpreters[n].Name, i, seed);
     253            Assert.AreEqual(sum, s, 1e-12, errorMessage);
     254          }
     255        }
     256      }
     257    }
     258
     259    [TestMethod]
     260    [TestCategory("Problems.DataAnalysis.Symbolic")]
     261    [TestProperty("Time", "long")]
     262    public void TestCompiledInterpreterEstimatedValuesConsistency() {
     263      const double delta = 1e-12;
     264
     265      var twister = new MersenneTwister();
     266      int seed = twister.Next(0, int.MaxValue);
     267      twister.Seed((uint)seed);
     268
     269      Console.WriteLine(seed);
     270
     271      const int numRows = 100;
     272      var dataset = Util.CreateRandomDataset(twister, numRows, Columns);
     273
     274      var grammar = new TypeCoherentExpressionGrammar();
     275      grammar.ConfigureAsDefaultRegressionGrammar();
     276      grammar.Symbols.First(x => x.Name == "Power Functions").Enabled = true;
     277
     278      var randomTrees = Util.CreateRandomTrees(twister, dataset, grammar, N, 1, 10, 0, 0);
     279      foreach (ISymbolicExpressionTree tree in randomTrees) {
     280        Util.InitTree(tree, twister, new List<string>(dataset.VariableNames));
     281      }
     282
     283      var interpreters = new ISymbolicDataAnalysisExpressionTreeInterpreter[] {
     284        new SymbolicDataAnalysisExpressionCompiledTreeInterpreter(),
     285        new SymbolicDataAnalysisExpressionTreeInterpreter(),
     286        new SymbolicDataAnalysisExpressionTreeLinearInterpreter(),
     287      };
     288      var rows = Enumerable.Range(0, numRows).ToList();
     289      var formatter = new SymbolicExpressionTreeHierarchicalFormatter();
     290
     291      for (int i = 0; i < randomTrees.Length; ++i) {
     292        var tree = randomTrees[i];
     293        var valuesMatrix = interpreters.Select(x => x.GetSymbolicExpressionTreeValues(tree, dataset, rows).ToList()).ToList();
     294        for (int m = 0; m < interpreters.Length - 1; ++m) {
     295          for (int n = m + 1; n < interpreters.Length; ++n) {
     296            for (int row = 0; row < numRows; ++row) {
     297              var v1 = valuesMatrix[m][row];
     298              var v2 = valuesMatrix[n][row];
     299              if (double.IsNaN(v1) && double.IsNaN(v2)) continue;
     300              if (Math.Abs(v1 - v2) > delta) {
     301                Console.WriteLine(formatter.Format(tree));
     302                foreach (var node in tree.Root.GetSubtree(0).GetSubtree(0).IterateNodesPrefix().ToList()) {
     303                  var rootNode = (SymbolicExpressionTreeTopLevelNode)grammar.ProgramRootSymbol.CreateTreeNode();
     304                  if (rootNode.HasLocalParameters) rootNode.ResetLocalParameters(twister);
     305                  rootNode.SetGrammar(grammar.CreateExpressionTreeGrammar());
     306
     307                  var startNode = (SymbolicExpressionTreeTopLevelNode)grammar.StartSymbol.CreateTreeNode();
     308                  if (startNode.HasLocalParameters) startNode.ResetLocalParameters(twister);
     309                  startNode.SetGrammar(grammar.CreateExpressionTreeGrammar());
     310
     311                  rootNode.AddSubtree(startNode);
     312                  var t = new SymbolicExpressionTree(rootNode);
     313                  var start = t.Root.GetSubtree(0);
     314                  var p = node.Parent;
     315                  start.AddSubtree(node);
     316                  Console.WriteLine(node);
     317
     318                  var y1 = interpreters[m].GetSymbolicExpressionTreeValues(t, dataset, new[] { row }).First();
     319                  var y2 = interpreters[n].GetSymbolicExpressionTreeValues(t, dataset, new[] { row }).First();
     320
     321                  if (double.IsNaN(y1) && double.IsNaN(y2)) continue;
     322                  string prefix = Math.Abs(y1 - y2) > delta ? "++" : "==";
     323                  Console.WriteLine("\t{0} Row {1}: {2} {3}, Deviation = {4}", prefix, row, y1, y2, Math.Abs(y1 - y2));
     324                  node.Parent = p;
     325                }
     326              }
     327              string errorMessage = string.Format("Interpreters {0} and {1} do not agree on tree {2} and row {3} (seed = {4}).", interpreters[m].Name, interpreters[n].Name, i, row, seed);
     328              Assert.AreEqual(v1, v2, delta, errorMessage);
     329            }
     330          }
     331        }
     332      }
     333    }
     334
     335    private void EvaluateTerminals(ISymbolicDataAnalysisExpressionTreeInterpreter interpreter, IDataset ds) {
    201336      // constants
    202337      Evaluate(interpreter, ds, "(+ 1.5 3.5)", 0, 5.0);
     
    207342    }
    208343
    209     private void EvaluateAdf(ISymbolicDataAnalysisExpressionTreeInterpreter interpreter, Dataset ds) {
     344    private void EvaluateAdf(ISymbolicDataAnalysisExpressionTreeInterpreter interpreter, IDataset ds) {
    210345
    211346      // ADF     
     
    246381    }
    247382
    248     private void EvaluateOperations(ISymbolicDataAnalysisExpressionTreeInterpreter interpreter, Dataset ds) {
     383    private void EvaluateSpecialFunctions(ISymbolicDataAnalysisExpressionTreeInterpreter interpreter, IDataset ds) {
     384      // special functions
     385      Action<double> checkAiry = (x) => {
     386        double ai, aip, bi, bip;
     387        alglib.airy(x, out ai, out aip, out bi, out bip);
     388        Evaluate(interpreter, ds, "(airya " + x + ")", 0, ai);
     389        Evaluate(interpreter, ds, "(airyb " + x + ")", 0, bi);
     390      };
     391
     392      Action<double> checkBessel = (x) => {
     393        Evaluate(interpreter, ds, "(bessel " + x + ")", 0, alglib.besseli0(x));
     394      };
     395
     396      Action<double> checkSinCosIntegrals = (x) => {
     397        double si, ci;
     398        alglib.sinecosineintegrals(x, out si, out ci);
     399        Evaluate(interpreter, ds, "(cosint " + x + ")", 0, ci);
     400        Evaluate(interpreter, ds, "(sinint " + x + ")", 0, si);
     401      };
     402      Action<double> checkHypSinCosIntegrals = (x) => {
     403        double shi, chi;
     404        alglib.hyperbolicsinecosineintegrals(x, out shi, out chi);
     405        Evaluate(interpreter, ds, "(hypcosint " + x + ")", 0, chi);
     406        Evaluate(interpreter, ds, "(hypsinint " + x + ")", 0, shi);
     407      };
     408      Action<double> checkFresnelSinCosIntegrals = (x) => {
     409        double c = 0, s = 0;
     410        alglib.fresnelintegral(x, ref c, ref s);
     411        Evaluate(interpreter, ds, "(fresnelcosint " + x + ")", 0, c);
     412        Evaluate(interpreter, ds, "(fresnelsinint " + x + ")", 0, s);
     413      };
     414      Action<double> checkNormErf = (x) => {
     415        Evaluate(interpreter, ds, "(norm " + x + ")", 0, alglib.normaldistribution(x));
     416        Evaluate(interpreter, ds, "(erf " + x + ")", 0, alglib.errorfunction(x));
     417      };
     418
     419      Action<double> checkGamma = (x) => {
     420        Evaluate(interpreter, ds, "(gamma " + x + ")", 0, alglib.gammafunction(x));
     421      };
     422      Action<double> checkPsi = (x) => {
     423        try {
     424          Evaluate(interpreter, ds, "(psi " + x + ")", 0, alglib.psi(x));
     425        } catch (alglib.alglibexception) { // ignore cases where alglib throws an exception
     426        }
     427      };
     428      Action<double> checkDawson = (x) => {
     429        Evaluate(interpreter, ds, "(dawson " + x + ")", 0, alglib.dawsonintegral(x));
     430      };
     431      Action<double> checkExpInt = (x) => {
     432        Evaluate(interpreter, ds, "(expint " + x + ")", 0, alglib.exponentialintegralei(x));
     433      };
     434
     435      foreach (var e in new[] { -2.0, -1.0, 0.0, 1.0, 2.0 }) {
     436        checkAiry(e);
     437        checkBessel(e);
     438        checkSinCosIntegrals(e);
     439        checkGamma(e);
     440        checkExpInt(e);
     441        checkDawson(e);
     442        checkPsi(e);
     443        checkNormErf(e);
     444        checkFresnelSinCosIntegrals(e);
     445        checkHypSinCosIntegrals(e);
     446      }
     447    }
     448
     449    private void EvaluateLaggedOperations(ISymbolicDataAnalysisExpressionTreeInterpreter interpreter, IDataset ds) {
     450      // lag
     451      Evaluate(interpreter, ds, "(lagVariable 1.0 a -1) ", 1, ds.GetDoubleValue("A", 0));
     452      Evaluate(interpreter, ds, "(lagVariable 1.0 a -1) ", 2, ds.GetDoubleValue("A", 1));
     453      Evaluate(interpreter, ds, "(lagVariable 1.0 a 0) ", 2, ds.GetDoubleValue("A", 2));
     454      Evaluate(interpreter, ds, "(lagVariable 1.0 a 1) ", 0, ds.GetDoubleValue("A", 1));
     455
     456      // integral
     457      Evaluate(interpreter, ds, "(integral -1.0 (variable 1.0 a)) ", 1, ds.GetDoubleValue("A", 0) + ds.GetDoubleValue("A", 1));
     458      Evaluate(interpreter, ds, "(integral -1.0 (lagVariable 1.0 a 1)) ", 1, ds.GetDoubleValue("A", 1) + ds.GetDoubleValue("A", 2));
     459      Evaluate(interpreter, ds, "(integral -2.0 (variable 1.0 a)) ", 2, ds.GetDoubleValue("A", 0) + ds.GetDoubleValue("A", 1) + ds.GetDoubleValue("A", 2));
     460      Evaluate(interpreter, ds, "(integral -1.0 (* (variable 1.0 a) (variable 1.0 b)))", 1, ds.GetDoubleValue("A", 0) * ds.GetDoubleValue("B", 0) + ds.GetDoubleValue("A", 1) * ds.GetDoubleValue("B", 1));
     461      Evaluate(interpreter, ds, "(integral -2.0 3.0)", 1, 9.0);
     462
     463      // derivative
     464      // (f_0 + 2 * f_1 - 2 * f_3 - f_4) / 8; // h = 1
     465      Evaluate(interpreter, ds, "(diff (variable 1.0 a)) ", 5, (ds.GetDoubleValue("A", 5) + 2 * ds.GetDoubleValue("A", 4) - 2 * ds.GetDoubleValue("A", 2) - ds.GetDoubleValue("A", 1)) / 8.0);
     466      Evaluate(interpreter, ds, "(diff (variable 1.0 b)) ", 5, (ds.GetDoubleValue("B", 5) + 2 * ds.GetDoubleValue("B", 4) - 2 * ds.GetDoubleValue("B", 2) - ds.GetDoubleValue("B", 1)) / 8.0);
     467      Evaluate(interpreter, ds, "(diff (* (variable 1.0 a) (variable 1.0 b)))", 5, +
     468        (ds.GetDoubleValue("A", 5) * ds.GetDoubleValue("B", 5) +
     469        2 * ds.GetDoubleValue("A", 4) * ds.GetDoubleValue("B", 4) -
     470        2 * ds.GetDoubleValue("A", 2) * ds.GetDoubleValue("B", 2) -
     471        ds.GetDoubleValue("A", 1) * ds.GetDoubleValue("B", 1)) / 8.0);
     472      Evaluate(interpreter, ds, "(diff -2.0 3.0)", 5, 0.0);
     473
     474      // timelag
     475      Evaluate(interpreter, ds, "(lag -1.0 (lagVariable 1.0 a 2)) ", 1, ds.GetDoubleValue("A", 2));
     476      Evaluate(interpreter, ds, "(lag -2.0 (lagVariable 1.0 a 2)) ", 2, ds.GetDoubleValue("A", 2));
     477      Evaluate(interpreter, ds, "(lag -1.0 (* (lagVariable 1.0 a 1) (lagVariable 1.0 b 2)))", 1, ds.GetDoubleValue("A", 1) * ds.GetDoubleValue("B", 2));
     478      Evaluate(interpreter, ds, "(lag -2.0 3.0)", 1, 3.0);
     479    }
     480
     481    private void EvaluateOperations(ISymbolicDataAnalysisExpressionTreeInterpreter interpreter, IDataset ds) {
    249482      // addition
    250483      Evaluate(interpreter, ds, "(+ (variable 2.0 a ))", 1, 4.0);
     
    369602      // mean
    370603      Evaluate(interpreter, ds, "(mean -1.0 1.0 -1.0)", 0, -1.0 / 3.0);
    371 
    372       // lag
    373       Evaluate(interpreter, ds, "(lagVariable 1.0 a -1) ", 1, ds.GetDoubleValue("A", 0));
    374       Evaluate(interpreter, ds, "(lagVariable 1.0 a -1) ", 2, ds.GetDoubleValue("A", 1));
    375       Evaluate(interpreter, ds, "(lagVariable 1.0 a 0) ", 2, ds.GetDoubleValue("A", 2));
    376       Evaluate(interpreter, ds, "(lagVariable 1.0 a 1) ", 0, ds.GetDoubleValue("A", 1));
    377 
    378       // integral
    379       Evaluate(interpreter, ds, "(integral -1.0 (variable 1.0 a)) ", 1, ds.GetDoubleValue("A", 0) + ds.GetDoubleValue("A", 1));
    380       Evaluate(interpreter, ds, "(integral -1.0 (lagVariable 1.0 a 1)) ", 1, ds.GetDoubleValue("A", 1) + ds.GetDoubleValue("A", 2));
    381       Evaluate(interpreter, ds, "(integral -2.0 (variable 1.0 a)) ", 2, ds.GetDoubleValue("A", 0) + ds.GetDoubleValue("A", 1) + ds.GetDoubleValue("A", 2));
    382       Evaluate(interpreter, ds, "(integral -1.0 (* (variable 1.0 a) (variable 1.0 b)))", 1, ds.GetDoubleValue("A", 0) * ds.GetDoubleValue("B", 0) + ds.GetDoubleValue("A", 1) * ds.GetDoubleValue("B", 1));
    383       Evaluate(interpreter, ds, "(integral -2.0 3.0)", 1, 9.0);
    384 
    385       // derivative
    386       // (f_0 + 2 * f_1 - 2 * f_3 - f_4) / 8; // h = 1
    387       Evaluate(interpreter, ds, "(diff (variable 1.0 a)) ", 5, (ds.GetDoubleValue("A", 5) + 2 * ds.GetDoubleValue("A", 4) - 2 * ds.GetDoubleValue("A", 2) - ds.GetDoubleValue("A", 1)) / 8.0);
    388       Evaluate(interpreter, ds, "(diff (variable 1.0 b)) ", 5, (ds.GetDoubleValue("B", 5) + 2 * ds.GetDoubleValue("B", 4) - 2 * ds.GetDoubleValue("B", 2) - ds.GetDoubleValue("B", 1)) / 8.0);
    389       Evaluate(interpreter, ds, "(diff (* (variable 1.0 a) (variable 1.0 b)))", 5, +
    390         (ds.GetDoubleValue("A", 5) * ds.GetDoubleValue("B", 5) +
    391         2 * ds.GetDoubleValue("A", 4) * ds.GetDoubleValue("B", 4) -
    392         2 * ds.GetDoubleValue("A", 2) * ds.GetDoubleValue("B", 2) -
    393         ds.GetDoubleValue("A", 1) * ds.GetDoubleValue("B", 1)) / 8.0);
    394       Evaluate(interpreter, ds, "(diff -2.0 3.0)", 5, 0.0);
    395 
    396       // timelag
    397       Evaluate(interpreter, ds, "(lag -1.0 (lagVariable 1.0 a 2)) ", 1, ds.GetDoubleValue("A", 2));
    398       Evaluate(interpreter, ds, "(lag -2.0 (lagVariable 1.0 a 2)) ", 2, ds.GetDoubleValue("A", 2));
    399       Evaluate(interpreter, ds, "(lag -1.0 (* (lagVariable 1.0 a 1) (lagVariable 1.0 b 2)))", 1, ds.GetDoubleValue("A", 1) * ds.GetDoubleValue("B", 2));
    400       Evaluate(interpreter, ds, "(lag -2.0 3.0)", 1, 3.0);
    401 
    402       {
    403         // special functions
    404         Action<double> checkAiry = (x) => {
    405           double ai, aip, bi, bip;
    406           alglib.airy(x, out ai, out aip, out bi, out bip);
    407           Evaluate(interpreter, ds, "(airya " + x + ")", 0, ai);
    408           Evaluate(interpreter, ds, "(airyb " + x + ")", 0, bi);
    409         };
    410 
    411         Action<double> checkBessel = (x) => {
    412           Evaluate(interpreter, ds, "(bessel " + x + ")", 0, alglib.besseli0(x));
    413         };
    414 
    415         Action<double> checkSinCosIntegrals = (x) => {
    416           double si, ci;
    417           alglib.sinecosineintegrals(x, out si, out ci);
    418           Evaluate(interpreter, ds, "(cosint " + x + ")", 0, ci);
    419           Evaluate(interpreter, ds, "(sinint " + x + ")", 0, si);
    420         };
    421         Action<double> checkHypSinCosIntegrals = (x) => {
    422           double shi, chi;
    423           alglib.hyperbolicsinecosineintegrals(x, out shi, out chi);
    424           Evaluate(interpreter, ds, "(hypcosint " + x + ")", 0, chi);
    425           Evaluate(interpreter, ds, "(hypsinint " + x + ")", 0, shi);
    426         };
    427         Action<double> checkFresnelSinCosIntegrals = (x) => {
    428           double c = 0, s = 0;
    429           alglib.fresnelintegral(x, ref c, ref s);
    430           Evaluate(interpreter, ds, "(fresnelcosint " + x + ")", 0, c);
    431           Evaluate(interpreter, ds, "(fresnelsinint " + x + ")", 0, s);
    432         };
    433         Action<double> checkNormErf = (x) => {
    434           Evaluate(interpreter, ds, "(norm " + x + ")", 0, alglib.normaldistribution(x));
    435           Evaluate(interpreter, ds, "(erf " + x + ")", 0, alglib.errorfunction(x));
    436         };
    437 
    438         Action<double> checkGamma = (x) => {
    439           Evaluate(interpreter, ds, "(gamma " + x + ")", 0, alglib.gammafunction(x));
    440         };
    441         Action<double> checkPsi = (x) => {
    442           try {
    443             Evaluate(interpreter, ds, "(psi " + x + ")", 0, alglib.psi(x));
    444           }
    445           catch (alglib.alglibexception) { // ignore cases where alglib throws an exception
    446           }
    447         };
    448         Action<double> checkDawson = (x) => {
    449           Evaluate(interpreter, ds, "(dawson " + x + ")", 0, alglib.dawsonintegral(x));
    450         };
    451         Action<double> checkExpInt = (x) => {
    452           Evaluate(interpreter, ds, "(expint " + x + ")", 0, alglib.exponentialintegralei(x));
    453         };
    454 
    455 
    456 
    457         foreach (var e in new[] { -2.0, -1.0, 0.0, 1.0, 2.0 }) {
    458           checkAiry(e);
    459           checkBessel(e);
    460           checkSinCosIntegrals(e);
    461           checkGamma(e);
    462           checkExpInt(e);
    463           checkDawson(e);
    464           checkPsi(e);
    465           checkNormErf(e);
    466           checkFresnelSinCosIntegrals(e);
    467           checkHypSinCosIntegrals(e);
    468         }
    469       }
    470     }
    471 
    472     private void Evaluate(ISymbolicDataAnalysisExpressionTreeInterpreter interpreter, Dataset ds, string expr, int index, double expected) {
     604    }
     605
     606    private void Evaluate(ISymbolicDataAnalysisExpressionTreeInterpreter interpreter, IDataset ds, string expr, int index, double expected) {
    473607      var importer = new SymbolicExpressionImporter();
    474608      ISymbolicExpressionTree tree = importer.Import(expr);
Note: See TracChangeset for help on using the changeset viewer.