Index: /stable/HeuristicLab.Problems.DataAnalysis.Symbolic.TimeSeriesPrognosis/3.4/SymbolicTimeSeriesPrognosisExpressionTreeInterpreter.cs
===================================================================
--- /stable/HeuristicLab.Problems.DataAnalysis.Symbolic.TimeSeriesPrognosis/3.4/SymbolicTimeSeriesPrognosisExpressionTreeInterpreter.cs	(revision 14810)
+++ /stable/HeuristicLab.Problems.DataAnalysis.Symbolic.TimeSeriesPrognosis/3.4/SymbolicTimeSeriesPrognosisExpressionTreeInterpreter.cs	(revision 14811)
@@ -73,6 +73,7 @@
     }
 
+    private readonly object syncRoot = new object();
     public IEnumerable<IEnumerable<double>> GetSymbolicExpressionTreeValues(ISymbolicExpressionTree tree, IDataset dataset, IEnumerable<int> rows, IEnumerable<int> horizons) {
-      if (CheckExpressionsWithIntervalArithmetic.Value)
+      if (CheckExpressionsWithIntervalArithmetic)
         throw new NotSupportedException("Interval arithmetic is not yet supported in the symbolic data analysis interpreter.");
       if (targetVariableCache == null || targetVariableCache.GetLength(0) < dataset.Rows)
@@ -82,6 +83,6 @@
 
       string targetVariable = TargetVariable;
-      lock (EvaluatedSolutions) {
-        EvaluatedSolutions.Value++; // increment the evaluated solutions counter
+      lock (syncRoot) {
+        EvaluatedSolutions++; // increment the evaluated solutions counter
       }
       var state = PrepareInterpreterState(tree, dataset, targetVariableCache, TargetVariable);
Index: /stable/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/HeuristicLab.Problems.DataAnalysis.Symbolic-3.4.csproj
===================================================================
--- /stable/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/HeuristicLab.Problems.DataAnalysis.Symbolic-3.4.csproj	(revision 14810)
+++ /stable/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/HeuristicLab.Problems.DataAnalysis.Symbolic-3.4.csproj	(revision 14811)
@@ -140,4 +140,5 @@
     <Compile Include="Importer\Token.cs" />
     <Compile Include="Interfaces\IModelBacktransformator.cs" />
+    <Compile Include="Interpreter\SymbolicDataAnalysisExpressionCompiledTreeInterpreter.cs" />
     <Compile Include="SymbolicDataAnalysisExpressionTreeSimplificationOperator.cs" />
     <Compile Include="SymbolicDataAnalysisModelComplexityCalculator.cs" />
Index: /stable/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/Interfaces/ISymbolicDataAnalysisExpressionTreeInterpreter.cs
===================================================================
--- /stable/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/Interfaces/ISymbolicDataAnalysisExpressionTreeInterpreter.cs	(revision 14810)
+++ /stable/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/Interfaces/ISymbolicDataAnalysisExpressionTreeInterpreter.cs	(revision 14811)
@@ -22,5 +22,4 @@
 using System.Collections.Generic;
 using HeuristicLab.Core;
-using HeuristicLab.Data;
 using HeuristicLab.Encodings.SymbolicExpressionTreeEncoding;
 
@@ -28,5 +27,5 @@
   public interface ISymbolicDataAnalysisExpressionTreeInterpreter : INamedItem, IStatefulItem {
     IEnumerable<double> GetSymbolicExpressionTreeValues(ISymbolicExpressionTree tree, IDataset dataset, IEnumerable<int> rows);
-    IntValue EvaluatedSolutions { get; set; }
+    int EvaluatedSolutions { get; set; }
   }
 }
Index: /stable/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/Interpreter/SymbolicDataAnalysisExpressionCompiledTreeInterpreter.cs
===================================================================
--- /stable/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/Interpreter/SymbolicDataAnalysisExpressionCompiledTreeInterpreter.cs	(revision 14811)
+++ /stable/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/Interpreter/SymbolicDataAnalysisExpressionCompiledTreeInterpreter.cs	(revision 14811)
@@ -0,0 +1,640 @@
+﻿#region License Information
+/* HeuristicLab
+ * Copyright (C) 2002-2015 Heuristic and Evolutionary Algorithms Laboratory (HEAL)
+ *
+ * This file is part of HeuristicLab.
+ *
+ * HeuristicLab is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * HeuristicLab is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with HeuristicLab. If not, see <http://www.gnu.org/licenses/>.
+ */
+#endregion
+
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Linq.Expressions;
+using System.Reflection;
+using HeuristicLab.Common;
+using HeuristicLab.Core;
+using HeuristicLab.Data;
+using HeuristicLab.Encodings.SymbolicExpressionTreeEncoding;
+using HeuristicLab.Parameters;
+using HeuristicLab.Persistence.Default.CompositeSerializers.Storable;
+
+namespace HeuristicLab.Problems.DataAnalysis.Symbolic {
+  [StorableClass]
+  [Item("SymbolicDataAnalysisExpressionCompiledTreeInterpreter", "Interpreter that converts the tree into a Linq.Expression then compiles it.")]
+  public sealed class SymbolicDataAnalysisExpressionCompiledTreeInterpreter : ParameterizedNamedItem, ISymbolicDataAnalysisExpressionTreeInterpreter {
+    private const string CheckExpressionsWithIntervalArithmeticParameterName = "CheckExpressionsWithIntervalArithmetic";
+    private const string CheckExpressionsWithIntervalArithmeticParameterDescription = "Switch that determines if the interpreter checks the validity of expressions with interval arithmetic before evaluating the expression.";
+    private const string EvaluatedSolutionsParameterName = "EvaluatedSolutions";
+
+    #region method info for the commonly called functions
+    private static readonly MethodInfo Sin = typeof(Math).GetMethod("Sin", new[] { typeof(double) });
+    private static readonly MethodInfo Cos = typeof(Math).GetMethod("Cos", new[] { typeof(double) });
+    private static readonly MethodInfo Tan = typeof(Math).GetMethod("Tan", new[] { typeof(double) });
+    private static readonly MethodInfo Sqrt = typeof(Math).GetMethod("Sqrt", new[] { typeof(double) });
+    private static readonly MethodInfo Floor = typeof(Math).GetMethod("Floor", new[] { typeof(double) });
+    private static readonly MethodInfo Round = typeof(Math).GetMethod("Round", new[] { typeof(double) });
+    private static readonly MethodInfo Exp = typeof(Math).GetMethod("Exp", new[] { typeof(double) });
+    private static readonly MethodInfo Log = typeof(Math).GetMethod("Log", new[] { typeof(double) });
+    private static readonly MethodInfo IsNaN = typeof(double).GetMethod("IsNaN");
+    private static readonly MethodInfo IsAlmost = typeof(DoubleExtensions).GetMethod("IsAlmost");
+    private static readonly MethodInfo Gamma = typeof(alglib).GetMethod("gammafunction", new[] { typeof(double) });
+    private static readonly MethodInfo Psi = typeof(alglib).GetMethod("psi", new[] { typeof(double) });
+    private static readonly MethodInfo DawsonIntegral = typeof(alglib).GetMethod("dawsonintegral", new[] { typeof(double) });
+    private static readonly MethodInfo ExponentialIntegralEi = typeof(alglib).GetMethod("exponentialintegralei", new[] { typeof(double) });
+    private static readonly MethodInfo SineCosineIntegrals = typeof(alglib).GetMethod("sinecosineintegrals", new[] { typeof(double), typeof(double).MakeByRefType(), typeof(double).MakeByRefType() });
+    private static readonly MethodInfo HyperbolicSineCosineIntegrals = typeof(alglib).GetMethod("hyperbolicsinecosineintegrals", new[] { typeof(double), typeof(double).MakeByRefType(), typeof(double).MakeByRefType() });
+    private static readonly MethodInfo FresnelIntegral = typeof(alglib).GetMethod("fresnelintegral", new[] { typeof(double), typeof(double).MakeByRefType(), typeof(double).MakeByRefType() });
+    private static readonly MethodInfo Airy = typeof(alglib).GetMethod("airy", new[] { typeof(double), typeof(double).MakeByRefType(), typeof(double).MakeByRefType(), typeof(double).MakeByRefType(), typeof(double).MakeByRefType() });
+    private static readonly MethodInfo NormalDistribution = typeof(alglib).GetMethod("normaldistribution", new[] { typeof(double) });
+    private static readonly MethodInfo ErrorFunction = typeof(alglib).GetMethod("errorfunction", new[] { typeof(double) });
+    private static readonly MethodInfo Bessel = typeof(alglib).GetMethod("besseli0", new[] { typeof(double) });
+    #endregion
+
+    public override bool CanChangeName { get { return false; } }
+    public override bool CanChangeDescription { get { return false; } }
+
+    #region parameter properties
+    public IFixedValueParameter<BoolValue> CheckExpressionsWithIntervalArithmeticParameter {
+      get { return (IFixedValueParameter<BoolValue>)Parameters[CheckExpressionsWithIntervalArithmeticParameterName]; }
+    }
+
+    public IFixedValueParameter<IntValue> EvaluatedSolutionsParameter {
+      get { return (IFixedValueParameter<IntValue>)Parameters[EvaluatedSolutionsParameterName]; }
+    }
+    #endregion
+
+    #region properties
+    public bool CheckExpressionsWithIntervalArithmetic {
+      get { return CheckExpressionsWithIntervalArithmeticParameter.Value.Value; }
+      set { CheckExpressionsWithIntervalArithmeticParameter.Value.Value = value; }
+    }
+    public int EvaluatedSolutions {
+      get { return EvaluatedSolutionsParameter.Value.Value; }
+      set { EvaluatedSolutionsParameter.Value.Value = value; }
+    }
+    #endregion
+
+    public override IDeepCloneable Clone(Cloner cloner) {
+      return new SymbolicDataAnalysisExpressionCompiledTreeInterpreter(this, cloner);
+    }
+
+    private SymbolicDataAnalysisExpressionCompiledTreeInterpreter(SymbolicDataAnalysisExpressionCompiledTreeInterpreter original, Cloner cloner)
+      : base(original, cloner) {
+    }
+
+    [StorableConstructor]
+    private SymbolicDataAnalysisExpressionCompiledTreeInterpreter(bool deserializing)
+      : base(deserializing) {
+    }
+
+    public SymbolicDataAnalysisExpressionCompiledTreeInterpreter() :
+      base("SymbolicDataAnalysisExpressionCompiledTreeInterpreter", "Interpreter which compiles the tree into a lambda") {
+      Parameters.Add(new FixedValueParameter<BoolValue>(CheckExpressionsWithIntervalArithmeticParameterName, CheckExpressionsWithIntervalArithmeticParameterDescription, new BoolValue(false)));
+      Parameters.Add(new FixedValueParameter<IntValue>(EvaluatedSolutionsParameterName, "A counter for the total number of solutions the interpreter has evaluated", new IntValue(0)));
+    }
+
+    public SymbolicDataAnalysisExpressionCompiledTreeInterpreter(string name, string description) :
+      base(name, description) {
+      Parameters.Add(new FixedValueParameter<BoolValue>(CheckExpressionsWithIntervalArithmeticParameterName, CheckExpressionsWithIntervalArithmeticParameterDescription, new BoolValue(false)));
+      Parameters.Add(new FixedValueParameter<IntValue>(EvaluatedSolutionsParameterName, "A counter for the total number of solutions the interpreter has evaluated", new IntValue(0)));
+    }
+
+    public void InitializeState() {
+      EvaluatedSolutions = 0;
+    }
+
+    public void ClearState() { }
+
+    private readonly object syncRoot = new object();
+    public IEnumerable<double> GetSymbolicExpressionTreeValues(ISymbolicExpressionTree tree, IDataset dataset, IEnumerable<int> rows) {
+      if (CheckExpressionsWithIntervalArithmetic)
+        throw new NotSupportedException("Interval arithmetic is not yet supported in the symbolic data analysis interpreter.");
+
+      lock (syncRoot) {
+        EvaluatedSolutions++; // increment the evaluated solutions counter
+      }
+      var columns = dataset.DoubleVariables.Select(x => (IList<double>)dataset.GetReadOnlyDoubleValues(x)).ToArray();
+      var compiled = CompileTree(tree, dataset);
+      return rows.Select(x => compiled(x, columns));
+    }
+
+    public static Func<int, IList<double>[], double> CompileTree(ISymbolicExpressionTree tree, IDataset dataset) {
+      var lambda = CreateDelegate(tree, dataset);
+      return lambda.Compile();
+    }
+
+    public static Expression<Func<int, IList<double>[], double>> CreateDelegate(ISymbolicExpressionTree tree, IDataset dataset) {
+      var row = Expression.Parameter(typeof(int));
+      var columns = Expression.Parameter(typeof(IList<double>[]));
+      var variableIndices = dataset.DoubleVariables.Select((x, i) => new { x, i }).ToDictionary(e => e.x, e => e.i);
+      var expr = MakeExpr(tree, variableIndices, row, columns);
+      var lambda = Expression.Lambda<Func<int, IList<double>[], double>>(expr, row, columns);
+      return lambda;
+    }
+
+    private static Expression MakeExpr(ISymbolicExpressionTree tree, Dictionary<string, int> variableIndices, Expression row, Expression columns) {
+      var actualRoot = tree.Root.GetSubtree(0).GetSubtree(0);
+      return MakeExpr(actualRoot, variableIndices, row, columns);
+    }
+
+    private static readonly PropertyInfo Indexer = typeof(IList<double>).GetProperty("Item");
+    private static Expression MakeExpr(ISymbolicExpressionTreeNode node, Dictionary<string, int> variableIndices, Expression row, Expression columns) {
+      var opcode = OpCodes.MapSymbolToOpCode(node);
+      #region switch opcode
+      switch (opcode) {
+        case OpCodes.Constant: {
+            var constantTreeNode = (ConstantTreeNode)node;
+            return Expression.Constant(constantTreeNode.Value);
+          }
+        case OpCodes.Variable: {
+            var variableTreeNode = (VariableTreeNode)node;
+            var variableWeight = Expression.Constant(variableTreeNode.Weight);
+            var variableName = variableTreeNode.VariableName;
+            var indexExpr = Expression.Constant(variableIndices[variableName]);
+            var valuesExpr = Expression.ArrayIndex(columns, indexExpr);
+            return Expression.Multiply(variableWeight, Expression.Property(valuesExpr, Indexer, row));
+          }
+        case OpCodes.Add: {
+            Expression result = MakeExpr(node.GetSubtree(0), variableIndices, row, columns);
+            for (int i = 1; i < node.SubtreeCount; ++i) {
+              result = Expression.Add(result, MakeExpr(node.GetSubtree(i), variableIndices, row, columns));
+            }
+            return result;
+          }
+        case OpCodes.Sub: {
+            Expression result = MakeExpr(node.GetSubtree(0), variableIndices, row, columns);
+            if (node.SubtreeCount == 1)
+              return Expression.Negate(result);
+            for (int i = 1; i < node.SubtreeCount; ++i) {
+              result = Expression.Subtract(result, MakeExpr(node.GetSubtree(i), variableIndices, row, columns));
+            }
+            return result;
+          }
+        case OpCodes.Mul: {
+            Expression result = MakeExpr(node.GetSubtree(0), variableIndices, row, columns);
+            for (int i = 1; i < node.SubtreeCount; ++i) {
+              result = Expression.Multiply(result, MakeExpr(node.GetSubtree(i), variableIndices, row, columns));
+            }
+            return result;
+          }
+        case OpCodes.Div: {
+            Expression result = MakeExpr(node.GetSubtree(0), variableIndices, row, columns);
+            if (node.SubtreeCount == 1)
+              return Expression.Divide(Expression.Constant(1.0), result);
+            for (int i = 1; i < node.SubtreeCount; ++i) {
+              result = Expression.Divide(result, MakeExpr(node.GetSubtree(i), variableIndices, row, columns));
+            }
+            return result;
+          }
+        case OpCodes.Average: {
+            Expression result = MakeExpr(node.GetSubtree(0), variableIndices, row, columns);
+            for (int i = 1; i < node.SubtreeCount; ++i) {
+              result = Expression.Add(result, MakeExpr(node.GetSubtree(i), variableIndices, row, columns));
+            }
+            return Expression.Divide(result, Expression.Constant((double)node.SubtreeCount));
+          }
+        case OpCodes.Cos: {
+            var arg = MakeExpr(node.GetSubtree(0), variableIndices, row, columns);
+            return Expression.Call(Cos, arg);
+          }
+        case OpCodes.Sin: {
+            var arg = MakeExpr(node.GetSubtree(0), variableIndices, row, columns);
+            return Expression.Call(Sin, arg);
+          }
+        case OpCodes.Tan: {
+            var arg = MakeExpr(node.GetSubtree(0), variableIndices, row, columns);
+            return Expression.Call(Tan, arg);
+          }
+        case OpCodes.Square: {
+            var arg = MakeExpr(node.GetSubtree(0), variableIndices, row, columns);
+            return Expression.Power(arg, Expression.Constant(2.0));
+          }
+        case OpCodes.Power: {
+            var arg = MakeExpr(node.GetSubtree(0), variableIndices, row, columns);
+            var power = MakeExpr(node.GetSubtree(1), variableIndices, row, columns);
+            return Expression.Power(arg, Expression.Call(Round, power));
+          }
+        case OpCodes.SquareRoot: {
+            var arg = MakeExpr(node.GetSubtree(0), variableIndices, row, columns);
+            return Expression.Call(Sqrt, arg);
+          }
+        case OpCodes.Root: {
+            var arg = MakeExpr(node.GetSubtree(0), variableIndices, row, columns);
+            var power = MakeExpr(node.GetSubtree(1), variableIndices, row, columns);
+            return Expression.Power(arg, Expression.Divide(Expression.Constant(1.0), Expression.Call(Round, power)));
+          }
+        case OpCodes.Exp: {
+            var arg = MakeExpr(node.GetSubtree(0), variableIndices, row, columns);
+            return Expression.Call(Exp, arg);
+          }
+        case OpCodes.Log: {
+            var arg = MakeExpr(node.GetSubtree(0), variableIndices, row, columns);
+            return Expression.Call(Log, arg);
+          }
+        case OpCodes.Gamma: {
+            var arg = MakeExpr(node.GetSubtree(0), variableIndices, row, columns);
+            var isNaN = Expression.Call(IsNaN, arg);
+
+            var result = Expression.Variable(typeof(double));
+            var expr = Expression.Block(
+              new[] { result },
+              Expression.IfThenElse(
+                isNaN,
+                Expression.Assign(result, Expression.Constant(double.NaN)),
+                Expression.Assign(result, Expression.Call(Gamma, arg))
+                ),
+              result
+              );
+            return expr;
+          }
+        case OpCodes.Psi: {
+            var arg = MakeExpr(node.GetSubtree(0), variableIndices, row, columns);
+            var isNaN = Expression.Call(IsNaN, arg);
+
+            var result = Expression.Variable(typeof(double));
+            var floor = Expression.Call(Floor, arg);
+            var expr = Expression.Block(
+              new[] { result },
+              Expression.IfThenElse(
+                isNaN,
+                Expression.Assign(result, Expression.Constant(double.NaN)),
+                Expression.IfThenElse(
+                  Expression.AndAlso(
+                    Expression.LessThanOrEqual(arg, Expression.Constant(0.0)),
+                    Expression.Call(IsAlmost, Expression.Subtract(floor, arg), Expression.Constant(0.0))),
+                  Expression.Assign(result, Expression.Constant(double.NaN)),
+                  Expression.Assign(result, Expression.Call(Psi, arg)))
+                ),
+              result);
+
+            return expr;
+          }
+        case OpCodes.Dawson: {
+            var arg = MakeExpr(node.GetSubtree(0), variableIndices, row, columns);
+            var isNaN = Expression.Call(IsNaN, arg);
+            var result = Expression.Variable(typeof(double));
+            var expr = Expression.Block(
+              new[] { result },
+              Expression.IfThenElse(isNaN,
+                Expression.Assign(result, Expression.Constant(double.NaN)),
+                Expression.Assign(result, Expression.Call(DawsonIntegral, arg))),
+              result
+              );
+
+            return expr;
+          }
+        case OpCodes.ExponentialIntegralEi: {
+            var arg = MakeExpr(node.GetSubtree(0), variableIndices, row, columns);
+            var isNaN = Expression.Call(IsNaN, arg);
+            var result = Expression.Variable(typeof(double));
+            var expr = Expression.Block(
+              new[] { result },
+              Expression.IfThenElse(isNaN,
+                Expression.Assign(result, Expression.Constant(double.NaN)),
+                Expression.Assign(result, Expression.Call(ExponentialIntegralEi, arg))),
+              result
+              );
+
+            return expr;
+          }
+        case OpCodes.SineIntegral: {
+            var arg = MakeExpr(node.GetSubtree(0), variableIndices, row, columns);
+            var isNaN = Expression.Call(IsNaN, arg);
+            var si = Expression.Variable(typeof(double));
+            var ci = Expression.Variable(typeof(double));
+            var block = Expression.Block(
+              new[] { si, ci },
+              Expression.Call(SineCosineIntegrals, arg, si, ci),
+              si
+              );
+            var result = Expression.Variable(typeof(double));
+            var expr = Expression.Block(new[] { result },
+              Expression.IfThenElse(isNaN,
+                Expression.Assign(result, Expression.Constant(double.NaN)),
+                Expression.Assign(result, block)),
+              result
+              );
+
+            return expr;
+          }
+        case OpCodes.CosineIntegral: {
+            var arg = MakeExpr(node.GetSubtree(0), variableIndices, row, columns);
+            var isNaN = Expression.Call(IsNaN, arg);
+            var si = Expression.Variable(typeof(double));
+            var ci = Expression.Variable(typeof(double));
+            var block = Expression.Block(
+              new[] { si, ci },
+              Expression.Call(SineCosineIntegrals, arg, si, ci),
+              ci
+              );
+            var result = Expression.Variable(typeof(double));
+            var expr = Expression.Block(new[] { result },
+              Expression.IfThenElse(isNaN,
+                Expression.Assign(result, Expression.Constant(double.NaN)),
+                Expression.Assign(result, block)),
+              result
+              );
+
+            return expr;
+          }
+        case OpCodes.HyperbolicSineIntegral: {
+            var arg = MakeExpr(node.GetSubtree(0), variableIndices, row, columns);
+            var isNaN = Expression.Call(IsNaN, arg);
+            var shi = Expression.Variable(typeof(double));
+            var chi = Expression.Variable(typeof(double));
+            var block = Expression.Block(
+              new[] { shi, chi },
+              Expression.Call(HyperbolicSineCosineIntegrals, arg, shi, chi),
+              shi
+              );
+            var result = Expression.Variable(typeof(double));
+            var expr = Expression.Block(new[] { result },
+              Expression.IfThenElse(isNaN,
+                Expression.Assign(result, Expression.Constant(double.NaN)),
+                Expression.Assign(result, block)),
+              result
+              );
+
+            return expr;
+          }
+        case OpCodes.HyperbolicCosineIntegral: {
+            var arg = MakeExpr(node.GetSubtree(0), variableIndices, row, columns);
+            var isNaN = Expression.Call(IsNaN, arg);
+            var shi = Expression.Variable(typeof(double));
+            var chi = Expression.Variable(typeof(double));
+            var block = Expression.Block(
+              new[] { shi, chi },
+              Expression.Call(HyperbolicSineCosineIntegrals, arg, shi, chi),
+              chi
+              );
+            var result = Expression.Variable(typeof(double));
+            var expr = Expression.Block(new[] { result },
+              Expression.IfThenElse(isNaN,
+                Expression.Assign(result, Expression.Constant(double.NaN)),
+                Expression.Assign(result, block)),
+              result
+              );
+
+            return expr;
+          }
+        case OpCodes.FresnelSineIntegral: {
+            var arg = MakeExpr(node.GetSubtree(0), variableIndices, row, columns);
+            var isNaN = Expression.Call(IsNaN, arg);
+            var s = Expression.Variable(typeof(double));
+            var c = Expression.Variable(typeof(double));
+            var block = Expression.Block(new[] { s, c }, Expression.Call(FresnelIntegral, arg, c, s), s);
+            var result = Expression.Variable(typeof(double));
+            var expr = Expression.Block(new[] { result },
+              Expression.IfThenElse(isNaN,
+                Expression.Assign(result, Expression.Constant(double.NaN)),
+                Expression.Assign(result, block)),
+              result
+              );
+
+            return expr;
+          }
+        case OpCodes.FresnelCosineIntegral: {
+            var arg = MakeExpr(node.GetSubtree(0), variableIndices, row, columns);
+            var isNaN = Expression.Call(IsNaN, arg);
+            var s = Expression.Variable(typeof(double));
+            var c = Expression.Variable(typeof(double));
+            var block = Expression.Block(new[] { s, c }, Expression.Call(FresnelIntegral, arg, c, s), c);
+            var result = Expression.Variable(typeof(double));
+            var expr = Expression.Block(new[] { result },
+              Expression.IfThenElse(isNaN,
+                Expression.Assign(result, Expression.Constant(double.NaN)),
+                Expression.Assign(result, block)),
+              result
+              );
+
+            return expr;
+          }
+        case OpCodes.AiryA: {
+            var arg = MakeExpr(node.GetSubtree(0), variableIndices, row, columns);
+            var isNaN = Expression.Call(IsNaN, arg);
+            var ai = Expression.Variable(typeof(double));
+            var aip = Expression.Variable(typeof(double));
+            var bi = Expression.Variable(typeof(double));
+            var bip = Expression.Variable(typeof(double));
+            var block = Expression.Block(new[] { ai, aip, bi, bip }, Expression.Call(Airy, arg, ai, aip, bi, bip), ai);
+            var result = Expression.Variable(typeof(double));
+            var expr = Expression.Block(new[] { result },
+              Expression.IfThenElse(isNaN,
+                Expression.Assign(result, Expression.Constant(double.NaN)),
+                Expression.Assign(result, block)),
+              result
+              );
+
+            return expr;
+          }
+        case OpCodes.AiryB: {
+            var arg = MakeExpr(node.GetSubtree(0), variableIndices, row, columns);
+            var isNaN = Expression.Call(IsNaN, arg);
+            var ai = Expression.Variable(typeof(double));
+            var aip = Expression.Variable(typeof(double));
+            var bi = Expression.Variable(typeof(double));
+            var bip = Expression.Variable(typeof(double));
+            var block = Expression.Block(new[] { ai, aip, bi, bip }, Expression.Call(Airy, arg, ai, aip, bi, bip), bi);
+            var result = Expression.Variable(typeof(double));
+            var expr = Expression.Block(new[] { result },
+              Expression.IfThenElse(isNaN,
+                Expression.Assign(result, Expression.Constant(double.NaN)),
+                Expression.Assign(result, block)),
+              result
+              );
+
+            return expr;
+          }
+        case OpCodes.Norm: {
+            var arg = MakeExpr(node.GetSubtree(0), variableIndices, row, columns);
+            var result = Expression.Variable(typeof(double));
+            return Expression.Block(
+              new[] { result },
+              Expression.IfThenElse(
+                Expression.Call(IsNaN, arg),
+                Expression.Assign(result, arg),
+                Expression.Assign(result, Expression.Call(NormalDistribution, arg))),
+              result);
+          }
+        case OpCodes.Erf: {
+            var arg = MakeExpr(node.GetSubtree(0), variableIndices, row, columns);
+            var isNaN = Expression.Call(IsNaN, arg);
+            var result = Expression.Variable(typeof(double));
+            return Expression.Block(
+              new[] { result },
+              Expression.IfThenElse(
+                isNaN,
+                Expression.Assign(result, Expression.Constant(double.NaN)),
+                Expression.Assign(result, Expression.Call(ErrorFunction, arg))),
+              result);
+          }
+        case OpCodes.Bessel: {
+            var arg = MakeExpr(node.GetSubtree(0), variableIndices, row, columns);
+            var isNaN = Expression.Call(IsNaN, arg);
+            var result = Expression.Variable(typeof(double));
+            return Expression.Block(
+              new[] { result },
+              Expression.IfThenElse(
+                isNaN,
+                Expression.Assign(result, Expression.Constant(double.NaN)),
+                Expression.Assign(result, Expression.Call(Bessel, arg))),
+              result);
+          }
+        case OpCodes.IfThenElse: {
+            var test = MakeExpr(node.GetSubtree(0), variableIndices, row, columns);
+            var result = Expression.Variable(typeof(double));
+            var condition = Expression.IfThenElse(Expression.GreaterThan(test, Expression.Constant(0.0)),
+              Expression.Assign(result, MakeExpr(node.GetSubtree(1), variableIndices, row, columns)),
+              Expression.Assign(result, MakeExpr(node.GetSubtree(2), variableIndices, row, columns)));
+            return Expression.Block(new[] { result }, condition, result);
+          }
+        case OpCodes.AND: {
+            var result = Expression.Variable(typeof(double));
+            var expr = MakeExpr(node.GetSubtree(0), variableIndices, row, columns);
+
+            for (int i = 1; i < node.SubtreeCount; ++i) {
+              expr = Expression.Block(new[] { result },
+                Expression.IfThenElse(
+                  Expression.GreaterThan(expr, Expression.Constant(0.0)),
+                  Expression.Assign(result, MakeExpr(node.GetSubtree(i), variableIndices, row, columns)),
+                  Expression.Assign(result, expr)),
+                result
+                );
+            }
+
+            return Expression.Block(
+              new[] { result },
+              Expression.Assign(result, expr),
+              Expression.IfThenElse(
+                Expression.GreaterThan(result, Expression.Constant(0.0)),
+                Expression.Assign(result, Expression.Constant(1.0)),
+                Expression.Assign(result, Expression.Constant(-1.0))
+                ),
+              result
+              );
+          }
+        case OpCodes.OR: {
+            var result = Expression.Variable(typeof(double));
+            var expr = MakeExpr(node.GetSubtree(0), variableIndices, row, columns);
+
+            for (int i = 1; i < node.SubtreeCount; ++i) {
+              expr = Expression.Block(new[] { result },
+                Expression.IfThenElse(
+                  Expression.LessThanOrEqual(expr, Expression.Constant(0.0)),
+                  Expression.Assign(result, MakeExpr(node.GetSubtree(i), variableIndices, row, columns)),
+                  Expression.Assign(result, expr)),
+                result
+                );
+            }
+
+            return Expression.Block(
+              new[] { result },
+              Expression.Assign(result, expr),
+              Expression.IfThenElse(
+                Expression.GreaterThan(result, Expression.Constant(0.0)),
+                Expression.Assign(result, Expression.Constant(1.0)),
+                Expression.Assign(result, Expression.Constant(-1.0))
+                ),
+              result
+              );
+          }
+        case OpCodes.NOT: {
+            var value = MakeExpr(node.GetSubtree(0), variableIndices, row, columns);
+            var result = Expression.Variable(typeof(double));
+            var condition = Expression.IfThenElse(Expression.GreaterThan(value, Expression.Constant(0.0)),
+              Expression.Assign(result, Expression.Constant(-1.0)),
+              Expression.Assign(result, Expression.Constant(1.0)));
+            return Expression.Block(new[] { result }, condition, result);
+          }
+        case OpCodes.XOR: {
+            var ps = Expression.Variable(typeof(int));
+            var block = Expression.Block(
+              new[] { ps },
+              Expression.Assign(ps, Expression.Constant(0)),
+              ps
+              );
+
+            foreach (var subtree in node.Subtrees) {
+              var expr = MakeExpr(subtree, variableIndices, row, columns);
+              block = Expression.Block(
+                new[] { ps },
+                Expression.Assign(ps, block),
+                Expression.IfThen(Expression.GreaterThan(expr, Expression.Constant(0.0)),
+                  Expression.PostIncrementAssign(ps)),
+                ps
+                );
+            }
+
+            var result = Expression.Variable(typeof(double));
+            var xorExpr = Expression.Block(
+              new[] { result },
+              Expression.IfThenElse(
+                Expression.Equal(Expression.Modulo(block, Expression.Constant(2)), Expression.Constant(0)),
+                Expression.Assign(result, Expression.Constant(-1.0)),
+                Expression.Assign(result, Expression.Constant(1.0))
+                ),
+              result
+              );
+            return xorExpr;
+          }
+        case OpCodes.GT: {
+            var left = MakeExpr(node.GetSubtree(0), variableIndices, row, columns);
+            var right = MakeExpr(node.GetSubtree(1), variableIndices, row, columns);
+            var result = Expression.Variable(typeof(double));
+
+            var condition = Expression.IfThenElse(Expression.GreaterThan(left, right),
+              Expression.Assign(result, Expression.Constant(1.0)), Expression.Assign(result, Expression.Constant(-1.0)));
+            return Expression.Block(
+              new[] { result },
+              condition,
+              result);
+          }
+        case OpCodes.LT: {
+            var left = MakeExpr(node.GetSubtree(0), variableIndices, row, columns);
+            var right = MakeExpr(node.GetSubtree(1), variableIndices, row, columns);
+            var result = Expression.Variable(typeof(double));
+
+            var condition = Expression.IfThenElse(Expression.LessThan(left, right),
+              Expression.Assign(result, Expression.Constant(1.0)), Expression.Assign(result, Expression.Constant(-1.0)));
+            return Expression.Block(new[] { result }, condition, result);
+          }
+        case OpCodes.VariableCondition: {
+            var variableConditionTreeNode = (VariableConditionTreeNode)node;
+            var variableName = variableConditionTreeNode.VariableName;
+            var indexExpr = Expression.Constant(variableIndices[variableName]);
+            var valuesExpr = Expression.ArrayIndex(columns, indexExpr);
+            var variableValue = Expression.Property(valuesExpr, Indexer, row);
+            var variableThreshold = Expression.Constant(variableConditionTreeNode.Threshold);
+            var variableSlope = Expression.Constant(variableConditionTreeNode.Slope);
+
+            var x = Expression.Subtract(variableValue, variableThreshold);
+            var xSlope = Expression.Multiply(Expression.Negate(variableSlope), x);
+            var xSlopeExp = Expression.Call(Exp, xSlope);
+            var p = Expression.Divide(Expression.Constant(1), Expression.Add(Expression.Constant(1), xSlopeExp));
+            var trueBranch = MakeExpr(node.GetSubtree(0), variableIndices, row, columns);
+            var falseBranch = MakeExpr(node.GetSubtree(1), variableIndices, row, columns);
+            return Expression.Add(
+              Expression.Multiply(trueBranch, p),
+              Expression.Multiply(falseBranch, Expression.Subtract(Expression.Constant(1), p))
+              );
+          }
+        default:
+          throw new NotSupportedException("Unsupported symbol: " + node.Symbol);
+      }
+      #endregion
+    }
+  }
+}
Index: /stable/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/Interpreter/SymbolicDataAnalysisExpressionTreeILEmittingInterpreter.cs
===================================================================
--- /stable/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/Interpreter/SymbolicDataAnalysisExpressionTreeILEmittingInterpreter.cs	(revision 14810)
+++ /stable/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/Interpreter/SymbolicDataAnalysisExpressionTreeILEmittingInterpreter.cs	(revision 14811)
@@ -69,4 +69,5 @@
 
     private const string CheckExpressionsWithIntervalArithmeticParameterName = "CheckExpressionsWithIntervalArithmetic";
+    private const string CheckExpressionsWithIntervalArithmeticParameterDescription = "Switch that determines if the interpreter checks the validity of expressions with interval arithmetic before evaluating the expression.";
     private const string EvaluatedSolutionsParameterName = "EvaluatedSolutions";
 
@@ -80,29 +81,23 @@
 
     #region parameter properties
-
-    public IValueParameter<BoolValue> CheckExpressionsWithIntervalArithmeticParameter {
-      get { return (IValueParameter<BoolValue>)Parameters[CheckExpressionsWithIntervalArithmeticParameterName]; }
-    }
-
-    public IValueParameter<IntValue> EvaluatedSolutionsParameter {
-      get { return (IValueParameter<IntValue>)Parameters[EvaluatedSolutionsParameterName]; }
-    }
-
+    public IFixedValueParameter<BoolValue> CheckExpressionsWithIntervalArithmeticParameter {
+      get { return (IFixedValueParameter<BoolValue>)Parameters[CheckExpressionsWithIntervalArithmeticParameterName]; }
+    }
+
+    public IFixedValueParameter<IntValue> EvaluatedSolutionsParameter {
+      get { return (IFixedValueParameter<IntValue>)Parameters[EvaluatedSolutionsParameterName]; }
+    }
     #endregion
 
     #region properties
-
-    public BoolValue CheckExpressionsWithIntervalArithmetic {
-      get { return CheckExpressionsWithIntervalArithmeticParameter.Value; }
-      set { CheckExpressionsWithIntervalArithmeticParameter.Value = value; }
-    }
-
-    public IntValue EvaluatedSolutions {
-      get { return EvaluatedSolutionsParameter.Value; }
-      set { EvaluatedSolutionsParameter.Value = value; }
-    }
-
+    public bool CheckExpressionsWithIntervalArithmetic {
+      get { return CheckExpressionsWithIntervalArithmeticParameter.Value.Value; }
+      set { CheckExpressionsWithIntervalArithmeticParameter.Value.Value = value; }
+    }
+    public int EvaluatedSolutions {
+      get { return EvaluatedSolutionsParameter.Value.Value; }
+      set { EvaluatedSolutionsParameter.Value.Value = value; }
+    }
     #endregion
-
 
     [StorableConstructor]
@@ -116,31 +111,51 @@
     public SymbolicDataAnalysisExpressionTreeILEmittingInterpreter()
       : base("SymbolicDataAnalysisExpressionTreeILEmittingInterpreter", "Interpreter for symbolic expression trees.") {
-      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)));
-      Parameters.Add(new ValueParameter<IntValue>(EvaluatedSolutionsParameterName, "A counter for the total number of solutions the interpreter has evaluated", new IntValue(0)));
+      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)));
+      Parameters.Add(new FixedValueParameter<IntValue>(EvaluatedSolutionsParameterName, "A counter for the total number of solutions the interpreter has evaluated", new IntValue(0)));
+    }
+
+    public SymbolicDataAnalysisExpressionTreeILEmittingInterpreter(string name, string description)
+      : base(name, description) {
+      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)));
+      Parameters.Add(new FixedValueParameter<IntValue>(EvaluatedSolutionsParameterName, "A counter for the total number of solutions the interpreter has evaluated", new IntValue(0)));
     }
 
     [StorableHook(HookType.AfterDeserialization)]
     private void AfterDeserialization() {
-      if (!Parameters.ContainsKey(EvaluatedSolutionsParameterName))
-        Parameters.Add(new ValueParameter<IntValue>(EvaluatedSolutionsParameterName, "A counter for the total number of solutions the interpreter has evaluated", new IntValue(0)));
+      var evaluatedSolutions = new IntValue(0);
+      var checkExpressionsWithIntervalArithmetic = new BoolValue(false);
+      if (Parameters.ContainsKey(EvaluatedSolutionsParameterName)) {
+        var evaluatedSolutionsParameter = (IValueParameter<IntValue>)Parameters[EvaluatedSolutionsParameterName];
+        evaluatedSolutions = evaluatedSolutionsParameter.Value;
+        Parameters.Remove(EvaluatedSolutionsParameterName);
+      }
+      Parameters.Add(new FixedValueParameter<IntValue>(EvaluatedSolutionsParameterName, "A counter for the total number of solutions the interpreter has evaluated", evaluatedSolutions));
+      if (Parameters.ContainsKey(CheckExpressionsWithIntervalArithmeticParameterName)) {
+        var checkExpressionsWithIntervalArithmeticParameter = (IValueParameter<BoolValue>)Parameters[CheckExpressionsWithIntervalArithmeticParameterName];
+        Parameters.Remove(CheckExpressionsWithIntervalArithmeticParameterName);
+        checkExpressionsWithIntervalArithmetic = checkExpressionsWithIntervalArithmeticParameter.Value;
+      }
+      Parameters.Add(new FixedValueParameter<BoolValue>(CheckExpressionsWithIntervalArithmeticParameterName, CheckExpressionsWithIntervalArithmeticParameterDescription, checkExpressionsWithIntervalArithmetic));
     }
 
     #region IStatefulItem
