Index: branches/2435-alglib_3_15/HeuristicLab.Problems.DataAnalysis.Symbolic.Regression/3.4/MultiObjective/PearsonRSquaredAverageSimilarityEvaluator.cs
===================================================================
--- branches/2435-alglib_3_15/HeuristicLab.Problems.DataAnalysis.Symbolic.Regression/3.4/MultiObjective/PearsonRSquaredAverageSimilarityEvaluator.cs	(revision 16683)
+++ branches/2435-alglib_3_15/HeuristicLab.Problems.DataAnalysis.Symbolic.Regression/3.4/MultiObjective/PearsonRSquaredAverageSimilarityEvaluator.cs	(revision 17034)
@@ -22,6 +22,5 @@
 using System;
 using System.Collections.Generic;
-using System.Diagnostics;
-using System.Linq;
+using HEAL.Attic;
 using HeuristicLab.Common;
 using HeuristicLab.Core;
@@ -29,5 +28,4 @@
 using HeuristicLab.Encodings.SymbolicExpressionTreeEncoding;
 using HeuristicLab.Parameters;
-using HEAL.Attic;
 
 namespace HeuristicLab.Problems.DataAnalysis.Symbolic.Regression {
@@ -36,9 +34,16 @@
   public class PearsonRSquaredAverageSimilarityEvaluator : SymbolicRegressionMultiObjectiveEvaluator {
     private const string StrictSimilarityParameterName = "StrictSimilarity";
+    private const string AverageSimilarityParameterName = "AverageSimilarity";
 
     private readonly object locker = new object();
 
+    private readonly SymbolicDataAnalysisExpressionTreeAverageSimilarityCalculator SimilarityCalculator = new SymbolicDataAnalysisExpressionTreeAverageSimilarityCalculator();
+
     public IFixedValueParameter<BoolValue> StrictSimilarityParameter {
       get { return (IFixedValueParameter<BoolValue>)Parameters[StrictSimilarityParameterName]; }
+    }
+
+    public ILookupParameter<DoubleValue> AverageSimilarityParameter {
+      get { return (ILookupParameter<DoubleValue>)Parameters[AverageSimilarityParameterName]; }
     }
 
@@ -58,7 +63,8 @@
     public PearsonRSquaredAverageSimilarityEvaluator() : base() {
       Parameters.Add(new FixedValueParameter<BoolValue>(StrictSimilarityParameterName, "Use strict similarity calculation.", new BoolValue(false)));
+      Parameters.Add(new LookupParameter<DoubleValue>(AverageSimilarityParameterName));
     }
 
-    public override IEnumerable<bool> Maximization { get { return new bool[2] { true, false }; } } // maximize R² and minimize model complexity 
+    public override IEnumerable<bool> Maximization { get { return new bool[2] { true, false }; } } // maximize R² and minimize average similarity 
 
     public override IOperation InstrumentedApply() {
@@ -73,33 +79,42 @@
         SymbolicRegressionConstantOptimizationEvaluator.OptimizeConstants(interpreter, solution, problemData, rows, applyLinearScaling, ConstantOptimizationIterations, updateVariableWeights: ConstantOptimizationUpdateVariableWeights, lowerEstimationLimit: estimationLimits.Lower, upperEstimationLimit: estimationLimits.Upper);
       }
-      double[] qualities = Calculate(interpreter, solution, estimationLimits.Lower, estimationLimits.Upper, problemData, rows, applyLinearScaling, DecimalPlaces);
-      QualitiesParameter.ActualValue = new DoubleArray(qualities);
-      return base.InstrumentedApply();
-    }
 
-    public double[] Calculate(ISymbolicDataAnalysisExpressionTreeInterpreter interpreter, ISymbolicExpressionTree solution, double lowerEstimationLimit, double upperEstimationLimit, IRegressionProblemData problemData, IEnumerable<int> rows, bool applyLinearScaling, int decimalPlaces) {
-      double r2 = SymbolicRegressionSingleObjectivePearsonRSquaredEvaluator.Calculate(interpreter, solution, lowerEstimationLimit, upperEstimationLimit, problemData, rows, applyLinearScaling);
-      if (decimalPlaces >= 0)
-        r2 = Math.Round(r2, decimalPlaces);
+      double r2 = SymbolicRegressionSingleObjectivePearsonRSquaredEvaluator.Calculate(interpreter, solution, estimationLimits.Lower, estimationLimits.Upper, problemData, rows, applyLinearScaling);
 
-      var variables = ExecutionContext.Scope.Variables;
-      if (!variables.ContainsKey("AverageSimilarity")) {
-        lock (locker) {
-          CalculateAverageSimilarities(ExecutionContext.Scope.Parent.SubScopes.Where(x => x.Variables.ContainsKey("SymbolicExpressionTree")).ToArray(), StrictSimilarity);
+      if (DecimalPlaces >= 0)
+        r2 = Math.Round(r2, DecimalPlaces);
 
+      lock (locker) {
+        if (AverageSimilarityParameter.ActualValue == null) {
+          var context = new ExecutionContext(null, SimilarityCalculator, ExecutionContext.Scope.Parent);
+          SimilarityCalculator.StrictSimilarity = StrictSimilarity;
+          SimilarityCalculator.Execute(context, CancellationToken);
         }
       }
+      var avgSimilarity = AverageSimilarityParameter.ActualValue.Value;
 
-      double avgSim = ((DoubleValue)variables["AverageSimilarity"].Value).Value;
-      return new double[2] { r2, avgSim };
+      QualitiesParameter.ActualValue = new DoubleArray(new[] { r2, avgSimilarity });
+      return base.InstrumentedApply();
     }
 
     public override double[] Evaluate(IExecutionContext context, ISymbolicExpressionTree tree, IRegressionProblemData problemData, IEnumerable<int> rows) {
       SymbolicDataAnalysisTreeInterpreterParameter.ExecutionContext = context;
+      AverageSimilarityParameter.ExecutionContext = context;
       EstimationLimitsParameter.ExecutionContext = context;
       ApplyLinearScalingParameter.ExecutionContext = context;
-      // DecimalPlaces parameter is a FixedValueParameter and doesn't need the context.
 
-      double[] quality = Calculate(SymbolicDataAnalysisTreeInterpreterParameter.ActualValue, tree, EstimationLimitsParameter.ActualValue.Lower, EstimationLimitsParameter.ActualValue.Upper, problemData, rows, ApplyLinearScalingParameter.ActualValue.Value, DecimalPlaces);
+      var estimationLimits = EstimationLimitsParameter.ActualValue;
+      var applyLinearScaling = ApplyLinearScalingParameter.ActualValue.Value;
+
+      double r2 = SymbolicRegressionSingleObjectivePearsonRSquaredEvaluator.Calculate(SymbolicDataAnalysisTreeInterpreterParameter.ActualValue, tree, estimationLimits.Lower, estimationLimits.Upper, problemData, rows, applyLinearScaling);
+
+      lock (locker) {
+        if (AverageSimilarityParameter.ActualValue == null) {
+          var ctx = new ExecutionContext(null, SimilarityCalculator, context.Scope.Parent);
+          SimilarityCalculator.StrictSimilarity = StrictSimilarity;
+          SimilarityCalculator.Execute(context, CancellationToken);
+        }
+      }
+      var avgSimilarity = AverageSimilarityParameter.ActualValue.Value;
 
       SymbolicDataAnalysisTreeInterpreterParameter.ExecutionContext = null;
@@ -107,27 +122,5 @@
       ApplyLinearScalingParameter.ExecutionContext = null;
 
-      return quality;
-    }
-
-    private readonly Stopwatch sw = new Stopwatch();
-    public void CalculateAverageSimilarities(IScope[] treeScopes, bool strict) {
-      var trees = treeScopes.Select(x => (ISymbolicExpressionTree)x.Variables["SymbolicExpressionTree"].Value).ToArray();
-      var similarityMatrix = SymbolicExpressionTreeHash.ComputeSimilarityMatrix(trees, simplify: false, strict: strict);
-
-      for (int i = 0; i < treeScopes.Length; ++i) {
-        var scope = treeScopes[i];
-        var avgSimilarity = 0d;
-        for (int j = 0; j < trees.Length; ++j) {
-          if (i == j) continue;
-          avgSimilarity += similarityMatrix[i, j];
-        }
-        avgSimilarity /= trees.Length - 1;
-
-        if (scope.Variables.ContainsKey("AverageSimilarity")) {
-          ((DoubleValue)scope.Variables["AverageSimilarity"].Value).Value = avgSimilarity;
-        } else {
-          scope.Variables.Add(new Core.Variable("AverageSimilarity", new DoubleValue(avgSimilarity)));
-        }
-      }
+      return new[] { r2, avgSimilarity };
     }
   }
Index: branches/2435-alglib_3_15/HeuristicLab.Problems.DataAnalysis.Symbolic.Regression/3.4/SingleObjective/Evaluators/SymbolicRegressionConstantOptimizationEvaluator.cs
===================================================================
--- branches/2435-alglib_3_15/HeuristicLab.Problems.DataAnalysis.Symbolic.Regression/3.4/SingleObjective/Evaluators/SymbolicRegressionConstantOptimizationEvaluator.cs	(revision 16683)
+++ branches/2435-alglib_3_15/HeuristicLab.Problems.DataAnalysis.Symbolic.Regression/3.4/SingleObjective/Evaluators/SymbolicRegressionConstantOptimizationEvaluator.cs	(revision 17034)
@@ -23,4 +23,5 @@
 using System.Collections.Generic;
 using System.Linq;
+using HEAL.Attic;
 using HeuristicLab.Common;
 using HeuristicLab.Core;
@@ -29,5 +30,4 @@
 using HeuristicLab.Optimization;
 using HeuristicLab.Parameters;
-using HEAL.Attic;
 
 namespace HeuristicLab.Problems.DataAnalysis.Symbolic.Regression {
@@ -114,8 +114,8 @@
     public SymbolicRegressionConstantOptimizationEvaluator()
       : base() {
-      Parameters.Add(new FixedValueParameter<IntValue>(ConstantOptimizationIterationsParameterName, "Determines how many iterations should be calculated while optimizing the constant of a symbolic expression tree (0 indicates other or default stopping criterion).", new IntValue(10), true));
-      Parameters.Add(new FixedValueParameter<DoubleValue>(ConstantOptimizationImprovementParameterName, "Determines the relative improvement which must be achieved in the constant optimization to continue with it (0 indicates other or default stopping criterion).", new DoubleValue(0), true) { Hidden = true });
-      Parameters.Add(new FixedValueParameter<PercentValue>(ConstantOptimizationProbabilityParameterName, "Determines the probability that the constants are optimized", new PercentValue(1), true));
-      Parameters.Add(new FixedValueParameter<PercentValue>(ConstantOptimizationRowsPercentageParameterName, "Determines the percentage of the rows which should be used for constant optimization", new PercentValue(1), true));
+      Parameters.Add(new FixedValueParameter<IntValue>(ConstantOptimizationIterationsParameterName, "Determines how many iterations should be calculated while optimizing the constant of a symbolic expression tree (0 indicates other or default stopping criterion).", new IntValue(10)));
+      Parameters.Add(new FixedValueParameter<DoubleValue>(ConstantOptimizationImprovementParameterName, "Determines the relative improvement which must be achieved in the constant optimization to continue with it (0 indicates other or default stopping criterion).", new DoubleValue(0)) { Hidden = true });
+      Parameters.Add(new FixedValueParameter<PercentValue>(ConstantOptimizationProbabilityParameterName, "Determines the probability that the constants are optimized", new PercentValue(1)));
+      Parameters.Add(new FixedValueParameter<PercentValue>(ConstantOptimizationRowsPercentageParameterName, "Determines the percentage of the rows which should be used for constant optimization", new PercentValue(1)));
       Parameters.Add(new FixedValueParameter<BoolValue>(UpdateConstantsInTreeParameterName, "Determines if the constants in the tree should be overwritten by the optimized constants.", new BoolValue(true)) { Hidden = true });
       Parameters.Add(new FixedValueParameter<BoolValue>(UpdateVariableWeightsParameterName, "Determines if the variable weights in the tree should be  optimized.", new BoolValue(true)) { Hidden = true });
Index: branches/2435-alglib_3_15/HeuristicLab.Problems.DataAnalysis.Symbolic.Regression/3.4/SymbolicRegressionModel.cs
===================================================================
--- branches/2435-alglib_3_15/HeuristicLab.Problems.DataAnalysis.Symbolic.Regression/3.4/SymbolicRegressionModel.cs	(revision 16683)
+++ branches/2435-alglib_3_15/HeuristicLab.Problems.DataAnalysis.Symbolic.Regression/3.4/SymbolicRegressionModel.cs	(revision 17034)
@@ -90,5 +90,5 @@
       var regressionProblemData = problemData as IRegressionProblemData;
       if (regressionProblemData == null)
-        throw new ArgumentException("The problem data is not a regression problem data. Instead a " + problemData.GetType().GetPrettyName() + " was provided.", "problemData");
+        throw new ArgumentException("The problem data is not compatible with this symbolic regression model. Instead a " + problemData.GetType().GetPrettyName() + " was provided.", "problemData");
       return IsProblemDataCompatible(regressionProblemData, out errorMessage);
     }
