Index: branches/crossvalidation-2434/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/Analyzers/SymbolicDataAnalysisMultiObjectiveTrainingBestSolutionAnalyzer.cs
===================================================================
--- branches/crossvalidation-2434/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/Analyzers/SymbolicDataAnalysisMultiObjectiveTrainingBestSolutionAnalyzer.cs	(revision 13401)
+++ branches/crossvalidation-2434/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/Analyzers/SymbolicDataAnalysisMultiObjectiveTrainingBestSolutionAnalyzer.cs	(revision 14029)
@@ -20,5 +20,4 @@
 #endregion
 
-using System;
 using System.Collections.Generic;
 using System.Linq;
@@ -42,4 +41,5 @@
     private const string TrainingBestSolutionQualitiesParameterName = "Best training solution qualities";
     private const string UpdateAlwaysParameterName = "Always update best solutions";
+    private const string TrainingBestSolutionParameterName = "Best training solution";
 
     #region parameter properties
@@ -55,14 +55,15 @@
     #endregion
     #region properties
-    public ItemList<T> TrainingBestSolutions {
+    private ItemList<T> TrainingBestSolutions {
       get { return TrainingBestSolutionsParameter.ActualValue; }
       set { TrainingBestSolutionsParameter.ActualValue = value; }
     }
-    public ItemList<DoubleArray> TrainingBestSolutionQualities {
+    private ItemList<DoubleArray> TrainingBestSolutionQualities {
       get { return TrainingBestSolutionQualitiesParameter.ActualValue; }
       set { TrainingBestSolutionQualitiesParameter.ActualValue = value; }
     }
-    public BoolValue UpdateAlways {
-      get { return UpdateAlwaysParameter.Value; }
+    public bool UpdateAlways {
+      get { return UpdateAlwaysParameter.Value.Value; }
+      set { UpdateAlwaysParameter.Value.Value = value; }
     }
     #endregion
@@ -97,7 +98,11 @@
       }
 
+      if (!results.ContainsKey(TrainingBestSolutionParameterName)) {
+        results.Add(new Result(TrainingBestSolutionParameterName, "", typeof(ISymbolicDataAnalysisSolution)));
+      }
+
       //if the pareto front of best solutions shall be updated regardless of the quality, the list initialized empty to discard old solutions
-      IList<double[]> trainingBestQualities;
-      if (UpdateAlways.Value) {
+      List<double[]> trainingBestQualities;
+      if (UpdateAlways) {
         trainingBestQualities = new List<double[]>();
       } else {
@@ -105,42 +110,46 @@
       }
 
-      #region find best trees
-      IList<int> nonDominatedIndexes = new List<int>();
-      ISymbolicExpressionTree[] tree = SymbolicExpressionTree.ToArray();
+      ISymbolicExpressionTree[] trees = SymbolicExpressionTree.ToArray();
       List<double[]> qualities = Qualities.Select(x => x.ToArray()).ToList();
       bool[] maximization = Maximization.ToArray();
-      List<double[]> newNonDominatedQualities = new List<double[]>();
-      for (int i = 0; i < tree.Length; i++) {
-        if (IsNonDominated(qualities[i], trainingBestQualities, maximization) &&
-          IsNonDominated(qualities[i], qualities, maximization)) {
-          if (!newNonDominatedQualities.Contains(qualities[i], new DoubleArrayComparer())) {
-            newNonDominatedQualities.Add(qualities[i]);
-            nonDominatedIndexes.Add(i);
+
+      var nonDominatedIndividuals = new[] { new { Tree = default(ISymbolicExpressionTree), Qualities = default(double[]) } }.ToList();
+      nonDominatedIndividuals.Clear();
+
+      // build list of new non-dominated solutions
+      for (int i = 0; i < trees.Length; i++) {
+        if (IsNonDominated(qualities[i], nonDominatedIndividuals.Select(ind => ind.Qualities), maximization) &&
+            IsNonDominated(qualities[i], trainingBestQualities, maximization)) {
+          for (int j = nonDominatedIndividuals.Count - 1; j >= 0; j--) {
+            if (IsBetterOrEqual(qualities[i], nonDominatedIndividuals[j].Qualities, maximization)) {
+              nonDominatedIndividuals.RemoveAt(j);
+            }
           }
+          nonDominatedIndividuals.Add(new { Tree = trees[i], Qualities = qualities[i] });
         }
       }
-      #endregion
+
+      var nonDominatedSolutions = nonDominatedIndividuals.Select(x => new { Solution = CreateSolution(x.Tree, x.Qualities), Qualities = x.Qualities }).ToList();
+      nonDominatedSolutions.ForEach(s => s.Solution.Name = string.Join(",", s.Qualities.Select(q => q.ToString())));
+
       #region update Pareto-optimal solution archive
-      if (nonDominatedIndexes.Count > 0) {
-        ItemList<DoubleArray> nonDominatedQualities = new ItemList<DoubleArray>();
-        ItemList<T> nonDominatedSolutions = new ItemList<T>();
-        // add all new non-dominated solutions to the archive
-        foreach (var index in nonDominatedIndexes) {
-          T solution = CreateSolution(tree[index], qualities[index]);
-          nonDominatedSolutions.Add(solution);
-          nonDominatedQualities.Add(new DoubleArray(qualities[index]));
-        }
-        // add old non-dominated solutions only if they are not dominated by one of the new solutions
+      if (nonDominatedSolutions.Count > 0) {
+        //add old non-dominated solutions only if they are not dominated by one of the new solutions
         for (int i = 0; i < trainingBestQualities.Count; i++) {
-          if (IsNonDominated(trainingBestQualities[i], newNonDominatedQualities, maximization)) {
-            if (!newNonDominatedQualities.Contains(trainingBestQualities[i], new DoubleArrayComparer())) {
-              nonDominatedSolutions.Add(TrainingBestSolutions[i]);
-              nonDominatedQualities.Add(TrainingBestSolutionQualities[i]);
-            }
+          if (IsNonDominated(trainingBestQualities[i], nonDominatedSolutions.Select(x => x.Qualities), maximization)) {
+            nonDominatedSolutions.Add(new { Solution = TrainingBestSolutions[i], Qualities = TrainingBestSolutionQualities[i].ToArray() });
           }
         }
 
-        results[TrainingBestSolutionsParameter.Name].Value = nonDominatedSolutions;
-        results[TrainingBestSolutionQualitiesParameter.Name].Value = nonDominatedQualities;
+        //assumes the the first objective is always the accuracy
+        var sortedNonDominatedSolutions = maximization[0]
+          ? nonDominatedSolutions.OrderByDescending(x => x.Qualities[0])
+          : nonDominatedSolutions.OrderBy(x => x.Qualities[0]);
+        var trainingBestSolution = sortedNonDominatedSolutions.Select(s => s.Solution).First();
+        results[TrainingBestSolutionParameterName].Value = trainingBestSolution;
+        TrainingBestSolutions = new ItemList<T>(sortedNonDominatedSolutions.Select(x => x.Solution));
+        results[TrainingBestSolutionsParameter.Name].Value = TrainingBestSolutions;
+        TrainingBestSolutionQualities = new ItemList<DoubleArray>(sortedNonDominatedSolutions.Select(x => new DoubleArray(x.Qualities)));
+        results[TrainingBestSolutionQualitiesParameter.Name].Value = TrainingBestSolutionQualities;
       }
       #endregion
@@ -148,36 +157,25 @@
     }
 
-    private class DoubleArrayComparer : IEqualityComparer<double[]> {
-      public bool Equals(double[] x, double[] y) {
-        if (y.Length != x.Length) throw new ArgumentException();
-        for (int i = 0; i < x.Length; i++) {
-          if (!x[i].IsAlmost(y[i])) return false;
-        }
-        return true;
-      }
-
-      public int GetHashCode(double[] obj) {
-        int c = obj.Length;
-        for (int i = 0; i < obj.Length; i++)
-          c ^= obj[i].GetHashCode();
-        return c;
-      }
-    }
-
     protected abstract T CreateSolution(ISymbolicExpressionTree bestTree, double[] bestQuality);
 
-    private bool IsNonDominated(double[] point, IList<double[]> points, bool[] maximization) {
+    private bool IsNonDominated(double[] point, IEnumerable<double[]> points, bool[] maximization) {
       foreach (var refPoint in points) {
-        bool refPointDominatesPoint = true;
-        for (int i = 0; i < point.Length; i++) {
-          refPointDominatesPoint &= IsBetterOrEqual(refPoint[i], point[i], maximization[i]);
-        }
+        bool refPointDominatesPoint = IsBetterOrEqual(refPoint, point, maximization);
         if (refPointDominatesPoint) return false;
       }
       return true;
     }
+
+    private bool IsBetterOrEqual(double[] lhs, double[] rhs, bool[] maximization) {
+      for (int i = 0; i < lhs.Length; i++) {
+        var result = IsBetterOrEqual(lhs[i], rhs[i], maximization[i]);
+        if (!result) return false;
+      }
+      return true;
+    }
+
     private bool IsBetterOrEqual(double lhs, double rhs, bool maximization) {
-      if (maximization) return lhs > rhs;
-      else return lhs < rhs;
+      if (maximization) return lhs >= rhs;
+      else return lhs <= rhs;
     }
   }
Index: branches/crossvalidation-2434/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/Creators/MultiSymbolicDataAnalysisExpressionCreator.cs
===================================================================
--- branches/crossvalidation-2434/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/Creators/MultiSymbolicDataAnalysisExpressionCreator.cs	(revision 13401)
+++ branches/crossvalidation-2434/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/Creators/MultiSymbolicDataAnalysisExpressionCreator.cs	(revision 14029)
@@ -35,4 +35,5 @@
 
 namespace HeuristicLab.Problems.DataAnalysis.Symbolic.Creators {
+  [StorableClass]
   public class MultiSymbolicDataAnalysisExpressionCreator : StochasticMultiBranch<ISymbolicDataAnalysisSolutionCreator>,
     ISymbolicDataAnalysisSolutionCreator,
Index: branches/crossvalidation-2434/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/Crossovers/SymbolicDataAnalysisExpressionContextAwareCrossover.cs
===================================================================
--- branches/crossvalidation-2434/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/Crossovers/SymbolicDataAnalysisExpressionContextAwareCrossover.cs	(revision 13401)
+++ branches/crossvalidation-2434/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/Crossovers/SymbolicDataAnalysisExpressionContextAwareCrossover.cs	(revision 14029)
@@ -34,4 +34,5 @@
                                  "- Randomly choose a node N from P1\n" +
                                  "- Test all crossover points from P0 to determine the best location for N to be inserted")]
+  [StorableClass]
   public sealed class SymbolicDataAnalysisExpressionContextAwareCrossover<T> : SymbolicDataAnalysisExpressionCrossover<T> where T : class, IDataAnalysisProblemData {
     [StorableConstructor]
Index: branches/crossvalidation-2434/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/Crossovers/SymbolicDataAnalysisExpressionCrossover.cs
===================================================================
--- branches/crossvalidation-2434/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/Crossovers/SymbolicDataAnalysisExpressionCrossover.cs	(revision 13401)
+++ branches/crossvalidation-2434/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/Crossovers/SymbolicDataAnalysisExpressionCrossover.cs	(revision 14029)
@@ -32,4 +32,5 @@
 
 namespace HeuristicLab.Problems.DataAnalysis.Symbolic {
+  [StorableClass]
   public abstract class SymbolicDataAnalysisExpressionCrossover<T> : SymbolicExpressionTreeCrossover, ISymbolicDataAnalysisExpressionCrossover<T> where T : class, IDataAnalysisProblemData {
     private const string SymbolicDataAnalysisTreeInterpreterParameterName = "SymbolicExpressionTreeInterpreter";
Index: branches/crossvalidation-2434/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/Crossovers/SymbolicDataAnalysisExpressionDepthConstrainedCrossover.cs
===================================================================
--- branches/crossvalidation-2434/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/Crossovers/SymbolicDataAnalysisExpressionDepthConstrainedCrossover.cs	(revision 13401)
+++ branches/crossvalidation-2434/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/Crossovers/SymbolicDataAnalysisExpressionDepthConstrainedCrossover.cs	(revision 14029)
@@ -36,4 +36,5 @@
                                      "- Standard (mid 50% of the tree)\n" +
                                      "- LowLevel (lower 25% of the tree)")]
+  [StorableClass]
   public sealed class SymbolicDataAnalysisExpressionDepthConstrainedCrossover<T> :
     SymbolicDataAnalysisExpressionCrossover<T> where T : class, IDataAnalysisProblemData {
Index: branches/crossvalidation-2434/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/Crossovers/SymbolicDataAnalysisExpressionDeterministicBestCrossover.cs
===================================================================
--- branches/crossvalidation-2434/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/Crossovers/SymbolicDataAnalysisExpressionDeterministicBestCrossover.cs	(revision 13401)
+++ branches/crossvalidation-2434/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/Crossovers/SymbolicDataAnalysisExpressionDeterministicBestCrossover.cs	(revision 14029)
@@ -34,4 +34,5 @@
                                       "- Randomly choose a crossover point C from P0\n" +
                                       "- Test all nodes from P1 to determine the one that produces the best child when inserted at place C in P0")]
+  [StorableClass]
   public sealed class SymbolicDataAnalysisExpressionDeterministicBestCrossover<T> : SymbolicDataAnalysisExpressionCrossover<T> where T : class, IDataAnalysisProblemData {
     [StorableConstructor]
Index: branches/crossvalidation-2434/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/Crossovers/SymbolicDataAnalysisExpressionProbabilisticFunctionalCrossover.cs
===================================================================
--- branches/crossvalidation-2434/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/Crossovers/SymbolicDataAnalysisExpressionProbabilisticFunctionalCrossover.cs	(revision 13401)
+++ branches/crossvalidation-2434/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/Crossovers/SymbolicDataAnalysisExpressionProbabilisticFunctionalCrossover.cs	(revision 14029)
@@ -36,4 +36,5 @@
                                             "\t\tD(N,M) = 0.5 * ( abs(max(N) - max(M)) + abs(min(N) - min(M)) )\n" +
                                             "- Make a probabilistic weighted choice of node M from P1, based on the inversed and normalized behavioral distance")]
+  [StorableClass]
   public sealed class SymbolicDataAnalysisExpressionProbabilisticFunctionalCrossover<T> : SymbolicDataAnalysisExpressionCrossover<T> where T : class, IDataAnalysisProblemData {
     [StorableConstructor]
Index: branches/crossvalidation-2434/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/Crossovers/SymbolicDataAnalysisExpressionSemanticSimilarityCrossover.cs
===================================================================
--- branches/crossvalidation-2434/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/Crossovers/SymbolicDataAnalysisExpressionSemanticSimilarityCrossover.cs	(revision 13401)
+++ branches/crossvalidation-2434/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/Crossovers/SymbolicDataAnalysisExpressionSemanticSimilarityCrossover.cs	(revision 14029)
@@ -37,4 +37,5 @@
                                        "- Find the first node M that satisfies the semantic similarity criteria\n" +
                                        "- Swap N for M and return P0")]
+  [StorableClass]
   public sealed class SymbolicDataAnalysisExpressionSemanticSimilarityCrossover<T> : SymbolicDataAnalysisExpressionCrossover<T> where T : class, IDataAnalysisProblemData {
     private const string SemanticSimilarityRangeParameterName = "SemanticSimilarityRange";
Index: branches/crossvalidation-2434/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/Crossovers/SymbolicDataAnalysisExpressionSizefairCrossover.cs
===================================================================
--- branches/crossvalidation-2434/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/Crossovers/SymbolicDataAnalysisExpressionSizefairCrossover.cs	(revision 13401)
+++ 	(revision )
@@ -1,46 +1,0 @@
-﻿#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 HeuristicLab.Data;
-using HeuristicLab.Encodings.SymbolicExpressionTreeEncoding;
-using HeuristicLab.Persistence.Default.CompositeSerializers.Storable;
-using HeuristicLab.Common;
-using HeuristicLab.Core;
-
-namespace HeuristicLab.Problems.DataAnalysis.Symbolic.Crossovers {
-  [Item("SizeFairCrossover", "An operator which performs subtree swapping crossover.")]
-  class SymbolicDataAnalysisExpressionSizefairCrossover<T> : SubtreeCrossover, ISymbolicDataAnalysisExpressionCrossover<T> {
-    [StorableConstructor]
-    protected SymbolicDataAnalysisExpressionSizefairCrossover(bool deserializing) : base(deserializing) { }
-    protected SymbolicDataAnalysisExpressionSizefairCrossover(SubtreeCrossover original, Cloner cloner) : base(original, cloner) { }
-    public override IDeepCloneable Clone(Cloner cloner) { return new SymbolicDataAnalysisExpressionSizefairCrossover<T>(this, cloner); }
-
-    public override bool CanChangeName {
-      get { return true; }
-    }
-
-    public SymbolicDataAnalysisExpressionSizefairCrossover()
-      : base() {
-      SymbolicDataAnalysisEvaluationPartitionParameter.Hidden = true;
-      Name = "SizeFairCrossover";
-    }
-  }
-}
Index: branches/crossvalidation-2434/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/Evaluators/SymbolicDataAnalysisEvaluator.cs
===================================================================
--- branches/crossvalidation-2434/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/Evaluators/SymbolicDataAnalysisEvaluator.cs	(revision 13401)
+++ branches/crossvalidation-2434/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/Evaluators/SymbolicDataAnalysisEvaluator.cs	(revision 14029)
@@ -93,13 +93,13 @@
     public SymbolicDataAnalysisEvaluator()
       : base() {
-      Parameters.Add(new ValueLookupParameter<IRandom>(RandomParameterName, "The random generator to use."));
-      Parameters.Add(new LookupParameter<ISymbolicDataAnalysisExpressionTreeInterpreter>(SymbolicDataAnalysisTreeInterpreterParameterName, "The interpreter that should be used to calculate the output values of the symbolic data analysis tree."));
-      Parameters.Add(new LookupParameter<ISymbolicExpressionTree>(SymbolicExpressionTreeParameterName, "The symbolic data analysis solution encoded as a symbolic expression tree."));
-      Parameters.Add(new ValueLookupParameter<T>(ProblemDataParameterName, "The problem data on which the symbolic data analysis solution should be evaluated."));
-      Parameters.Add(new ValueLookupParameter<IntRange>(EvaluationPartitionParameterName, "The start index of the dataset partition on which the symbolic data analysis solution should be evaluated."));
-      Parameters.Add(new ValueLookupParameter<DoubleLimit>(EstimationLimitsParameterName, "The upper and lower limit that should be used as cut off value for the output values of symbolic data analysis trees."));
-      Parameters.Add(new ValueLookupParameter<PercentValue>(RelativeNumberOfEvaluatedSamplesParameterName, "The relative number of samples of the dataset partition, which should be randomly chosen for evaluation between the start and end index."));
-      Parameters.Add(new LookupParameter<BoolValue>(ApplyLinearScalingParameterName, "Flag that indicates if the individual should be linearly scaled before evaluating."));
-      Parameters.Add(new ValueLookupParameter<StringValue>(ValidRowIndicatorParameterName, "An indicator variable in the data set that specifies which rows should be evaluated (those for which the indicator <> 0) (optional)."));
+      Parameters.Add(new ValueLookupParameter<IRandom>(RandomParameterName, "The random generator to use.") { Hidden = true });
+      Parameters.Add(new LookupParameter<ISymbolicDataAnalysisExpressionTreeInterpreter>(SymbolicDataAnalysisTreeInterpreterParameterName, "The interpreter that should be used to calculate the output values of the symbolic data analysis tree.") { Hidden = true });
+      Parameters.Add(new LookupParameter<ISymbolicExpressionTree>(SymbolicExpressionTreeParameterName, "The symbolic data analysis solution encoded as a symbolic expression tree.") { Hidden = true });
+      Parameters.Add(new ValueLookupParameter<T>(ProblemDataParameterName, "The problem data on which the symbolic data analysis solution should be evaluated.") { Hidden = true });
+      Parameters.Add(new ValueLookupParameter<IntRange>(EvaluationPartitionParameterName, "The start index of the dataset partition on which the symbolic data analysis solution should be evaluated.") { Hidden = true });
+      Parameters.Add(new ValueLookupParameter<DoubleLimit>(EstimationLimitsParameterName, "The upper and lower limit that should be used as cut off value for the output values of symbolic data analysis trees.") { Hidden = true });
+      Parameters.Add(new ValueLookupParameter<PercentValue>(RelativeNumberOfEvaluatedSamplesParameterName, "The relative number of samples of the dataset partition, which should be randomly chosen for evaluation between the start and end index.") { Hidden = true });
+      Parameters.Add(new LookupParameter<BoolValue>(ApplyLinearScalingParameterName, "Flag that indicates if the individual should be linearly scaled before evaluating.") { Hidden = true });
+      Parameters.Add(new ValueLookupParameter<StringValue>(ValidRowIndicatorParameterName, "An indicator variable in the data set that specifies which rows should be evaluated (those for which the indicator <> 0) (optional).") { Hidden = true });
     }
 
Index: branches/crossvalidation-2434/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/Evaluators/SymbolicDataAnalysisMultiObjectiveEvaluator.cs
===================================================================
--- branches/crossvalidation-2434/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/Evaluators/SymbolicDataAnalysisMultiObjectiveEvaluator.cs	(revision 13401)
+++ branches/crossvalidation-2434/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/Evaluators/SymbolicDataAnalysisMultiObjectiveEvaluator.cs	(revision 14029)
@@ -24,9 +24,10 @@
 using HeuristicLab.Core;
 using HeuristicLab.Data;
+using HeuristicLab.Encodings.SymbolicExpressionTreeEncoding;
 using HeuristicLab.Parameters;
 using HeuristicLab.Persistence.Default.CompositeSerializers.Storable;
-using HeuristicLab.Encodings.SymbolicExpressionTreeEncoding;
 
 namespace HeuristicLab.Problems.DataAnalysis.Symbolic {
+  [StorableClass]
   public abstract class SymbolicDataAnalysisMultiObjectiveEvaluator<T> : SymbolicDataAnalysisEvaluator<T>, ISymbolicDataAnalysisMultiObjectiveEvaluator<T>
    where T : class, IDataAnalysisProblemData {
Index: branches/crossvalidation-2434/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/Formatters/InfixExpressionFormatter.cs
===================================================================
--- branches/crossvalidation-2434/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/Formatters/InfixExpressionFormatter.cs	(revision 14029)
+++ branches/crossvalidation-2434/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/Formatters/InfixExpressionFormatter.cs	(revision 14029)
@@ -0,0 +1,135 @@
+#region License Information
+/* HeuristicLab
+ * Copyright (C) 2002-2016 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.Globalization;
+using System.Linq;
+using System.Text;
+using HeuristicLab.Common;
+using HeuristicLab.Core;
+using HeuristicLab.Encodings.SymbolicExpressionTreeEncoding;
+using HeuristicLab.Persistence.Default.CompositeSerializers.Storable;
+
+namespace HeuristicLab.Problems.DataAnalysis.Symbolic {
+  /// <summary>
+  /// Formats mathematical expressions in infix form. E.g. x1 * (3.0 * x2 + x3)
+  /// </summary>
+  [StorableClass]
+  [Item("Infix Symbolic Expression Tree Formatter", "A string formatter that converts symbolic expression trees to infix expressions.")]
+
+  public sealed class InfixExpressionFormatter : NamedItem, ISymbolicExpressionTreeStringFormatter {
+
+
+    [StorableConstructor]
+    private InfixExpressionFormatter(bool deserializing) : base(deserializing) { }
+    private InfixExpressionFormatter(InfixExpressionFormatter original, Cloner cloner) : base(original, cloner) { }
+    public InfixExpressionFormatter()
+      : base() {
+      Name = ItemName;
+      Description = ItemDescription;
+    }
+    public override IDeepCloneable Clone(Cloner cloner) {
+      return new InfixExpressionFormatter(this, cloner);
+    }
+
+    public string Format(ISymbolicExpressionTree symbolicExpressionTree) {
+      // skip root and start symbols
+      StringBuilder strBuilder = new StringBuilder();
+      FormatRecursively(symbolicExpressionTree.Root.GetSubtree(0).GetSubtree(0), strBuilder);
+      return strBuilder.ToString();
+    }
+
+    private void FormatRecursively(ISymbolicExpressionTreeNode node, StringBuilder strBuilder) {
+      if (node.SubtreeCount > 1) {
+        var token = GetToken(node.Symbol);
+        if (token == "+" || token == "-" || token == "OR" || token == "XOR") {
+          strBuilder.Append("(");
+          FormatRecursively(node.Subtrees.First(), strBuilder);
+
+          foreach (var subtree in node.Subtrees.Skip(1)) {
+            strBuilder.Append(" ").Append(token).Append(" ");
+            FormatRecursively(subtree, strBuilder);
+          }
+          strBuilder.Append(")");
+
+        } else if (token == "*" || token == "/" || token == "AND") {
+          strBuilder.Append("(");
+          FormatRecursively(node.Subtrees.First(), strBuilder);
+
+          foreach (var subtree in node.Subtrees.Skip(1)) {
+            strBuilder.Append(" ").Append(token).Append(" ");
+            FormatRecursively(subtree, strBuilder);
+          }
+          strBuilder.Append(")");
+        }
+      } else if (node.SubtreeCount == 1) {
+        var token = GetToken(node.Symbol);
+        if (token == "-" || token == "NOT") {
+          strBuilder.Append("(").Append(token).Append("(");
+          FormatRecursively(node.GetSubtree(0), strBuilder);
+          strBuilder.Append("))");
+        } else if (token == "/") {
+          strBuilder.Append("1/");
+          FormatRecursively(node.GetSubtree(0), strBuilder);
+        } else if (token == "+" || token == "*") {
+          FormatRecursively(node.GetSubtree(0), strBuilder);
+        } else {
+          // function
+          strBuilder.Append(token).Append("(");
+          FormatRecursively(node.GetSubtree(0), strBuilder);
+          strBuilder.Append(")");
+        }
+      } else {
+        // no subtrees
+        if (node.Symbol is Variable) {
+          var varNode = node as VariableTreeNode;
+          if (!varNode.Weight.IsAlmost(1.0)) {
+            strBuilder.Append("(");
+            strBuilder.AppendFormat(CultureInfo.InvariantCulture, "{0}", varNode.Weight);
+            strBuilder.Append("*");
+          }
+          if (varNode.VariableName.Contains("'")) {
+            strBuilder.AppendFormat("\"{0}\"", varNode.VariableName);
+          } else {
+            strBuilder.AppendFormat("'{0}'", varNode.VariableName);
+          }
+          if (!varNode.Weight.IsAlmost(1.0)) {
+            strBuilder.Append(")");
+          }
+        } else if (node.Symbol is Constant) {
+          var constNode = node as ConstantTreeNode;
+          if (constNode.Value >= 0.0)
+            strBuilder.AppendFormat(CultureInfo.InvariantCulture, "{0}", constNode.Value);
+          else
+            strBuilder.AppendFormat(CultureInfo.InvariantCulture, "({0})", constNode.Value);     // (-1)
+        }
+      }
+    }
+
+    private string GetToken(ISymbol symbol) {
+      var tok = InfixExpressionParser.knownSymbols.GetBySecond(symbol).SingleOrDefault();
+      if (tok == null)
+        throw new ArgumentException(string.Format("Unknown symbol {0} found.", symbol.Name));
+      return tok;
+    }
+  }
+}
Index: branches/crossvalidation-2434/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/Formatters/SymbolicDataAnalysisExpressionCSharpFormatter.cs
===================================================================
--- branches/crossvalidation-2434/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/Formatters/SymbolicDataAnalysisExpressionCSharpFormatter.cs	(revision 13401)
+++ branches/crossvalidation-2434/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/Formatters/SymbolicDataAnalysisExpressionCSharpFormatter.cs	(revision 14029)
@@ -56,4 +56,5 @@
 
     private void FormatRecursively(ISymbolicExpressionTreeNode node, StringBuilder strBuilder) {
+      // TODO: adapt to interpreter semantics. The HL interpreter also allows Boolean operations on reals
       if (node.Subtrees.Any()) {
         if (node.Symbol is Addition) {
@@ -83,8 +84,10 @@
         } else if (node.Symbol is Or) {
           FormatOperator(node, "||", strBuilder);
+        } else if (node.Symbol is Xor) {
+          FormatOperator(node, "^", strBuilder);
         } else if (node.Symbol is Sine) {
           FormatFunction(node, "Math.Sin", strBuilder);
         } else if (node.Symbol is Subtraction) {
-          FormatOperator(node, "-", strBuilder);
+          FormatSubtraction(node, strBuilder);
         } else if (node.Symbol is Tangent) {
           FormatFunction(node, "Math.Tan", strBuilder);
@@ -142,4 +145,14 @@
     }
 
+    private void FormatSubtraction(ISymbolicExpressionTreeNode node, StringBuilder strBuilder) {
+      if (node.SubtreeCount == 1) {
+        strBuilder.Append("-");
+        FormatRecursively(node.GetSubtree(0), strBuilder);
+        return;
+      }
+      //Default case: more than 1 child
+      FormatOperator(node, "-", strBuilder);
+    }
+
     private void FormatOperator(ISymbolicExpressionTreeNode node, string symbol, StringBuilder strBuilder) {
       strBuilder.Append("(");
@@ -176,5 +189,5 @@
       }
 
-      var orderedNames = varNames.OrderBy(n => n, new NaturalStringComparer()).Select(n=> "double " + n);
+      var orderedNames = varNames.OrderBy(n => n, new NaturalStringComparer()).Select(n => "double " + n);
       strBuilder.Append(string.Join(", ", orderedNames));
 
Index: branches/crossvalidation-2434/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/Formatters/SymbolicDataAnalysisExpressionLatexFormatter.cs
===================================================================
--- branches/crossvalidation-2434/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/Formatters/SymbolicDataAnalysisExpressionLatexFormatter.cs	(revision 13401)
+++ branches/crossvalidation-2434/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/Formatters/SymbolicDataAnalysisExpressionLatexFormatter.cs	(revision 14029)
@@ -403,5 +403,5 @@
             var constStr = string.Format(System.Globalization.NumberFormatInfo.InvariantInfo, "{0:G5}", constant);
             if (!constStr.Contains(".")) constStr = constStr + ".0";
-            constStr = constStr.Replace(".", "\\negthickspace&.");  // fix problem in rendering of aligned expressions
+            constStr = constStr.Replace(".", "&.");  // fix problem in rendering of aligned expressions
             strBuilder.Append("c_{" + i + "}& = & " + constStr);
             strBuilder.Append(@"\\");
Index: branches/crossvalidation-2434/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/Formatters/SymbolicDataAnalysisExpressionMathematicaFormatter.cs
===================================================================
--- branches/crossvalidation-2434/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/Formatters/SymbolicDataAnalysisExpressionMathematicaFormatter.cs	(revision 14029)
+++ branches/crossvalidation-2434/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/Formatters/SymbolicDataAnalysisExpressionMathematicaFormatter.cs	(revision 14029)
@@ -0,0 +1,231 @@
+﻿#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.Globalization;
+using System.Linq;
+using System.Text;
+using HeuristicLab.Common;
+using HeuristicLab.Core;
+using HeuristicLab.Encodings.SymbolicExpressionTreeEncoding;
+using HeuristicLab.Persistence.Default.CompositeSerializers.Storable;
+
+namespace HeuristicLab.Problems.DataAnalysis.Symbolic {
+  [Item("Mathematica Symbolic Expression Tree Formatter", "A string formatter that converts symbolic expression trees to Mathematica expressions.")]
+  [StorableClass]
+  public sealed class SymbolicDataAnalysisExpressionMathematicaFormatter : NamedItem, ISymbolicExpressionTreeStringFormatter {
+    [StorableConstructor]
+    private SymbolicDataAnalysisExpressionMathematicaFormatter(bool deserializing) : base(deserializing) { }
+    private SymbolicDataAnalysisExpressionMathematicaFormatter(SymbolicDataAnalysisExpressionMathematicaFormatter original, Cloner cloner) : base(original, cloner) { }
+    public SymbolicDataAnalysisExpressionMathematicaFormatter()
+      : base() {
+      Name = ItemName;
+      Description = ItemDescription;
+    }
+    public override IDeepCloneable Clone(Cloner cloner) {
+      return new SymbolicDataAnalysisExpressionMathematicaFormatter(this, cloner);
+    }
+
+    public string Format(ISymbolicExpressionTree symbolicExpressionTree) {
+      // skip root and start symbols
+      StringBuilder strBuilder = new StringBuilder();
+      FormatRecursively(symbolicExpressionTree.Root.GetSubtree(0).GetSubtree(0), strBuilder);
+      return strBuilder.ToString();
+    }
+
+    private void FormatRecursively(ISymbolicExpressionTreeNode node, StringBuilder strBuilder) {
+      if (node.Subtrees.Any()) {
+        if (node.Symbol is Addition) {
+          FormatFunction(node, "Plus", strBuilder);
+        } else if (node.Symbol is Average) {
+          FormatAverage(node, strBuilder);
+        } else if (node.Symbol is Multiplication) {
+          FormatFunction(node, "Times", strBuilder);
+        } else if (node.Symbol is Subtraction) {
+          FormatSubtraction(node, strBuilder);
+        } else if (node.Symbol is Division) {
+          FormatDivision(node, strBuilder);
+        } else if (node.Symbol is Sine) {
+          FormatFunction(node, "Sin", strBuilder);
+        } else if (node.Symbol is Cosine) {
+          FormatFunction(node, "Cos", strBuilder);
+        } else if (node.Symbol is Tangent) {
+          FormatFunction(node, "Tan", strBuilder);
+        } else if (node.Symbol is Exponential) {
+          FormatFunction(node, "Exp", strBuilder);
+        } else if (node.Symbol is Logarithm) {
+          FormatFunction(node, "Log", strBuilder);
+        } else if (node.Symbol is IfThenElse) {
+          FormatIf(node, strBuilder);
+        } else if (node.Symbol is GreaterThan) {
+          strBuilder.Append("If[Greater[");
+          FormatRecursively(node.GetSubtree(0), strBuilder);
+          strBuilder.Append(",");
+          FormatRecursively(node.GetSubtree(1), strBuilder);
+          strBuilder.Append("], 1, -1]");
+        } else if (node.Symbol is LessThan) {
+          strBuilder.Append("If[Less[");
+          FormatRecursively(node.GetSubtree(0), strBuilder);
+          strBuilder.Append(",");
+          FormatRecursively(node.GetSubtree(1), strBuilder);
+          strBuilder.Append("], 1, -1]");
+        } else if (node.Symbol is And) {
+          FormatAnd(node, strBuilder);
+        } else if (node.Symbol is Not) {
+          strBuilder.Append("If[Greater[");
+          FormatRecursively(node.GetSubtree(0), strBuilder);
+          strBuilder.Append(", 0], -1, 1]");
+        } else if (node.Symbol is Or) {
+          FormatOr(node, strBuilder);
+        } else if (node.Symbol is Xor) {
+          FormatXor(node, strBuilder);
+        } else if (node.Symbol is Square) {
+          FormatSquare(node, strBuilder);
+        } else if (node.Symbol is SquareRoot) {
+          FormatFunction(node, "Sqrt", strBuilder);
+        } else if (node.Symbol is Power) {
+          FormatFunction(node, "Power", strBuilder);
+        } else if (node.Symbol is Root) {
+          FormatRoot(node, strBuilder);
+        } else {
+          throw new NotSupportedException("Formatting of symbol: " + node.Symbol + " is not supported.");
+        }
+      } else {
+        if (node is VariableTreeNode) {
+          var varNode = node as VariableTreeNode;
+          strBuilder.AppendFormat("Times[{0}, {1}]", varNode.VariableName, varNode.Weight.ToString("G17", CultureInfo.InvariantCulture));
+        } else if (node is ConstantTreeNode) {
+          var constNode = node as ConstantTreeNode;
+          strBuilder.Append(constNode.Value.ToString("G17", CultureInfo.InvariantCulture));
+        } else {
+          throw new NotSupportedException("Formatting of symbol: " + node.Symbol + " is not supported.");
+        }
+      }
+    }
+
+    private void FormatXor(ISymbolicExpressionTreeNode node, StringBuilder strBuilder) {
+      strBuilder.Append("If[Xor[");
+      foreach (var t in node.Subtrees) {
+        strBuilder.Append("Greater[");
+        FormatRecursively(t, strBuilder);
+        strBuilder.Append(", 0]");
+        if (t != node.Subtrees.Last()) strBuilder.Append(",");
+      }
+      strBuilder.Append("], 1, -1]");
+    }
+
+    private void FormatOr(ISymbolicExpressionTreeNode node, StringBuilder strBuilder) {
+      strBuilder.Append("If[Or[");
+      foreach (var t in node.Subtrees) {
+        strBuilder.Append("Greater[");
+        FormatRecursively(t, strBuilder);
+        strBuilder.Append(", 0]");
+        if (t != node.Subtrees.Last()) strBuilder.Append(",");
+      }
+      strBuilder.Append("], 1, -1]");
+    }
+
+    private void FormatAnd(ISymbolicExpressionTreeNode node, StringBuilder strBuilder) {
+      strBuilder.Append("If[And[");
+      foreach (var t in node.Subtrees) {
+        strBuilder.Append("Greater[");
+        FormatRecursively(t, strBuilder);
+        strBuilder.Append(", 0]");
+        if (t != node.Subtrees.Last()) strBuilder.Append(",");
+      }
+      strBuilder.Append("], 1, -1]");
+    }
+
+    private void FormatIf(ISymbolicExpressionTreeNode node, StringBuilder strBuilder) {
+      strBuilder.Append("If[Greater[");
+      FormatRecursively(node.GetSubtree(0), strBuilder);
+      strBuilder.Append(", 0], ");
+      FormatRecursively(node.GetSubtree(1), strBuilder);
+      strBuilder.Append(", ");
+      FormatRecursively(node.GetSubtree(2), strBuilder);
+      strBuilder.Append("]");
+    }
+
+    private void FormatAverage(ISymbolicExpressionTreeNode node, StringBuilder strBuilder) {
+      // mean function needs a list of values
+      strBuilder.Append("Mean[{");
+      FormatRecursively(node.GetSubtree(0), strBuilder);
+      for (int i = 1; i < node.SubtreeCount; i++) {
+        strBuilder.Append(",");
+        FormatRecursively(node.GetSubtree(i), strBuilder);
+      }
+      strBuilder.Append("}]");
+    }
+
+    private void FormatSubtraction(ISymbolicExpressionTreeNode node, StringBuilder strBuilder) {
+      strBuilder.Append("Subtract[");
+      FormatRecursively(node.GetSubtree(0), strBuilder);
+      strBuilder.Append(", Times[-1");
+      foreach (var t in node.Subtrees) {
+        strBuilder.Append(",");
+        FormatRecursively(t, strBuilder);
+      }
+      strBuilder.Append("]]");
+    }
+
+    private void FormatSquare(ISymbolicExpressionTreeNode node, StringBuilder strBuilder) {
+      strBuilder.Append("Power[");
+      FormatRecursively(node.GetSubtree(0), strBuilder);
+      strBuilder.Append(", 2]");
+    }
+
+    private void FormatRoot(ISymbolicExpressionTreeNode node, StringBuilder strBuilder) {
+      strBuilder.Append("Power[");
+      FormatRecursively(node.GetSubtree(0), strBuilder);
+      strBuilder.Append(", Divide[1,");
+      FormatRecursively(node.GetSubtree(1), strBuilder);
+      strBuilder.Append("]]");
+    }
+
+    private void FormatDivision(ISymbolicExpressionTreeNode node, StringBuilder strBuilder) {
+      if (node.SubtreeCount == 1) {
+        strBuilder.Append("Divide[1, ");
+        FormatRecursively(node.GetSubtree(0), strBuilder);
+        strBuilder.Append("]");
+      } else {
+        strBuilder.Append("Divide[");
+        FormatRecursively(node.GetSubtree(0), strBuilder);
+        strBuilder.Append(", Times[");
+        FormatRecursively(node.GetSubtree(1), strBuilder);
+        for (int i = 2; i < node.SubtreeCount; i++) {
+          strBuilder.Append(",");
+          FormatRecursively(node.GetSubtree(i), strBuilder);
+        }
+        strBuilder.Append("]]");
+      }
+    }
+
+    private void FormatFunction(ISymbolicExpressionTreeNode node, string function, StringBuilder strBuilder) {
+      strBuilder.Append(function + "[");
+      foreach (var child in node.Subtrees) {
+        FormatRecursively(child, strBuilder);
+        if (child != node.Subtrees.Last())
+          strBuilder.Append(", ");
+      }
+      strBuilder.Append("]");
+    }
+  }
+}
Index: branches/crossvalidation-2434/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/HeuristicLab.Problems.DataAnalysis.Symbolic-3.4.csproj
===================================================================
--- branches/crossvalidation-2434/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/HeuristicLab.Problems.DataAnalysis.Symbolic-3.4.csproj	(revision 13401)
+++ branches/crossvalidation-2434/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/HeuristicLab.Problems.DataAnalysis.Symbolic-3.4.csproj	(revision 14029)
@@ -133,8 +133,14 @@
       <SubType>Code</SubType>
     </Compile>
+    <Compile Include="Formatters\InfixExpressionFormatter.cs" />
+    <Compile Include="Formatters\SymbolicDataAnalysisExpressionMathematicaFormatter.cs" />
     <Compile Include="Formatters\SymbolicDataAnalysisExpressionCSharpFormatter.cs" />
+    <Compile Include="Importer\InfixExpressionParser.cs" />
     <Compile Include="Importer\SymbolicExpressionImporter.cs" />
     <Compile Include="Importer\Token.cs" />
     <Compile Include="Interfaces\IModelBacktransformator.cs" />
+    <Compile Include="Interpreter\SymbolicDataAnalysisExpressionCompiledTreeInterpreter.cs" />
+    <Compile Include="SymbolicDataAnalysisExpressionTreeSimplificationOperator.cs" />
+    <Compile Include="SymbolicDataAnalysisModelComplexityCalculator.cs" />
     <Compile Include="SymbolicExpressionTreeBacktransformator.cs" />
     <Compile Include="SymbolicDataAnalysisExpressionPruningOperator.cs" />
Index: branches/crossvalidation-2434/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/Importer/InfixExpressionParser.cs
===================================================================
--- branches/crossvalidation-2434/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/Importer/InfixExpressionParser.cs	(revision 14029)
+++ branches/crossvalidation-2434/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/Importer/InfixExpressionParser.cs	(revision 14029)
@@ -0,0 +1,372 @@
+#region License Information
+/* HeuristicLab
+ * Copyright (C) 2002-2016 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.Globalization;
+using System.Linq;
+using System.Text;
+using HeuristicLab.Collections;
+using HeuristicLab.Encodings.SymbolicExpressionTreeEncoding;
+
+namespace HeuristicLab.Problems.DataAnalysis.Symbolic {
+  /// <summary>
+  /// Parses mathematical expressions in infix form. E.g. x1 * (3.0 * x2 + x3)
+  /// Identifier format (functions or variables): '_' | letter { '_' | letter | digit }
+  /// Variables names can be set under quotes "" or '' because variable names might contain spaces. 
+  /// It is also possible to use functions e.g. log("x1") or real-valued constants e.g. 3.1415 . 
+  /// Variable names are case sensitive. Function names are not case sensitive.
+  /// </summary>
+  public sealed class InfixExpressionParser {
+    private enum TokenType { Operator, Identifier, Number, LeftPar, RightPar, End, NA };
+    private class Token {
+      internal double doubleVal;
+      internal string strVal;
+      internal TokenType TokenType;
+    }
+
+    private class SymbolNameComparer : IEqualityComparer<ISymbol>, IComparer<ISymbol> {
+      public int Compare(ISymbol x, ISymbol y) {
+        return x.Name.CompareTo(y.Name);
+      }
+
+      public bool Equals(ISymbol x, ISymbol y) {
+        return Compare(x, y) == 0;
+      }
+
+      public int GetHashCode(ISymbol obj) {
+        return obj.Name.GetHashCode();
+      }
+    }
+    // format name <-> symbol 
+    // the lookup table is also used in the corresponding formatter
+    internal static readonly BidirectionalLookup<string, ISymbol>
+      knownSymbols = new BidirectionalLookup<string, ISymbol>(StringComparer.InvariantCulture, new SymbolNameComparer());
+
+    private Constant constant = new Constant();
+    private Variable variable = new Variable();
+
+    private ProgramRootSymbol programRootSymbol = new ProgramRootSymbol();
+    private StartSymbol startSymbol = new StartSymbol();
+
+    static InfixExpressionParser() {
+      // populate bidirectional lookup
+      var dict = new Dictionary<string, ISymbol>
+      {
+        { "+", new Addition()},
+        { "/", new Division()},
+        { "*", new Multiplication()},
+        { "-", new Subtraction()},
+        { "EXP", new Exponential()},
+        { "LOG", new Logarithm()},
+        { "POW", new Power()},
+        { "ROOT", new Root()},
+        { "SQR", new Square() },
+        { "SQRT", new SquareRoot() },
+        { "SIN",new Sine()},
+        { "COS", new Cosine()},
+        { "TAN", new Tangent()},
+        { "AIRYA", new AiryA()},
+        { "AIRYB", new AiryB()},
+        { "BESSEL", new Bessel()},
+        { "COSINT", new CosineIntegral()},
+        { "SININT", new SineIntegral()},
+        { "HYPCOSINT", new HyperbolicCosineIntegral()},
+        { "HYPSININT", new HyperbolicSineIntegral()},
+        { "FRESNELSININT", new FresnelSineIntegral()},
+        { "FRESNELCOSINT", new FresnelCosineIntegral()},
+        { "NORM", new Norm()},
+        { "ERF", new Erf()},
+        { "GAMMA", new Gamma()},
+        { "PSI", new Psi()},
+        { "DAWSON", new Dawson()},
+        { "EXPINT", new ExponentialIntegralEi()},
+        { "MEAN", new Average()},
+        { "IF", new IfThenElse()},
+        { ">", new GreaterThan()},
+        { "<", new LessThan()},
+        { "AND", new And()},
+        { "OR", new Or()},
+        { "NOT", new Not()},
+        { "XOR", new Xor()},
+        { "DIFF", new Derivative()},
+      };
+
+
+      foreach (var kvp in dict) {
+        knownSymbols.Add(kvp.Key, kvp.Value);
+      }
+    }
+
+    public ISymbolicExpressionTree Parse(string str) {
+      ISymbolicExpressionTreeNode root = programRootSymbol.CreateTreeNode();
+      ISymbolicExpressionTreeNode start = startSymbol.CreateTreeNode();
+      var allTokens = GetAllTokens(str).ToArray();
+      ISymbolicExpressionTreeNode mainBranch = ParseS(new Queue<Token>(allTokens));
+
+      // only a main branch was given => insert the main branch into the default tree template
+      root.AddSubtree(start);
+      start.AddSubtree(mainBranch);
+      return new SymbolicExpressionTree(root);
+    }
+
+    private IEnumerable<Token> GetAllTokens(string str) {
+      int pos = 0;
+      while (true) {
+        while (pos < str.Length && Char.IsWhiteSpace(str[pos])) pos++;
+        if (pos >= str.Length) {
+          yield return new Token { TokenType = TokenType.End, strVal = "" };
+          yield break;
+        }
+        if (char.IsDigit(str[pos])) {
+          // read number (=> read until white space or operator)
+          var sb = new StringBuilder();
+          sb.Append(str[pos]);
+          pos++;
+          while (pos < str.Length && !char.IsWhiteSpace(str[pos])
+            && (str[pos] != '+' || str[pos-1] == 'e' || str[pos-1] == 'E')     // continue reading exponents
+            && (str[pos] != '-' || str[pos - 1] == 'e' || str[pos - 1] == 'E')
+            && str[pos] != '*'           
+            && str[pos] != '/'
+            && str[pos] != ')') {
+            sb.Append(str[pos]);
+            pos++;
+          }
+          double dblVal;
+          if (double.TryParse(sb.ToString(), NumberStyles.Float, CultureInfo.InvariantCulture, out dblVal))
+            yield return new Token { TokenType = TokenType.Number, strVal = sb.ToString(), doubleVal = dblVal };
+          else yield return new Token { TokenType = TokenType.NA, strVal = sb.ToString() };
+        } else if (char.IsLetter(str[pos]) || str[pos] == '_') {
+          // read ident
+          var sb = new StringBuilder();
+          sb.Append(str[pos]);
+          pos++;
+          while (pos < str.Length &&
+            (char.IsLetter(str[pos]) || str[pos] == '_' || char.IsDigit(str[pos]))) {
+            sb.Append(str[pos]);
+            pos++;
+          }
+          yield return new Token { TokenType = TokenType.Identifier, strVal = sb.ToString() };
+        } else if (str[pos] == '"') {
+          // read to next " 
+          pos++;
+          var sb = new StringBuilder();
+          while (pos < str.Length && str[pos] != '"') {
+            sb.Append(str[pos]);
+            pos++;
+          }
+          if (pos < str.Length && str[pos] == '"') {
+            pos++; // skip "
+            yield return new Token { TokenType = TokenType.Identifier, strVal = sb.ToString() };
+          } else
+            yield return new Token { TokenType = TokenType.NA };
+
+        } else if (str[pos] == '\'') {
+          // read to next '
+          pos++;
+          var sb = new StringBuilder();
+          while (pos < str.Length && str[pos] != '\'') {
+            sb.Append(str[pos]);
+            pos++;
+          }
+          if (pos < str.Length && str[pos] == '\'') {
+            pos++; // skip '
+            yield return new Token { TokenType = TokenType.Identifier, strVal = sb.ToString() };
+          } else
+            yield return new Token { TokenType = TokenType.NA };
+        } else if (str[pos] == '+') {
+          pos++;
+          yield return new Token { TokenType = TokenType.Operator, strVal = "+" };
+        } else if (str[pos] == '-') {
+          pos++;
+          yield return new Token { TokenType = TokenType.Operator, strVal = "-" };
+        } else if (str[pos] == '/') {
+          pos++;
+          yield return new Token { TokenType = TokenType.Operator, strVal = "/" };
+        } else if (str[pos] == '*') {
+          pos++;
+          yield return new Token { TokenType = TokenType.Operator, strVal = "*" };
+        } else if (str[pos] == '(') {
+          pos++;
+          yield return new Token { TokenType = TokenType.LeftPar, strVal = "(" };
+        } else if (str[pos] == ')') {
+          pos++;
+          yield return new Token { TokenType = TokenType.RightPar, strVal = ")" };
+        }
+      }
+    }
+
+    // S = Expr EOF
+    // Expr = ['-' | '+'] Term { '+' Term | '-' Term }
+    // Term = Fact { '*' Fact | '/' Fact }
+    // Fact = '(' Expr ')' | funcId '(' Expr ')' | varId | number
+    private ISymbolicExpressionTreeNode ParseS(Queue<Token> tokens) {
+      var expr = ParseExpr(tokens);
+
+      var endTok = tokens.Dequeue();
+      if (endTok.TokenType != TokenType.End)
+        throw new ArgumentException(string.Format("Expected end of expression (got {0})", endTok.strVal));
+
+      return expr;
+    }
+    private ISymbolicExpressionTreeNode ParseExpr(Queue<Token> tokens) {
+      var next = tokens.Peek();
+      var posTerms = new List<ISymbolicExpressionTreeNode>();
+      var negTerms = new List<ISymbolicExpressionTreeNode>();
+      bool negateFirstTerm = false;
+      if (next.TokenType == TokenType.Operator && (next.strVal == "+" || next.strVal == "-")) {
+        tokens.Dequeue();
+        if (next.strVal == "-")
+          negateFirstTerm = true;
+      }
+      var t = ParseTerm(tokens);
+      if (negateFirstTerm) negTerms.Add(t);
+      else posTerms.Add(t);
+
+      next = tokens.Peek();
+      while (next.strVal == "+" || next.strVal == "-") {
+        switch (next.strVal) {
+          case "+": {
+              tokens.Dequeue();
+              var term = ParseTerm(tokens);
+              posTerms.Add(term);
+              break;
+            }
+          case "-": {
+              tokens.Dequeue();
+              var term = ParseTerm(tokens);
+              negTerms.Add(term);
+              break;
+            }
+        }
+        next = tokens.Peek();
+      }
+
+      var sum = GetSymbol("+").CreateTreeNode();
+      foreach (var posTerm in posTerms) sum.AddSubtree(posTerm);
+      if (negTerms.Any()) {
+        if (negTerms.Count == 1) {
+          var sub = GetSymbol("-").CreateTreeNode();
+          sub.AddSubtree(negTerms.Single());
+          sum.AddSubtree(sub);
+        } else {
+          var sumNeg = GetSymbol("+").CreateTreeNode();
+          foreach (var negTerm in negTerms) sumNeg.AddSubtree(negTerm);
+
+          var constNode = (ConstantTreeNode)constant.CreateTreeNode();
+          constNode.Value = -1.0;
+          var prod = GetSymbol("*").CreateTreeNode();
+          prod.AddSubtree(constNode);
+          prod.AddSubtree(sumNeg);
+
+          sum.AddSubtree(prod);
+        }
+      }
+      if (sum.SubtreeCount == 1) return sum.Subtrees.First();
+      else return sum;
+    }
+
+    private ISymbol GetSymbol(string tok) {
+      var symb = knownSymbols.GetByFirst(tok).FirstOrDefault();
+      if (symb == null) throw new ArgumentException(string.Format("Unknown token {0} found.", tok));
+      return symb;
+    }
+
+    // Term = Fact { '*' Fact | '/' Fact }
+    private ISymbolicExpressionTreeNode ParseTerm(Queue<Token> tokens) {
+      var factors = new List<ISymbolicExpressionTreeNode>();
+      var firstFactor = ParseFact(tokens);
+      factors.Add(firstFactor);
+
+      var next = tokens.Peek();
+      while (next.strVal == "*" || next.strVal == "/") {
+        switch (next.strVal) {
+          case "*": {
+              tokens.Dequeue();
+              var fact = ParseFact(tokens);
+              factors.Add(fact);
+              break;
+            }
+          case "/": {
+              tokens.Dequeue();
+              var invFact = ParseFact(tokens);
+              var divNode = GetSymbol("/").CreateTreeNode(); // 1/x
+              divNode.AddSubtree(invFact);
+              factors.Add(divNode);
+              break;
+            }
+        }
+
+        next = tokens.Peek();
+      }
+      if (factors.Count == 1) return factors.First();
+      else {
+        var prod = GetSymbol("*").CreateTreeNode();
+        foreach (var f in factors) prod.AddSubtree(f);
+        return prod;
+      }
+    }
+
+    // Fact = '(' Expr ')' | funcId '(' Expr ')' | varId | number
+    private ISymbolicExpressionTreeNode ParseFact(Queue<Token> tokens) {
+      var next = tokens.Peek();
+      if (next.TokenType == TokenType.LeftPar) {
+        tokens.Dequeue();
+        var expr = ParseExpr(tokens);
+        var rPar = tokens.Dequeue();
+        if (rPar.TokenType != TokenType.RightPar)
+          throw new ArgumentException("expected )");
+        return expr;
+      } else if (next.TokenType == TokenType.Identifier) {
+        var idTok = tokens.Dequeue();
+        if (tokens.Peek().TokenType == TokenType.LeftPar) {
+          // function identifier
+          var funcId = idTok.strVal.ToUpperInvariant();
+
+          var funcNode = GetSymbol(funcId).CreateTreeNode();
+          var lPar = tokens.Dequeue();
+          if (lPar.TokenType != TokenType.LeftPar)
+            throw new ArgumentException("expected (");
+          var expr = ParseExpr(tokens);
+          var rPar = tokens.Dequeue();
+          if (rPar.TokenType != TokenType.RightPar)
+            throw new ArgumentException("expected )");
+
+          funcNode.AddSubtree(expr);
+          return funcNode;
+        } else {
+          // variable
+          var varNode = (VariableTreeNode)variable.CreateTreeNode();
+          varNode.Weight = 1.0;
+          varNode.VariableName = idTok.strVal;
+          return varNode;
+        }
+      } else if (next.TokenType == TokenType.Number) {
+        var numTok = tokens.Dequeue();
+        var constNode = (ConstantTreeNode)constant.CreateTreeNode();
+        constNode.Value = numTok.doubleVal;
+        return constNode;
+      } else {
+        throw new ArgumentException(string.Format("unexpected token in expression {0}", next.strVal));
+      }
+    }
+  }
+}
Index: branches/crossvalidation-2434/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/Interfaces/ISymbolicDataAnalysisExpressionTreeInterpreter.cs
===================================================================
--- branches/crossvalidation-2434/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/Interfaces/ISymbolicDataAnalysisExpressionTreeInterpreter.cs	(revision 13401)
+++ branches/crossvalidation-2434/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/Interfaces/ISymbolicDataAnalysisExpressionTreeInterpreter.cs	(revision 14029)
@@ -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: branches/crossvalidation-2434/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/Interpreter/SymbolicDataAnalysisExpressionCompiledTreeInterpreter.cs
===================================================================
--- branches/crossvalidation-2434/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/Interpreter/SymbolicDataAnalysisExpressionCompiledTreeInterpreter.cs	(revision 14029)
+++ branches/crossvalidation-2434/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/Interpreter/SymbolicDataAnalysisExpressionCompiledTreeInterpreter.cs	(revision 14029)
@@ -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: branches/crossvalidation-2434/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/Interpreter/SymbolicDataAnalysisExpressionTreeILEmittingInterpreter.cs
===================================================================
--- branches/crossvalidation-2434/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/Interpreter/SymbolicDataAnalysisExpressionTreeILEmittingInterpreter.cs	(revision 13401)
+++ branches/crossvalidation-2434/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/Interpreter/SymbolicDataAnalysisExpressionTreeILEmittingInterpreter.cs	(revision 14029)
@@ -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);
 
Index: branches/crossvalidation-2434/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/Interpreter/SymbolicDataAnalysisExpressionTreeInterpreter.cs
===================================================================
--- branches/crossvalidation-2434/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/Interpreter/SymbolicDataAnalysisExpressionTreeInterpreter.cs	(revision 13401)
+++ branches/crossvalidation-2434/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/Interpreter/SymbolicDataAnalysisExpressionTreeInterpreter.cs	(revision 14029)
@@ -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: branches/crossvalidation-2434/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/Interpreter/SymbolicDataAnalysisExpressionTreeLinearInterpreter.cs
===================================================================
--- branches/crossvalidation-2434/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/Interpreter/SymbolicDataAnalysisExpressionTreeLinearInterpreter.cs	(revision 13401)
+++ branches/crossvalidation-2434/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/Interpreter/SymbolicDataAnalysisExpressionTreeLinearInterpreter.cs	(revision 14029)
@@ -35,4 +35,5 @@
   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";
 
@@ -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
@@ -84,6 +85,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 +99,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 +123,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
       }
 
@@ -122,6 +144,8 @@
         if (instr.opCode == OpCodes.Variable) {
           if (row < 0 || row >= dataset.Rows) instr.value = double.NaN;
-          var variableTreeNode = (VariableTreeNode)instr.dynamicNode;
-          instr.value = ((IList<double>)instr.data)[row] * variableTreeNode.Weight;
+          else {
+            var variableTreeNode = (VariableTreeNode)instr.dynamicNode;
+            instr.value = ((IList<double>)instr.data)[row] * variableTreeNode.Weight;
+          }
         } else if (instr.opCode == OpCodes.LagVariable) {
           var laggedVariableTreeNode = (LaggedVariableTreeNode)instr.dynamicNode;
@@ -190,5 +214,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: branches/crossvalidation-2434/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/Plugin.cs.frame
===================================================================
--- branches/crossvalidation-2434/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/Plugin.cs.frame	(revision 13401)
+++ branches/crossvalidation-2434/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/Plugin.cs.frame	(revision 14029)
@@ -26,5 +26,5 @@
 
 namespace HeuristicLab.Problems.DataAnalysis.Symbolic {
-  [Plugin("HeuristicLab.Problems.DataAnalysis.Symbolic","Provides base classes for symbolic data analysis tasks.", "3.4.8.$WCREV$")]
+  [Plugin("HeuristicLab.Problems.DataAnalysis.Symbolic","Provides base classes for symbolic data analysis tasks.", "3.4.9.$WCREV$")]
   [PluginFile("HeuristicLab.Problems.DataAnalysis.Symbolic-3.4.dll", PluginFileType.Assembly)]
   [PluginDependency("HeuristicLab.ALGLIB", "3.7.0")]
Index: branches/crossvalidation-2434/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/Properties/AssemblyInfo.cs.frame
===================================================================
--- branches/crossvalidation-2434/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/Properties/AssemblyInfo.cs.frame	(revision 13401)
+++ branches/crossvalidation-2434/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/Properties/AssemblyInfo.cs.frame	(revision 14029)
@@ -53,3 +53,3 @@
 // by using the '*' as shown below:
 [assembly: AssemblyVersion("3.4.0.0")]
-[assembly: AssemblyFileVersion("3.4.8.$WCREV$")]
+[assembly: AssemblyFileVersion("3.4.9.$WCREV$")]
Index: branches/crossvalidation-2434/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/SymbolicDataAnalysisExpressionTreeSimplificationOperator.cs
===================================================================
--- branches/crossvalidation-2434/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/SymbolicDataAnalysisExpressionTreeSimplificationOperator.cs	(revision 14029)
+++ branches/crossvalidation-2434/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/SymbolicDataAnalysisExpressionTreeSimplificationOperator.cs	(revision 14029)
@@ -0,0 +1,62 @@
+﻿#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 HeuristicLab.Common;
+using HeuristicLab.Core;
+using HeuristicLab.Encodings.SymbolicExpressionTreeEncoding;
+using HeuristicLab.Operators;
+using HeuristicLab.Parameters;
+using HeuristicLab.Persistence.Default.CompositeSerializers.Storable;
+
+namespace HeuristicLab.Problems.DataAnalysis.Symbolic {
+  [Item("SymbolicExpressionTreeSimplificationOperator", "Simplifies symbolic expression trees encoding a mathematical formula.")]
+  [StorableClass]
+  public class SymbolicDataAnalysisExpressionTreeSimplificationOperator : SingleSuccessorOperator, ISymbolicExpressionTreeOperator {
+    private const string SymbolicExpressionTreeParameterName = "SymbolicExpressionTree";
+
+    public ILookupParameter<ISymbolicExpressionTree> SymbolicExpressionTreeParameter {
+      get { return (ILookupParameter<ISymbolicExpressionTree>)Parameters[SymbolicExpressionTreeParameterName]; }
+    }
+
+    private readonly SymbolicDataAnalysisExpressionTreeSimplifier simplifier = new SymbolicDataAnalysisExpressionTreeSimplifier();
+
+    [StorableConstructor]
+    protected SymbolicDataAnalysisExpressionTreeSimplificationOperator(bool deserializing) : base(deserializing) { }
+    protected SymbolicDataAnalysisExpressionTreeSimplificationOperator(SymbolicDataAnalysisExpressionTreeSimplificationOperator original, Cloner cloner)
+      : base(original, cloner) { }
+    public override IDeepCloneable Clone(Cloner cloner) {
+      return new SymbolicDataAnalysisExpressionTreeSimplificationOperator(this, cloner);
+    }
+
+    public SymbolicDataAnalysisExpressionTreeSimplificationOperator() {
+      Parameters.Add(new LookupParameter<ISymbolicExpressionTree>(SymbolicExpressionTreeParameterName, "The symbolic expression tree to simplify."));
+    }
+
+    public override IOperation Apply() {
+      var tree = SymbolicExpressionTreeParameter.ActualValue;
+      var simplifiedTree = simplifier.Simplify(tree);
+      simplifiedTree = simplifier.Simplify(simplifiedTree);
+      SymbolicExpressionTreeParameter.ActualValue = simplifiedTree;
+
+      return base.Apply();
+    }
+  }
+}
Index: branches/crossvalidation-2434/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/SymbolicDataAnalysisModel.cs
===================================================================
--- branches/crossvalidation-2434/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/SymbolicDataAnalysisModel.cs	(revision 13401)
+++ branches/crossvalidation-2434/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/SymbolicDataAnalysisModel.cs	(revision 14029)
@@ -21,5 +21,7 @@
 
 using System;
+using System.Collections.Generic;
 using System.Drawing;
+using System.Linq;
 using HeuristicLab.Common;
 using HeuristicLab.Core;
@@ -56,4 +58,19 @@
       get { return interpreter; }
     }
+
+    public IEnumerable<string> VariablesUsedForPrediction {
+      get {
+        var variables =
+          SymbolicExpressionTree.IterateNodesPrefix()
+            .OfType<VariableTreeNode>()
+            .Select(x => x.VariableName)
+            .Distinct();
+        var variableConditions = SymbolicExpressionTree.IterateNodesPrefix()
+          .OfType<VariableConditionTreeNode>().Select(x => x.VariableName).Distinct();
+
+        return variables.Union(variableConditions).OrderBy(x => x);
+      }
+    }
+
     #endregion
 
@@ -160,4 +177,5 @@
     }
     #endregion
+
   }
 }
Index: branches/crossvalidation-2434/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/SymbolicDataAnalysisModelComplexityCalculator.cs
===================================================================
--- branches/crossvalidation-2434/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/SymbolicDataAnalysisModelComplexityCalculator.cs	(revision 14029)
+++ branches/crossvalidation-2434/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/SymbolicDataAnalysisModelComplexityCalculator.cs	(revision 14029)
@@ -0,0 +1,97 @@
+﻿#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 HeuristicLab.Encodings.SymbolicExpressionTreeEncoding;
+
+namespace HeuristicLab.Problems.DataAnalysis.Symbolic {
+  public static class SymbolicDataAnalysisModelComplexityCalculator {
+    public static double CalculateComplexity(ISymbolicExpressionTree tree) {
+      return CalculateComplexity(tree.Root);
+    }
+    public static double CalculateComplexity(ISymbolicExpressionTreeNode treeNode) {
+      var node = treeNode;
+      if (node.Symbol is ProgramRootSymbol) node = node.GetSubtree(0);
+      if (node.Symbol is StartSymbol) node = node.GetSubtree(0);
+
+      switch (OpCodes.MapSymbolToOpCode(node)) {
+        case OpCodes.Constant: {
+            return 1;
+          }
+        case OpCodes.Variable: {
+            return 2;
+          }
+        case OpCodes.Add: 
+        case OpCodes.Sub: {
+            double complexity = 0;
+            for (int i = 0; i < node.SubtreeCount; i++) {
+              complexity += CalculateComplexity(node.GetSubtree(i));
+            }
+            return complexity;
+          }
+        case OpCodes.Mul: 
+        case OpCodes.Div: {
+            double complexity = 1;
+            for (int i = 0; i < node.SubtreeCount; i++) {
+              var nodeComplexity = CalculateComplexity(node.GetSubtree(i));
+              complexity *= nodeComplexity + 1;
+            }
+            return complexity;
+          }
+        case OpCodes.Sin:
+        case OpCodes.Cos: 
+        case OpCodes.Tan:
+        case OpCodes.Exp: 
+        case OpCodes.Log: {
+            double complexity = CalculateComplexity(node.GetSubtree(0));
+            return Math.Pow(2.0, complexity);
+          }
+        case OpCodes.Square: {
+            double complexity = CalculateComplexity(node.GetSubtree(0));
+            return complexity * complexity;
+          }
+        case OpCodes.SquareRoot: {
+            double complexity = CalculateComplexity(node.GetSubtree(0));
+            return complexity * complexity * complexity;
+          }
+        case OpCodes.Power:          
+        case OpCodes.Root: {
+            double complexity = CalculateComplexity(node.GetSubtree(0));
+            var exponent = node.GetSubtree(1) as ConstantTreeNode;
+            if (exponent != null) {
+              double expVal = exponent.Value;
+              if (expVal < 0) expVal = Math.Abs(expVal);
+              if (expVal < 1) expVal = 1 / expVal;
+              return Math.Pow(complexity, Math.Round(expVal));
+            }
+
+            double expComplexity = CalculateComplexity(node.GetSubtree(1));
+            return Math.Pow(complexity, 2 * expComplexity);
+          }
+
+        default:
+          throw new NotSupportedException();
+      }
+    }
+  }
+}
Index: branches/crossvalidation-2434/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/Symbols/VariableCondition.cs
===================================================================
--- branches/crossvalidation-2434/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/Symbols/VariableCondition.cs	(revision 13401)
+++ branches/crossvalidation-2434/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/Symbols/VariableCondition.cs	(revision 14029)
@@ -100,5 +100,4 @@
         allVariableNames.Clear();
         allVariableNames.AddRange(value);
-        VariableNames = value;
       }
     }
@@ -149,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;
       }
     }