-
     public void InitializeState() {
-      EvaluatedSolutions.Value = 0;
+      EvaluatedSolutions = 0;
     }
 
     public void ClearState() {
-      EvaluatedSolutions.Value = 0;
-    }
-
+    }
     #endregion
 
+    private readonly object syncRoot = new object();
     public IEnumerable<double> GetSymbolicExpressionTreeValues(ISymbolicExpressionTree tree, IDataset dataset, IEnumerable<int> rows) {
-      if (CheckExpressionsWithIntervalArithmetic.Value)
+      if (CheckExpressionsWithIntervalArithmetic)
         throw new NotSupportedException("Interval arithmetic is not yet supported in the symbolic data analysis interpreter.");
 
-      EvaluatedSolutions.Value++; // increment the evaluated solutions counter
+      lock (syncRoot) {
+        EvaluatedSolutions++; // increment the evaluated solutions counter
+      }
       var state = PrepareInterpreterState(tree, dataset);
 
@@ -244,5 +259,5 @@
               il.Emit(System.Reflection.Emit.OpCodes.Add);
             }
-            il.Emit(System.Reflection.Emit.OpCodes.Ldc_I4, nArgs);
+            il.Emit(System.Reflection.Emit.OpCodes.Ldc_R8, (double)nArgs);
             il.Emit(System.Reflection.Emit.OpCodes.Div);
             return;
