Index: branches/OaaS/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/Evaluators/SymbolicDataAnalysisEvaluator.cs
===================================================================
--- branches/OaaS/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/Evaluators/SymbolicDataAnalysisEvaluator.cs	(revision 8228)
+++ branches/OaaS/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/Evaluators/SymbolicDataAnalysisEvaluator.cs	(revision 9363)
@@ -28,4 +28,5 @@
 using HeuristicLab.Encodings.SymbolicExpressionTreeEncoding;
 using HeuristicLab.Operators;
+using HeuristicLab.Optimization;
 using HeuristicLab.Parameters;
 using HeuristicLab.Persistence.Default.CompositeSerializers.Storable;
@@ -35,5 +36,5 @@
   [StorableClass]
   public abstract class SymbolicDataAnalysisEvaluator<T> : SingleSuccessorOperator,
-    ISymbolicDataAnalysisEvaluator<T>, ISymbolicDataAnalysisInterpreterOperator, ISymbolicDataAnalysisBoundedOperator
+    ISymbolicDataAnalysisEvaluator<T>, ISymbolicDataAnalysisInterpreterOperator, ISymbolicDataAnalysisBoundedOperator, IStochasticOperator
   where T : class, IDataAnalysisProblemData {
     private const string RandomParameterName = "Random";
@@ -44,8 +45,14 @@
     private const string EvaluationPartitionParameterName = "EvaluationPartition";
     private const string RelativeNumberOfEvaluatedSamplesParameterName = "RelativeNumberOfEvaluatedSamples";
+    private const string ApplyLinearScalingParameterName = "ApplyLinearScaling";
+    private const string ValidRowIndicatorParameterName = "ValidRowIndicator";
 
     public override bool CanChangeName { get { return false; } }
 
     #region parameter properties
+    ILookupParameter<IRandom> IStochasticOperator.RandomParameter {
+      get { return RandomParameter; }
+    }
+
     public IValueLookupParameter<IRandom> RandomParameter {
       get { return (IValueLookupParameter<IRandom>)Parameters[RandomParameterName]; }
@@ -70,4 +77,10 @@
       get { return (IValueLookupParameter<PercentValue>)Parameters[RelativeNumberOfEvaluatedSamplesParameterName]; }
     }
+    public ILookupParameter<BoolValue> ApplyLinearScalingParameter {
+      get { return (ILookupParameter<BoolValue>)Parameters[ApplyLinearScalingParameterName]; }
+    }
+    public IValueLookupParameter<StringValue> ValidRowIndicatorParameter {
+      get { return (IValueLookupParameter<StringValue>)Parameters[ValidRowIndicatorParameterName]; }
+    }
     #endregion
 
@@ -87,4 +100,16 @@
       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)."));
+    }
+
+    [StorableHook(HookType.AfterDeserialization)]
+    private void AfterDeserialization() {
+      if (Parameters.ContainsKey(ApplyLinearScalingParameterName) && !(Parameters[ApplyLinearScalingParameterName] is LookupParameter<BoolValue>))
+        Parameters.Remove(ApplyLinearScalingParameterName);
+      if (!Parameters.ContainsKey(ApplyLinearScalingParameterName))
+        Parameters.Add(new LookupParameter<BoolValue>(ApplyLinearScalingParameterName, "Flag that indicates if the individual should be linearly scaled before evaluating."));
+      if (!Parameters.ContainsKey(ValidRowIndicatorParameterName))
+        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)."));
     }
 
@@ -94,6 +119,4 @@
 
     protected IEnumerable<int> GenerateRowsToEvaluate(double percentageOfRows) {
-
-
       IEnumerable<int> rows;
       int samplesStart = EvaluationPartitionParameter.ActualValue.Start;
@@ -101,5 +124,4 @@
       int testPartitionStart = ProblemDataParameter.ActualValue.TestPartition.Start;
       int testPartitionEnd = ProblemDataParameter.ActualValue.TestPartition.End;
-
       if (samplesEnd < samplesStart) throw new ArgumentException("Start value is larger than end value.");
 
@@ -113,5 +135,54 @@
       }
 
-      return rows.Where(i => i < testPartitionStart || testPartitionEnd <= i);
+      rows = rows.Where(i => i < testPartitionStart || testPartitionEnd <= i);
+      if (ValidRowIndicatorParameter.ActualValue != null) {
+        string indicatorVar = ValidRowIndicatorParameter.ActualValue.Value;
+        var problemData = ProblemDataParameter.ActualValue;
+        var indicatorRow = problemData.Dataset.GetReadOnlyDoubleValues(indicatorVar);
+        rows = rows.Where(r => !indicatorRow[r].IsAlmost(0.0));
+      }
+      return rows;
+    }
+
+    [ThreadStatic]
+    private static double[] cache;
+    protected static void CalculateWithScaling(IEnumerable<double> targetValues, IEnumerable<double> estimatedValues,
+      double lowerEstimationLimit, double upperEstimationLimit,
+      IOnlineCalculator calculator, int maxRows) {
+      if (cache == null || cache.Length < maxRows) {
+        cache = new double[maxRows];
+      }
+
+      // calculate linear scaling
+      int i = 0;
+      var linearScalingCalculator = new OnlineLinearScalingParameterCalculator();
+      var targetValuesEnumerator = targetValues.GetEnumerator();
+      var estimatedValuesEnumerator = estimatedValues.GetEnumerator();
+      while (targetValuesEnumerator.MoveNext() & estimatedValuesEnumerator.MoveNext()) {
+        double target = targetValuesEnumerator.Current;
+        double estimated = estimatedValuesEnumerator.Current;
+        cache[i] = estimated;
+        if (!double.IsNaN(estimated) && !double.IsInfinity(estimated))
+          linearScalingCalculator.Add(estimated, target);
+        i++;
+      }
+      if (linearScalingCalculator.ErrorState == OnlineCalculatorError.None && (targetValuesEnumerator.MoveNext() || estimatedValuesEnumerator.MoveNext()))
+        throw new ArgumentException("Number of elements in target and estimated values enumeration do not match.");
+
+      double alpha = linearScalingCalculator.Alpha;
+      double beta = linearScalingCalculator.Beta;
+      if (linearScalingCalculator.ErrorState != OnlineCalculatorError.None) {
+        alpha = 0.0;
+        beta = 1.0;
+      }
+
+      //calculate the quality by using the passed online calculator
+      targetValuesEnumerator = targetValues.GetEnumerator();
+      var scaledBoundedEstimatedValuesEnumerator = Enumerable.Range(0, i).Select(x => cache[x] * beta + alpha)
+        .LimitToRange(lowerEstimationLimit, upperEstimationLimit).GetEnumerator();
+
+      while (targetValuesEnumerator.MoveNext() & scaledBoundedEstimatedValuesEnumerator.MoveNext()) {
+        calculator.Add(targetValuesEnumerator.Current, scaledBoundedEstimatedValuesEnumerator.Current);
+      }
     }
   }