@@ -442,4 +457,5 @@
             il.Emit(System.Reflection.Emit.OpCodes.Ldc_I4_0); // > 0
             il.Emit(System.Reflection.Emit.OpCodes.Cgt);
+            il.Emit(System.Reflection.Emit.OpCodes.Conv_R8); // convert to float64
             il.Emit(System.Reflection.Emit.OpCodes.Ldc_R8, 2.0); // * 2
             il.Emit(System.Reflection.Emit.OpCodes.Mul);
@@ -460,4 +476,6 @@
               il.Emit(System.Reflection.Emit.OpCodes.Xor);
             }
+            il.Emit(System.Reflection.Emit.OpCodes.Conv_R8); // convert to float64
+
             il.Emit(System.Reflection.Emit.OpCodes.Ldc_R8, 2.0); // * 2
             il.Emit(System.Reflection.Emit.OpCodes.Mul);
@@ -471,4 +489,5 @@
 
             il.Emit(System.Reflection.Emit.OpCodes.Cgt); // 1 (>) / 0 (otherwise)
+            il.Emit(System.Reflection.Emit.OpCodes.Conv_R8); // convert to float64
             il.Emit(System.Reflection.Emit.OpCodes.Ldc_R8, 2.0); // * 2
             il.Emit(System.Reflection.Emit.OpCodes.Mul);
@@ -481,4 +500,5 @@
             CompileInstructions(il, state, ds);
             il.Emit(System.Reflection.Emit.OpCodes.Clt);
+            il.Emit(System.Reflection.Emit.OpCodes.Conv_R8); // convert to float64
             il.Emit(System.Reflection.Emit.OpCodes.Ldc_R8, 2.0); // * 2
             il.Emit(System.Reflection.Emit.OpCodes.Mul);
Index: /stable/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/Interpreter/SymbolicDataAnalysisExpressionTreeInterpreter.cs
===================================================================
--- /stable/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/Interpreter/SymbolicDataAnalysisExpressionTreeInterpreter.cs	(revision 14810)
+++ /stable/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/Interpreter/SymbolicDataAnalysisExpressionTreeInterpreter.cs	(revision 14811)
@@ -32,30 +32,37 @@
   [StorableClass]
   [Item("SymbolicDataAnalysisExpressionTreeInterpreter", "Interpreter for symbolic expression trees including automatically defined functions.")]
-  public class SymbolicDataAnalysisExpressionTreeInterpreter : ParameterizedNamedItem, ISymbolicDataAnalysisExpressionTreeInterpreter {
+  public class SymbolicDataAnalysisExpressionTreeInterpreter : ParameterizedNamedItem,
+    ISymbolicDataAnalysisExpressionTreeInterpreter {
     private const string CheckExpressionsWithIntervalArithmeticParameterName = "CheckExpressionsWithIntervalArithmetic";
+    private const string CheckExpressionsWithIntervalArithmeticParameterDescription = "Switch that determines if the interpreter checks the validity of expressions with interval arithmetic before evaluating the expression.";
     private const string EvaluatedSolutionsParameterName = "EvaluatedSolutions";
 
-    public override bool CanChangeName { get { return false; } }
-    public override bool CanChangeDescription { get { return false; } }
+    public override bool CanChangeName {
+      get { return false; }
+    }
+
+    public override bool CanChangeDescription {
+      get { return false; }
+    }
 
     #region parameter properties
-    public IValueParameter<BoolValue> CheckExpressionsWithIntervalArithmeticParameter {
-      get { return (IValueParameter<BoolValue>)Parameters[CheckExpressionsWithIntervalArithmeticParameterName]; }
-    }
-
-    public IValueParameter<IntValue> EvaluatedSolutionsParameter {
-      get { return (IValueParameter<IntValue>)Parameters[EvaluatedSolutionsParameterName]; }
+    public IFixedValueParameter<BoolValue> CheckExpressionsWithIntervalArithmeticParameter {
+      get { return (IFixedValueParameter<BoolValue>)Parameters[CheckExpressionsWithIntervalArithmeticParameterName]; }
+    }
+
+    public IFixedValueParameter<IntValue> EvaluatedSolutionsParameter {
+      get { return (IFixedValueParameter<IntValue>)Parameters[EvaluatedSolutionsParameterName]; }
     }
     #endregion
 
     #region properties
-    public BoolValue CheckExpressionsWithIntervalArithmetic {
-      get { return CheckExpressionsWithIntervalArithmeticParameter.Value; }
-      set { CheckExpressionsWithIntervalArithmeticParameter.Value = value; }
-    }
-
-    public IntValue EvaluatedSolutions {
-      get { return EvaluatedSolutionsParameter.Value; }
-      set { EvaluatedSolutionsParameter.Value = value; }
+    public bool CheckExpressionsWithIntervalArithmetic {
+      get { return CheckExpressionsWithIntervalArithmeticParameter.Value.Value; }
+      set { CheckExpressionsWithIntervalArithmeticParameter.Value.Value = value; }
+    }
+
+    public int EvaluatedSolutions {
+      get { return EvaluatedSolutionsParameter.Value.Value; }
+      set { EvaluatedSolutionsParameter.Value.Value = value; }
     }
     #endregion
@@ -63,5 +70,9 @@
     [StorableConstructor]
     protected SymbolicDataAnalysisExpressionTreeInterpreter(bool deserializing) : base(deserializing) { }
-    protected SymbolicDataAnalysisExpressionTreeInterpreter(SymbolicDataAnalysisExpressionTreeInterpreter original, Cloner cloner) : base(original, cloner) { }
+
+    protected SymbolicDataAnalysisExpressionTreeInterpreter(SymbolicDataAnalysisExpressionTreeInterpreter original,
+      Cloner cloner)
+      : base(original, cloner) { }
+
     public override IDeepCloneable Clone(Cloner cloner) {
       return new SymbolicDataAnalysisExpressionTreeInterpreter(this, cloner);
@@ -70,35 +81,49 @@
     public SymbolicDataAnalysisExpressionTreeInterpreter()
       : base("SymbolicDataAnalysisExpressionTreeInterpreter", "Interpreter for symbolic expression trees including automatically defined functions.") {
-      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)));
-      Parameters.Add(new ValueParameter<IntValue>(EvaluatedSolutionsParameterName, "A counter for the total number of solutions the interpreter has evaluated", new IntValue(0)));
+      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)));
+      Parameters.Add(new FixedValueParameter<IntValue>(EvaluatedSolutionsParameterName, "A counter for the total number of solutions the interpreter has evaluated", new IntValue(0)));
     }
 
     protected SymbolicDataAnalysisExpressionTreeInterpreter(string name, string description)
       : base(name, description) {
-      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)));
-      Parameters.Add(new ValueParameter<IntValue>(EvaluatedSolutionsParameterName, "A counter for the total number of solutions the interpreter has evaluated", new IntValue(0)));
+      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)));
+      Parameters.Add(new FixedValueParameter<IntValue>(EvaluatedSolutionsParameterName, "A counter for the total number of solutions the interpreter has evaluated", new IntValue(0)));
     }
 
     [StorableHook(HookType.AfterDeserialization)]
     private void AfterDeserialization() {
-      if (!Parameters.ContainsKey(EvaluatedSolutionsParameterName))
-        Parameters.Add(new ValueParameter<IntValue>(EvaluatedSolutionsParameterName, "A counter for the total number of solutions the interpreter has evaluated", new IntValue(0)));
+      var evaluatedSolutions = new IntValue(0);
+      var checkExpressionsWithIntervalArithmetic = new BoolValue(false);
+      if (Parameters.ContainsKey(EvaluatedSolutionsParameterName)) {
+        var evaluatedSolutionsParameter = (IValueParameter<IntValue>)Parameters[EvaluatedSolutionsParameterName];
+        evaluatedSolutions = evaluatedSolutionsParameter.Value;
+        Parameters.Remove(EvaluatedSolutionsParameterName);
+      }
+      Parameters.Add(new FixedValueParameter<IntValue>(EvaluatedSolutionsParameterName, "A counter for the total number of solutions the interpreter has evaluated", evaluatedSolutions));
+      if (Parameters.ContainsKey(CheckExpressionsWithIntervalArithmeticParameterName)) {
+        var checkExpressionsWithIntervalArithmeticParameter = (IValueParameter<BoolValue>)Parameters[CheckExpressionsWithIntervalArithmeticParameterName];
+        Parameters.Remove(CheckExpressionsWithIntervalArithmeticParameterName);
+        checkExpressionsWithIntervalArithmetic = checkExpressionsWithIntervalArithmeticParameter.Value;
+      }
+      Parameters.Add(new FixedValueParameter<BoolValue>(CheckExpressionsWithIntervalArithmeticParameterName, CheckExpressionsWithIntervalArithmeticParameterDescription, checkExpressionsWithIntervalArithmetic));
     }
 
     #region IStatefulItem
     public void InitializeState() {
-      EvaluatedSolutions.Value = 0;
-    }
-
-    public void ClearState() {
-    }
+      EvaluatedSolutions = 0;
+    }
+
+    public void ClearState() { }
     #endregion
 
-    public IEnumerable<double> GetSymbolicExpressionTreeValues(ISymbolicExpressionTree tree, IDataset dataset, IEnumerable<int> rows) {
-      if (CheckExpressionsWithIntervalArithmetic.Value)
+    private readonly object syncRoot = new object();
+    public IEnumerable<double> GetSymbolicExpressionTreeValues(ISymbolicExpressionTree tree, IDataset dataset,
+      IEnumerable<int> rows) {
+      if (CheckExpressionsWithIntervalArithmetic) {
         throw new NotSupportedException("Interval arithmetic is not yet supported in the symbolic data analysis interpreter.");
-
-      lock (EvaluatedSolutions) {
-        EvaluatedSolutions.Value++; // increment the evaluated solutions counter
+      }
+
+      lock (syncRoot) {
+        EvaluatedSolutions++; // increment the evaluated solutions counter
       }
       var state = PrepareInterpreterState(tree, dataset);
@@ -131,5 +156,4 @@
     }
 
-
     public virtual double Evaluate(IDataset dataset, ref int row, InterpreterState state) {
       Instruction currentInstr = state.NextInstruction();
@@ -147,5 +171,5 @@
               s -= Evaluate(dataset, ref row, state);
             }
-            if (currentInstr.nArguments == 1) s = -s;
+            if (currentInstr.nArguments == 1) { s = -s; }
             return s;
           }
@@ -162,5 +186,5 @@
               p /= Evaluate(dataset, ref row, state);
             }
-            if (currentInstr.nArguments == 1) p = 1.0 / p;
+            if (currentInstr.nArguments == 1) { p = 1.0 / p; }
             return p;
           }
@@ -205,6 +229,5 @@
         case OpCodes.Gamma: {
             var x = Evaluate(dataset, ref row, state);
-            if (double.IsNaN(x)) return double.NaN;
-            else return alglib.gammafunction(x);
+            if (double.IsNaN(x)) { return double.NaN; } else { return alglib.gammafunction(x); }
           }
         case OpCodes.Psi: {
@@ -216,10 +239,10 @@
         case OpCodes.Dawson: {
             var x = Evaluate(dataset, ref row, state);
-            if (double.IsNaN(x)) return double.NaN;
+            if (double.IsNaN(x)) { return double.NaN; }
             return alglib.dawsonintegral(x);
           }
         case OpCodes.ExponentialIntegralEi: {
             var x = Evaluate(dataset, ref row, state);
-            if (double.IsNaN(x)) return double.NaN;
+            if (double.IsNaN(x)) { return double.NaN; }
             return alglib.exponentialintegralei(x);
           }
@@ -349,5 +372,5 @@
             int positiveSignals = 0;
             for (int i = 0; i < currentInstr.nArguments; i++) {
-              if (Evaluate(dataset, ref row, state) > 0.0) positiveSignals++;
+              if (Evaluate(dataset, ref row, state) > 0.0) { positiveSignals++; }
             }
             return positiveSignals % 2 != 0 ? 1.0 : -1.0;
@@ -356,12 +379,10 @@
             double x = Evaluate(dataset, ref row, state);
             double y = Evaluate(dataset, ref row, state);
-            if (x > y) return 1.0;
-            else return -1.0;
+            if (x > y) { return 1.0; } else { return -1.0; }
           }
         case OpCodes.LT: {
             double x = Evaluate(dataset, ref row, state);
             double y = Evaluate(dataset, ref row, state);
-            if (x < y) return 1.0;
-            else return -1.0;
+            if (x < y) { return 1.0; } else { return -1.0; }
           }
         case OpCodes.TimeLag: {
@@ -437,5 +458,5 @@
             var laggedVariableTreeNode = (LaggedVariableTreeNode)currentInstr.dynamicNode;
             int actualRow = row + laggedVariableTreeNode.Lag;
-            if (actualRow < 0 || actualRow >= dataset.Rows) return double.NaN;
+            if (actualRow < 0 || actualRow >= dataset.Rows) { return double.NaN; }
             return ((IList<double>)currentInstr.data)[actualRow] * laggedVariableTreeNode.Weight;
           }
@@ -459,5 +480,6 @@
             return trueBranch * p + falseBranch * (1 - p);
           }
-        default: throw new NotSupportedException();
+        default:
+          throw new NotSupportedException();
       }
     }
Index: /stable/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/Interpreter/SymbolicDataAnalysisExpressionTreeLinearInterpreter.cs
===================================================================
--- /stable/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/Interpreter/SymbolicDataAnalysisExpressionTreeLinearInterpreter.cs	(revision 14810)
+++ /stable/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/Interpreter/SymbolicDataAnalysisExpressionTreeLinearInterpreter.cs	(revision 14811)
@@ -35,7 +35,8 @@
   public sealed class SymbolicDataAnalysisExpressionTreeLinearInterpreter : ParameterizedNamedItem, ISymbolicDataAnalysisExpressionTreeInterpreter {
     private const string CheckExpressionsWithIntervalArithmeticParameterName = "CheckExpressionsWithIntervalArithmetic";
+    private const string CheckExpressionsWithIntervalArithmeticParameterDescription = "Switch that determines if the interpreter checks the validity of expressions with interval arithmetic before evaluating the expression.";
     private const string EvaluatedSolutionsParameterName = "EvaluatedSolutions";
 
-    private SymbolicDataAnalysisExpressionTreeInterpreter interpreter;
+    private readonly SymbolicDataAnalysisExpressionTreeInterpreter interpreter;
 
     public override bool CanChangeName {
@@ -48,21 +49,21 @@
 
     #region parameter properties
-    public IValueParameter<BoolValue> CheckExpressionsWithIntervalArithmeticParameter {
-      get { return (IValueParameter<BoolValue>)Parameters[CheckExpressionsWithIntervalArithmeticParameterName]; }
-    }
-
-    public IValueParameter<IntValue> EvaluatedSolutionsParameter {
-      get { return (IValueParameter<IntValue>)Parameters[EvaluatedSolutionsParameterName]; }
+    public IFixedValueParameter<BoolValue> CheckExpressionsWithIntervalArithmeticParameter {
+      get { return (IFixedValueParameter<BoolValue>)Parameters[CheckExpressionsWithIntervalArithmeticParameterName]; }
+    }
+
+    public IFixedValueParameter<IntValue> EvaluatedSolutionsParameter {
+      get { return (IFixedValueParameter<IntValue>)Parameters[EvaluatedSolutionsParameterName]; }
     }
     #endregion
 
     #region properties
-    public BoolValue CheckExpressionsWithIntervalArithmetic {
-      get { return CheckExpressionsWithIntervalArithmeticParameter.Value; }
-      set { CheckExpressionsWithIntervalArithmeticParameter.Value = value; }
-    }
-    public IntValue EvaluatedSolutions {
-      get { return EvaluatedSolutionsParameter.Value; }
-      set { EvaluatedSolutionsParameter.Value = value; }
+    public bool CheckExpressionsWithIntervalArithmetic {
+      get { return CheckExpressionsWithIntervalArithmeticParameter.Value.Value; }
+      set { CheckExpressionsWithIntervalArithmeticParameter.Value.Value = value; }
+    }
+    public int EvaluatedSolutions {
+      get { return EvaluatedSolutionsParameter.Value.Value; }
+      set { EvaluatedSolutionsParameter.Value.Value = value; }
     }
     #endregion
@@ -71,4 +72,5 @@
     private SymbolicDataAnalysisExpressionTreeLinearInterpreter(bool deserializing)
       : base(deserializing) {
+      interpreter = new SymbolicDataAnalysisExpressionTreeInterpreter();
     }
 
@@ -84,6 +86,13 @@
     public SymbolicDataAnalysisExpressionTreeLinearInterpreter()
       : base("SymbolicDataAnalysisExpressionTreeLinearInterpreter", "Linear (non-recursive) interpreter for symbolic expression trees (does not support ADFs).") {
-      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)));
-      Parameters.Add(new ValueParameter<IntValue>(EvaluatedSolutionsParameterName, "A counter for the total number of solutions the interpreter has evaluated", new IntValue(0)));
+      Parameters.Add(new FixedValueParameter<BoolValue>(CheckExpressionsWithIntervalArithmeticParameterName, CheckExpressionsWithIntervalArithmeticParameterDescription, new BoolValue(false)));
+      Parameters.Add(new FixedValueParameter<IntValue>(EvaluatedSolutionsParameterName, "A counter for the total number of solutions the interpreter has evaluated", new IntValue(0)));
+      interpreter = new SymbolicDataAnalysisExpressionTreeInterpreter();
+    }
+
+    public SymbolicDataAnalysisExpressionTreeLinearInterpreter(string name, string description)
+      : base(name, description) {
+      Parameters.Add(new FixedValueParameter<BoolValue>(CheckExpressionsWithIntervalArithmeticParameterName, CheckExpressionsWithIntervalArithmeticParameterDescription, new BoolValue(false)));
+      Parameters.Add(new FixedValueParameter<IntValue>(EvaluatedSolutionsParameterName, "A counter for the total number of solutions the interpreter has evaluated", new IntValue(0)));
       interpreter = new SymbolicDataAnalysisExpressionTreeInterpreter();
     }
@@ -91,10 +100,23 @@
     [StorableHook(HookType.AfterDeserialization)]
     private void AfterDeserialization() {
-      if (interpreter == null) interpreter = new SymbolicDataAnalysisExpressionTreeInterpreter();
+      var evaluatedSolutions = new IntValue(0);
+      var checkExpressionsWithIntervalArithmetic = new BoolValue(false);
+      if (Parameters.ContainsKey(EvaluatedSolutionsParameterName)) {
+        var evaluatedSolutionsParameter = (IValueParameter<IntValue>)Parameters[EvaluatedSolutionsParameterName];
+        evaluatedSolutions = evaluatedSolutionsParameter.Value;
+        Parameters.Remove(EvaluatedSolutionsParameterName);
+      }
+      Parameters.Add(new FixedValueParameter<IntValue>(EvaluatedSolutionsParameterName, "A counter for the total number of solutions the interpreter has evaluated", evaluatedSolutions));
+      if (Parameters.ContainsKey(CheckExpressionsWithIntervalArithmeticParameterName)) {
+        var checkExpressionsWithIntervalArithmeticParameter = (IValueParameter<BoolValue>)Parameters[CheckExpressionsWithIntervalArithmeticParameterName];
+        Parameters.Remove(CheckExpressionsWithIntervalArithmeticParameterName);
+        checkExpressionsWithIntervalArithmetic = checkExpressionsWithIntervalArithmeticParameter.Value;
+      }
+      Parameters.Add(new FixedValueParameter<BoolValue>(CheckExpressionsWithIntervalArithmeticParameterName, CheckExpressionsWithIntervalArithmeticParameterDescription, checkExpressionsWithIntervalArithmetic));
     }
 
     #region IStatefulItem
     public void InitializeState() {
-      EvaluatedSolutions.Value = 0;
+      EvaluatedSolutions = 0;
     }
 
@@ -102,10 +124,11 @@
     #endregion
 
+    private readonly object syncRoot = new object();
     public IEnumerable<double> GetSymbolicExpressionTreeValues(ISymbolicExpressionTree tree, IDataset dataset, IEnumerable<int> rows) {
-      if (CheckExpressionsWithIntervalArithmetic.Value)
+      if (CheckExpressionsWithIntervalArithmetic)
         throw new NotSupportedException("Interval arithmetic is not yet supported in the symbolic data analysis interpreter.");
 
-      lock (EvaluatedSolutions) {
-        EvaluatedSolutions.Value++; // increment the evaluated solutions counter
+      lock (syncRoot) {
+        EvaluatedSolutions++; // increment the evaluated solutions counter
       }
 
@@ -190,5 +213,5 @@
         } else if (instr.opCode == OpCodes.Root) {
           double x = code[instr.childIndex].value;
-          double y = code[instr.childIndex + 1].value;
+          double y = Math.Round(code[instr.childIndex + 1].value);
           instr.value = Math.Pow(x, 1 / y);
         } else if (instr.opCode == OpCodes.Exp) {
Index: /stable/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/Symbols/VariableCondition.cs
===================================================================
--- /stable/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/Symbols/VariableCondition.cs	(revision 14810)
+++ /stable/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/Symbols/VariableCondition.cs	(revision 14811)
@@ -148,4 +148,15 @@
           OnChanged(EventArgs.Empty);
         }
+      }
+    }
+
+    public override bool Enabled {
+      get {
+        if (variableNames.Count == 0) return false;
+        return base.Enabled;
+      }
+      set {
+        if (variableNames.Count == 0) base.Enabled = false;
+        else base.Enabled = value;
       }
     }
Index: /stable/HeuristicLab.Tests/HeuristicLab.Problems.DataAnalysis.Symbolic-3.4/SymbolicDataAnalysisExpressionTreeInterpreterTest.cs
===================================================================
--- /stable/HeuristicLab.Tests/HeuristicLab.Problems.DataAnalysis.Symbolic-3.4/SymbolicDataAnalysisExpressionTreeInterpreterTest.cs	(revision 14810)
+++ /stable/HeuristicLab.Tests/HeuristicLab.Problems.DataAnalysis.Symbolic-3.4/SymbolicDataAnalysisExpressionTreeInterpreterTest.cs	(revision 14811)
@@ -70,4 +70,22 @@
     }
 
+    [TestMethod]
+    [TestCategory("Problems.DataAnalysis.Symbolic")]
+    [TestProperty("Time", "long")]
+    public void CompiledInterpreterTestTypeCoherentGrammarPerformance() {
+      TestTypeCoherentGrammarPerformance(new SymbolicDataAnalysisExpressionCompiledTreeInterpreter(), 12.5e6);
+    }
+    [TestMethod]
+    [TestCategory("Problems.DataAnalysis.Symbolic")]
+    [TestProperty("Time", "long")]
+    public void CompiledInterpreterTestFullGrammarPerformance() {
+      TestFullGrammarPerformance(new SymbolicDataAnalysisExpressionCompiledTreeInterpreter(), 12.5e6);
+    }
+    [TestMethod]
+    [TestCategory("Problems.DataAnalysis.Symbolic")]
+    [TestProperty("Time", "long")]
+    public void CompiledInterpreterTestArithmeticGrammarPerformance() {
+      TestArithmeticGrammarPerformance(new SymbolicDataAnalysisExpressionCompiledTreeInterpreter(), 12.5e6);
+    }
 
     [TestMethod]
@@ -80,14 +98,7 @@
     [TestCategory("Problems.DataAnalysis.Symbolic")]
     [TestProperty("Time", "long")]
-    public void ILEmittingInterpreterTestFullGrammarPerformance() {
-      TestFullGrammarPerformance(new SymbolicDataAnalysisExpressionTreeILEmittingInterpreter(), 7.5e6);
-    }
-    [TestMethod]
-    [TestCategory("Problems.DataAnalysis.Symbolic")]
-    [TestProperty("Time", "long")]
     public void ILEmittingInterpreterTestArithmeticGrammarPerformance() {
       TestArithmeticGrammarPerformance(new SymbolicDataAnalysisExpressionTreeILEmittingInterpreter(), 7.5e6);
     }
-
 
     [TestMethod]
@@ -113,10 +124,8 @@
       var twister = new MersenneTwister(31415);
       var dataset = Util.CreateRandomDataset(twister, Rows, Columns);
+
       var grammar = new TypeCoherentExpressionGrammar();
       grammar.ConfigureAsDefaultRegressionGrammar();
-      grammar.MaximumFunctionArguments = 0;
-      grammar.MaximumFunctionDefinitions = 0;
-      grammar.MinimumFunctionArguments = 0;
-      grammar.MinimumFunctionDefinitions = 0;
+
       var randomTrees = Util.CreateRandomTrees(twister, dataset, grammar, N, 1, 100, 0, 0);
       foreach (ISymbolicExpressionTree tree in randomTrees) {
@@ -131,9 +140,6 @@
       var twister = new MersenneTwister(31415);
       var dataset = Util.CreateRandomDataset(twister, Rows, Columns);
+
       var grammar = new FullFunctionalExpressionGrammar();
-      grammar.MaximumFunctionArguments = 0;
-      grammar.MaximumFunctionDefinitions = 0;
-      grammar.MinimumFunctionArguments = 0;
-      grammar.MinimumFunctionDefinitions = 0;
       var randomTrees = Util.CreateRandomTrees(twister, dataset, grammar, N, 1, 100, 0, 0);
       foreach (ISymbolicExpressionTree tree in randomTrees) {
@@ -148,10 +154,6 @@
       var twister = new MersenneTwister(31415);
       var dataset = Util.CreateRandomDataset(twister, Rows, Columns);
+
       var grammar = new ArithmeticExpressionGrammar();
-      //grammar.Symbols.OfType<Variable>().First().Enabled = false;
-      grammar.MaximumFunctionArguments = 0;
-      grammar.MaximumFunctionDefinitions = 0;
-      grammar.MinimumFunctionArguments = 0;
-      grammar.MinimumFunctionDefinitions = 0;
       var randomTrees = Util.CreateRandomTrees(twister, dataset, grammar, N, 1, 100, 0, 0);
       foreach (SymbolicExpressionTree tree in randomTrees) {
@@ -175,7 +177,12 @@
       EvaluateTerminals(interpreter, ds);
       EvaluateOperations(interpreter, ds);
+      EvaluateLaggedOperations(interpreter, ds);
+      EvaluateSpecialFunctions(interpreter, ds);
       EvaluateAdf(interpreter, ds);
     }
 
+    /// <summary>
+    ///A test for Evaluate
+    ///</summary>
     [TestMethod]
     [TestCategory("Problems.DataAnalysis.Symbolic")]
@@ -185,4 +192,16 @@
       EvaluateTerminals(interpreter, ds);
       EvaluateOperations(interpreter, ds);
+      EvaluateLaggedOperations(interpreter, ds);
+      EvaluateSpecialFunctions(interpreter, ds);
+    }
+
+    [TestMethod]
+    [TestCategory("Problems.DataAnalysis.Symbolic")]
+    [TestProperty("Time", "short")]
+    public void CompiledInterpreterTestEvaluation() {
+      var interpreter = new SymbolicDataAnalysisExpressionCompiledTreeInterpreter();
+      EvaluateTerminals(interpreter, ds);
+      EvaluateOperations(interpreter, ds);
+      EvaluateSpecialFunctions(interpreter, ds);
     }
 
@@ -192,11 +211,127 @@
     public void LinearInterpreterTestEvaluation() {
       var interpreter = new SymbolicDataAnalysisExpressionTreeLinearInterpreter();
-
       //ADFs are not supported by the linear interpreter
       EvaluateTerminals(interpreter, ds);
       EvaluateOperations(interpreter, ds);
-    }
-
-    private void EvaluateTerminals(ISymbolicDataAnalysisExpressionTreeInterpreter interpreter, Dataset ds) {
+      EvaluateLaggedOperations(interpreter, ds);
+      EvaluateSpecialFunctions(interpreter, ds);
+    }
+
+    [TestMethod]
+    [TestCategory("Problems.DataAnalysis.Symbolic")]
+    [TestProperty("Time", "long")]
+    public void TestInterpretersEstimatedValuesConsistency() {
+      var twister = new MersenneTwister();
+      int seed = twister.Next(0, int.MaxValue);
+      twister.Seed((uint)seed);
+      const int numRows = 100;
+      var dataset = Util.CreateRandomDataset(twister, numRows, Columns);
+
+      var grammar = new TypeCoherentExpressionGrammar();
+
+      var interpreters = new ISymbolicDataAnalysisExpressionTreeInterpreter[] {
+        new SymbolicDataAnalysisExpressionTreeLinearInterpreter(),
+        new SymbolicDataAnalysisExpressionTreeInterpreter(),
+      };
+
+      var rows = Enumerable.Range(0, numRows).ToList();
+      var randomTrees = Util.CreateRandomTrees(twister, dataset, grammar, N, 1, 10, 0, 0);
+      foreach (ISymbolicExpressionTree tree in randomTrees) {
+        Util.InitTree(tree, twister, new List<string>(dataset.VariableNames));
+      }
+
+      for (int i = 0; i < randomTrees.Length; ++i) {
+        var tree = randomTrees[i];
+        var valuesMatrix = interpreters.Select(x => x.GetSymbolicExpressionTreeValues(tree, dataset, rows)).ToList();
+        for (int m = 0; m < interpreters.Length - 1; ++m) {
+          var sum = valuesMatrix[m].Sum();
+          for (int n = m + 1; n < interpreters.Length; ++n) {
+            var s = valuesMatrix[n].Sum();
+            if (double.IsNaN(sum) && double.IsNaN(s)) continue;
+
+            string errorMessage = string.Format("Interpreters {0} and {1} do not agree on tree {2} (seed = {3}).", interpreters[m].Name, interpreters[n].Name, i, seed);
+            Assert.AreEqual(sum, s, 1e-12, errorMessage);
+          }
+        }
+      }
+    }
+
+    [TestMethod]
+    [TestCategory("Problems.DataAnalysis.Symbolic")]
+    [TestProperty("Time", "long")]
+    public void TestCompiledInterpreterEstimatedValuesConsistency() {
+      const double delta = 1e-12;
+
+      var twister = new MersenneTwister();
+      int seed = twister.Next(0, int.MaxValue);
+      twister.Seed((uint)seed);
+
+      Console.WriteLine(seed);
+
+      const int numRows = 100;
+      var dataset = Util.CreateRandomDataset(twister, numRows, Columns);
+
+      var grammar = new TypeCoherentExpressionGrammar();
+      grammar.ConfigureAsDefaultRegressionGrammar();
+      grammar.Symbols.First(x => x.Name == "Power Functions").Enabled = true;
+
+      var randomTrees = Util.CreateRandomTrees(twister, dataset, grammar, N, 1, 10, 0, 0);
+      foreach (ISymbolicExpressionTree tree in randomTrees) {
+        Util.InitTree(tree, twister, new List<string>(dataset.VariableNames));
+      }
+
+      var interpreters = new ISymbolicDataAnalysisExpressionTreeInterpreter[] {
+        new SymbolicDataAnalysisExpressionCompiledTreeInterpreter(),
+        new SymbolicDataAnalysisExpressionTreeInterpreter(),
+        new SymbolicDataAnalysisExpressionTreeLinearInterpreter(),
+      };
+      var rows = Enumerable.Range(0, numRows).ToList();
+      var formatter = new SymbolicExpressionTreeHierarchicalFormatter();
+
+      for (int i = 0; i < randomTrees.Length; ++i) {
+        var tree = randomTrees[i];
+        var valuesMatrix = interpreters.Select(x => x.GetSymbolicExpressionTreeValues(tree, dataset, rows).ToList()).ToList();
+        for (int m = 0; m < interpreters.Length - 1; ++m) {
+          for (int n = m + 1; n < interpreters.Length; ++n) {
+            for (int row = 0; row < numRows; ++row) {
+              var v1 = valuesMatrix[m][row];
+              var v2 = valuesMatrix[n][row];
+              if (double.IsNaN(v1) && double.IsNaN(v2)) continue;
+              if (Math.Abs(v1 - v2) > delta) {
+                Console.WriteLine(formatter.Format(tree));
+                foreach (var node in tree.Root.GetSubtree(0).GetSubtree(0).IterateNodesPrefix().ToList()) {
+                  var rootNode = (SymbolicExpressionTreeTopLevelNode)grammar.ProgramRootSymbol.CreateTreeNode();
+                  if (rootNode.HasLocalParameters) rootNode.ResetLocalParameters(twister);
+                  rootNode.SetGrammar(grammar.CreateExpressionTreeGrammar());
+
+                  var startNode = (SymbolicExpressionTreeTopLevelNode)grammar.StartSymbol.CreateTreeNode();
+                  if (startNode.HasLocalParameters) startNode.ResetLocalParameters(twister);
+                  startNode.SetGrammar(grammar.CreateExpressionTreeGrammar());
+
+                  rootNode.AddSubtree(startNode);
+                  var t = new SymbolicExpressionTree(rootNode);
+                  var start = t.Root.GetSubtree(0);
+                  var p = node.Parent;
+                  start.AddSubtree(node);
+                  Console.WriteLine(node);
+
+                  var y1 = interpreters[m].GetSymbolicExpressionTreeValues(t, dataset, new[] { row }).First();
+                  var y2 = interpreters[n].GetSymbolicExpressionTreeValues(t, dataset, new[] { row }).First();
+
+                  if (double.IsNaN(y1) && double.IsNaN(y2)) continue;
+                  string prefix = Math.Abs(y1 - y2) > delta ? "++" : "==";
+                  Console.WriteLine("\t{0} Row {1}: {2} {3}, Deviation = {4}", prefix, row, y1, y2, Math.Abs(y1 - y2));
+                  node.Parent = p;
+                }
+              }
+              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);
+              Assert.AreEqual(v1, v2, delta, errorMessage);
+            }
+          }
+        }
+      }
+    }
+
+    private void EvaluateTerminals(ISymbolicDataAnalysisExpressionTreeInterpreter interpreter, IDataset ds) {
       // constants
       Evaluate(interpreter, ds, "(+ 1.5 3.5)", 0, 5.0);
@@ -207,5 +342,5 @@
     }
 
-    private void EvaluateAdf(ISymbolicDataAnalysisExpressionTreeInterpreter interpreter, Dataset ds) {
+    private void EvaluateAdf(ISymbolicDataAnalysisExpressionTreeInterpreter interpreter, IDataset ds) {
 
       // ADF      
@@ -246,5 +381,103 @@
     }
 
-    private void EvaluateOperations(ISymbolicDataAnalysisExpressionTreeInterpreter interpreter, Dataset ds) {
+    private void EvaluateSpecialFunctions(ISymbolicDataAnalysisExpressionTreeInterpreter interpreter, IDataset ds) {
+      // special functions
+      Action<double> checkAiry = (x) => {
+        double ai, aip, bi, bip;
+        alglib.airy(x, out ai, out aip, out bi, out bip);
+        Evaluate(interpreter, ds, "(airya " + x + ")", 0, ai);
+        Evaluate(interpreter, ds, "(airyb " + x + ")", 0, bi);
+      };
+
+      Action<double> checkBessel = (x) => {
+        Evaluate(interpreter, ds, "(bessel " + x + ")", 0, alglib.besseli0(x));
+      };
+
+      Action<double> checkSinCosIntegrals = (x) => {
+        double si, ci;
+        alglib.sinecosineintegrals(x, out si, out ci);
+        Evaluate(interpreter, ds, "(cosint " + x + ")", 0, ci);
+        Evaluate(interpreter, ds, "(sinint " + x + ")", 0, si);
+      };
+      Action<double> checkHypSinCosIntegrals = (x) => {
+        double shi, chi;
+        alglib.hyperbolicsinecosineintegrals(x, out shi, out chi);
+        Evaluate(interpreter, ds, "(hypcosint " + x + ")", 0, chi);
+        Evaluate(interpreter, ds, "(hypsinint " + x + ")", 0, shi);
+      };
+      Action<double> checkFresnelSinCosIntegrals = (x) => {
+        double c = 0, s = 0;
+        alglib.fresnelintegral(x, ref c, ref s);
+        Evaluate(interpreter, ds, "(fresnelcosint " + x + ")", 0, c);
+        Evaluate(interpreter, ds, "(fresnelsinint " + x + ")", 0, s);
+      };
+      Action<double> checkNormErf = (x) => {
+        Evaluate(interpreter, ds, "(norm " + x + ")", 0, alglib.normaldistribution(x));
+        Evaluate(interpreter, ds, "(erf " + x + ")", 0, alglib.errorfunction(x));
+      };
+
+      Action<double> checkGamma = (x) => {
+        Evaluate(interpreter, ds, "(gamma " + x + ")", 0, alglib.gammafunction(x));
+      };
+      Action<double> checkPsi = (x) => {
+        try {
+          Evaluate(interpreter, ds, "(psi " + x + ")", 0, alglib.psi(x));
+        } catch (alglib.alglibexception) { // ignore cases where alglib throws an exception
+        }
+      };
+      Action<double> checkDawson = (x) => {
+        Evaluate(interpreter, ds, "(dawson " + x + ")", 0, alglib.dawsonintegral(x));
+      };
+      Action<double> checkExpInt = (x) => {
+        Evaluate(interpreter, ds, "(expint " + x + ")", 0, alglib.exponentialintegralei(x));
+      };
+
+      foreach (var e in new[] { -2.0, -1.0, 0.0, 1.0, 2.0 }) {
+        checkAiry(e);
+        checkBessel(e);
+        checkSinCosIntegrals(e);
+        checkGamma(e);
+        checkExpInt(e);
+        checkDawson(e);
+        checkPsi(e);
+        checkNormErf(e);
+        checkFresnelSinCosIntegrals(e);
+        checkHypSinCosIntegrals(e);
+      }
+    }
+
+    private void EvaluateLaggedOperations(ISymbolicDataAnalysisExpressionTreeInterpreter interpreter, IDataset ds) {
+      // lag
+      Evaluate(interpreter, ds, "(lagVariable 1.0 a -1) ", 1, ds.GetDoubleValue("A", 0));
+      Evaluate(interpreter, ds, "(lagVariable 1.0 a -1) ", 2, ds.GetDoubleValue("A", 1));
+      Evaluate(interpreter, ds, "(lagVariable 1.0 a 0) ", 2, ds.GetDoubleValue("A", 2));
+      Evaluate(interpreter, ds, "(lagVariable 1.0 a 1) ", 0, ds.GetDoubleValue("A", 1));
+
+      // integral
+      Evaluate(interpreter, ds, "(integral -1.0 (variable 1.0 a)) ", 1, ds.GetDoubleValue("A", 0) + ds.GetDoubleValue("A", 1));
+      Evaluate(interpreter, ds, "(integral -1.0 (lagVariable 1.0 a 1)) ", 1, ds.GetDoubleValue("A", 1) + ds.GetDoubleValue("A", 2));
+      Evaluate(interpreter, ds, "(integral -2.0 (variable 1.0 a)) ", 2, ds.GetDoubleValue("A", 0) + ds.GetDoubleValue("A", 1) + ds.GetDoubleValue("A", 2));
+      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));
+      Evaluate(interpreter, ds, "(integral -2.0 3.0)", 1, 9.0);
+
+      // derivative
+      // (f_0 + 2 * f_1 - 2 * f_3 - f_4) / 8; // h = 1
+      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);
+      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);
+      Evaluate(interpreter, ds, "(diff (* (variable 1.0 a) (variable 1.0 b)))", 5, +
+        (ds.GetDoubleValue("A", 5) * ds.GetDoubleValue("B", 5) +
+        2 * ds.GetDoubleValue("A", 4) * ds.GetDoubleValue("B", 4) -
+        2 * ds.GetDoubleValue("A", 2) * ds.GetDoubleValue("B", 2) -
+        ds.GetDoubleValue("A", 1) * ds.GetDoubleValue("B", 1)) / 8.0);
+      Evaluate(interpreter, ds, "(diff -2.0 3.0)", 5, 0.0);
+
+      // timelag
+      Evaluate(interpreter, ds, "(lag -1.0 (lagVariable 1.0 a 2)) ", 1, ds.GetDoubleValue("A", 2));
+      Evaluate(interpreter, ds, "(lag -2.0 (lagVariable 1.0 a 2)) ", 2, ds.GetDoubleValue("A", 2));
+      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));
+      Evaluate(interpreter, ds, "(lag -2.0 3.0)", 1, 3.0);
+    }
+
+    private void EvaluateOperations(ISymbolicDataAnalysisExpressionTreeInterpreter interpreter, IDataset ds) {
       // addition
       Evaluate(interpreter, ds, "(+ (variable 2.0 a ))", 1, 4.0);
@@ -369,106 +602,7 @@
       // mean
       Evaluate(interpreter, ds, "(mean -1.0 1.0 -1.0)", 0, -1.0 / 3.0);
-
-      // lag
-      Evaluate(interpreter, ds, "(lagVariable 1.0 a -1) ", 1, ds.GetDoubleValue("A", 0));
-      Evaluate(interpreter, ds, "(lagVariable 1.0 a -1) ", 2, ds.GetDoubleValue("A", 1));
-      Evaluate(interpreter, ds, "(lagVariable 1.0 a 0) ", 2, ds.GetDoubleValue("A", 2));
-      Evaluate(interpreter, ds, "(lagVariable 1.0 a 1) ", 0, ds.GetDoubleValue("A", 1));
-
-      // integral
-      Evaluate(interpreter, ds, "(integral -1.0 (variable 1.0 a)) ", 1, ds.GetDoubleValue("A", 0) + ds.GetDoubleValue("A", 1));
-      Evaluate(interpreter, ds, "(integral -1.0 (lagVariable 1.0 a 1)) ", 1, ds.GetDoubleValue("A", 1) + ds.GetDoubleValue("A", 2));
-      Evaluate(interpreter, ds, "(integral -2.0 (variable 1.0 a)) ", 2, ds.GetDoubleValue("A", 0) + ds.GetDoubleValue("A", 1) + ds.GetDoubleValue("A", 2));
-      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));
-      Evaluate(interpreter, ds, "(integral -2.0 3.0)", 1, 9.0);
-
-      // derivative
-      // (f_0 + 2 * f_1 - 2 * f_3 - f_4) / 8; // h = 1
-      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);
-      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);
-      Evaluate(interpreter, ds, "(diff (* (variable 1.0 a) (variable 1.0 b)))", 5, +
-        (ds.GetDoubleValue("A", 5) * ds.GetDoubleValue("B", 5) +
-        2 * ds.GetDoubleValue("A", 4) * ds.GetDoubleValue("B", 4) -
-        2 * ds.GetDoubleValue("A", 2) * ds.GetDoubleValue("B", 2) -
-        ds.GetDoubleValue("A", 1) * ds.GetDoubleValue("B", 1)) / 8.0);
-      Evaluate(interpreter, ds, "(diff -2.0 3.0)", 5, 0.0);
-
-      // timelag
-      Evaluate(interpreter, ds, "(lag -1.0 (lagVariable 1.0 a 2)) ", 1, ds.GetDoubleValue("A", 2));
-      Evaluate(interpreter, ds, "(lag -2.0 (lagVariable 1.0 a 2)) ", 2, ds.GetDoubleValue("A", 2));
-      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));
-      Evaluate(interpreter, ds, "(lag -2.0 3.0)", 1, 3.0);
-
-      {
-        // special functions
-        Action<double> checkAiry = (x) => {
-          double ai, aip, bi, bip;
-          alglib.airy(x, out ai, out aip, out bi, out bip);
-          Evaluate(interpreter, ds, "(airya " + x + ")", 0, ai);
-          Evaluate(interpreter, ds, "(airyb " + x + ")", 0, bi);
-        };
-
-        Action<double> checkBessel = (x) => {
-          Evaluate(interpreter, ds, "(bessel " + x + ")", 0, alglib.besseli0(x));
-        };
-
-        Action<double> checkSinCosIntegrals = (x) => {
-          double si, ci;
-          alglib.sinecosineintegrals(x, out si, out ci);
-          Evaluate(interpreter, ds, "(cosint " + x + ")", 0, ci);
-          Evaluate(interpreter, ds, "(sinint " + x + ")", 0, si);
-        };
-        Action<double> checkHypSinCosIntegrals = (x) => {
-          double shi, chi;
-          alglib.hyperbolicsinecosineintegrals(x, out shi, out chi);
-          Evaluate(interpreter, ds, "(hypcosint " + x + ")", 0, chi);
-          Evaluate(interpreter, ds, "(hypsinint " + x + ")", 0, shi);
-        };
-        Action<double> checkFresnelSinCosIntegrals = (x) => {
-          double c = 0, s = 0;
-          alglib.fresnelintegral(x, ref c, ref s);
-          Evaluate(interpreter, ds, "(fresnelcosint " + x + ")", 0, c);
-          Evaluate(interpreter, ds, "(fresnelsinint " + x + ")", 0, s);
-        };
-        Action<double> checkNormErf = (x) => {
-          Evaluate(interpreter, ds, "(norm " + x + ")", 0, alglib.normaldistribution(x));
-          Evaluate(interpreter, ds, "(erf " + x + ")", 0, alglib.errorfunction(x));
-        };
-
-        Action<double> checkGamma = (x) => {
-          Evaluate(interpreter, ds, "(gamma " + x + ")", 0, alglib.gammafunction(x));
-        };
-        Action<double> checkPsi = (x) => {
-          try {
-            Evaluate(interpreter, ds, "(psi " + x + ")", 0, alglib.psi(x));
-          }
-          catch (alglib.alglibexception) { // ignore cases where alglib throws an exception
-          }
-        };
-        Action<double> checkDawson = (x) => {
-          Evaluate(interpreter, ds, "(dawson " + x + ")", 0, alglib.dawsonintegral(x));
-        };
-        Action<double> checkExpInt = (x) => {
-          Evaluate(interpreter, ds, "(expint " + x + ")", 0, alglib.exponentialintegralei(x));
-        };
-
-
-
-        foreach (var e in new[] { -2.0, -1.0, 0.0, 1.0, 2.0 }) {
-          checkAiry(e);
-          checkBessel(e);
-          checkSinCosIntegrals(e);
-          checkGamma(e);
-          checkExpInt(e);
-          checkDawson(e);
-          checkPsi(e);
-          checkNormErf(e);
-          checkFresnelSinCosIntegrals(e);
-          checkHypSinCosIntegrals(e);
-        }
-      }
-    }
-
-    private void Evaluate(ISymbolicDataAnalysisExpressionTreeInterpreter interpreter, Dataset ds, string expr, int index, double expected) {
+    }
+
+    private void Evaluate(ISymbolicDataAnalysisExpressionTreeInterpreter interpreter, IDataset ds, string expr, int index, double expected) {
       var importer = new SymbolicExpressionImporter();
       ISymbolicExpressionTree tree = importer.Import(expr);
