Index: branches/DataAnalysis/HeuristicLab.Problems.DataAnalysis.MultiVariate.TimeSeriesPrognosis.Views/3.3/InteractiveSymbolicTimeSeriesPrognosisSolutionSimplifierView.cs
===================================================================
--- branches/DataAnalysis/HeuristicLab.Problems.DataAnalysis.MultiVariate.TimeSeriesPrognosis.Views/3.3/InteractiveSymbolicTimeSeriesPrognosisSolutionSimplifierView.cs	(revision 4464)
+++ branches/DataAnalysis/HeuristicLab.Problems.DataAnalysis.MultiVariate.TimeSeriesPrognosis.Views/3.3/InteractiveSymbolicTimeSeriesPrognosisSolutionSimplifierView.cs	(revision 4475)
@@ -95,27 +95,29 @@
         int samplesEnd = Content.ProblemData.TrainingSamplesEnd.Value;
 
-        double[] alpha, beta;
         double quality;
         conditionVariableName = Content.ConditionalEvaluationVariable;
         targetVariables = Content.ProblemData.TargetVariables.CheckedItems.Select(x => x.Value.Value);
         int nTargetVariables = Content.ProblemData.TargetVariables.CheckedItems.Count();
-        lowerEstimationLimit = new DoubleArray(Enumerable.Repeat(double.NegativeInfinity, nTargetVariables).ToArray());
-        upperEstimationLimit = new DoubleArray(Enumerable.Repeat(double.PositiveInfinity, nTargetVariables).ToArray());
         interpreter = Content.Model.Interpreter;
         horizon = Content.Horizon;
         IEnumerable<int> rows = Enumerable.Range(samplesStart, samplesEnd - samplesStart);
-        SymbolicTimeSeriesPrognosisScaledNormalizedMseEvaluator.CalculateScalingParameters(simplifiedExpressionTree,
-          Content.ProblemData, interpreter,
-          conditionVariableName, rows,
-          out beta, out alpha);
-
-        quality = SymbolicTimeSeriesPrognosisScaledNormalizedMseEvaluator.Evaluate(simplifiedExpressionTree, Content.ProblemData, interpreter,
-          conditionVariableName, rows, horizon,
-          lowerEstimationLimit, upperEstimationLimit,
-          beta, alpha);
+        if (!string.IsNullOrEmpty(conditionVariableName)) {
+          rows = (from row in rows
+                  where !Content.ProblemData.Dataset[conditionVariableName, row].IsAlmost(0.0)
+                  select row).ToList();
+        }
+        lowerEstimationLimit = new DoubleArray(nTargetVariables);
+        upperEstimationLimit = new DoubleArray(nTargetVariables);
+        for (int i = 0; i < nTargetVariables; i++) {
+          lowerEstimationLimit[i] = Content.GetLowerEstimationLimit(i);
+          upperEstimationLimit[i] = Content.GetUpperEstimationLimit(i);
+        }
+        quality = SymbolicTimeSeriesPrognosisScaledNormalizedMseEvaluator.Calculate(simplifiedExpressionTree, Content.ProblemData, interpreter,
+          rows, horizon,
+          lowerEstimationLimit, upperEstimationLimit);
 
         this.CalculateReplacementNodes();
 
-        this.CalculateNodeImpacts(simplifiedExpressionTree, simplifiedExpressionTree.Root, quality);
+        this.CalculateNodeImpacts(simplifiedExpressionTree, simplifiedExpressionTree.Root, quality, rows);
         // show only interesing part
         this.treeChart.Tree = new SymbolicExpressionTree(simplifiedExpressionTree.Root.SubTrees[0]);
@@ -134,5 +136,7 @@
           while (start.SubTrees.Count > 0) start.RemoveSubTree(0);
           start.AddSubTree(node);
-          double constantTreeNodeValue = interpreter.GetSymbolicExpressionTreeValues(tree, Content.ProblemData.Dataset, targetVariables, trainingSamples, 1).Select(x => x[0]).Median();
+          // we only want a scalar replacement value for the single branch that should be evaluated
+          // so assume we only create an estimation for the first target variable
+          double constantTreeNodeValue = interpreter.GetSymbolicExpressionTreeValues(tree, Content.ProblemData.Dataset, targetVariables.Take(1) , trainingSamples, 1).Select(x => x[0]).Median();
           ConstantTreeNode constantTreeNode = MakeConstantTreeNode(constantTreeNodeValue);
           replacementNodes[node] = constantTreeNode;
@@ -141,28 +145,18 @@
     }
 
-    private void CalculateNodeImpacts(SymbolicExpressionTree tree, SymbolicExpressionTreeNode currentTreeNode, double originalQuality) {
+    private void CalculateNodeImpacts(SymbolicExpressionTree tree, SymbolicExpressionTreeNode currentTreeNode, double originalQuality, IEnumerable<int> rows) {
       foreach (SymbolicExpressionTreeNode childNode in currentTreeNode.SubTrees.ToList()) {
         if (!(childNode.Symbol is StartSymbol || childNode.Symbol is ProgramRootSymbol)) {
           SwitchNode(currentTreeNode, childNode, replacementNodes[childNode]);
-          int samplesStart = Content.ProblemData.TrainingSamplesStart.Value;
-          int samplesEnd = Content.ProblemData.TrainingSamplesEnd.Value;
-          double[] alpha;
-          double[] beta;
           int horizon = Content.Horizon;
-          IEnumerable<int> rows = Enumerable.Range(samplesStart, samplesEnd - samplesStart);          
-          SymbolicTimeSeriesPrognosisScaledNormalizedMseEvaluator.CalculateScalingParameters(tree,
-            Content.ProblemData, interpreter,
-            conditionVariableName, rows,
-            out beta, out alpha);
-
-          double newQuality = SymbolicTimeSeriesPrognosisScaledNormalizedMseEvaluator.Evaluate(tree, Content.ProblemData, interpreter,
-            conditionVariableName, rows, horizon,
-            lowerEstimationLimit, upperEstimationLimit,
-            beta, alpha);
+
+          double newQuality = SymbolicTimeSeriesPrognosisScaledNormalizedMseEvaluator.Calculate(tree, Content.ProblemData, interpreter,
+            rows, horizon,
+            lowerEstimationLimit, upperEstimationLimit);
 
           nodeImpacts[childNode] = newQuality / originalQuality;
           SwitchNode(currentTreeNode, replacementNodes[childNode], childNode);
         }
-        CalculateNodeImpacts(tree, childNode, originalQuality);
+        CalculateNodeImpacts(tree, childNode, originalQuality, rows);
       }
     }
Index: branches/DataAnalysis/HeuristicLab.Problems.DataAnalysis.MultiVariate.TimeSeriesPrognosis/3.3/HeuristicLab.Problems.DataAnalysis.MultiVariate.TimeSeriesPrognosis-3.3.csproj
===================================================================
--- branches/DataAnalysis/HeuristicLab.Problems.DataAnalysis.MultiVariate.TimeSeriesPrognosis/3.3/HeuristicLab.Problems.DataAnalysis.MultiVariate.TimeSeriesPrognosis-3.3.csproj	(revision 4464)
+++ branches/DataAnalysis/HeuristicLab.Problems.DataAnalysis.MultiVariate.TimeSeriesPrognosis/3.3/HeuristicLab.Problems.DataAnalysis.MultiVariate.TimeSeriesPrognosis-3.3.csproj	(revision 4475)
@@ -108,7 +108,10 @@
     <Compile Include="HeuristicLabProblemsDataAnalysisMultiVariateTimeSeriesPrognosisPlugin.cs" />
     <Compile Include="Symbolic\Analyzer\ValidationBestScaledSymbolicTimeSeriesPrognosisSolutionAnalyzer.cs" />
+    <Compile Include="Symbolic\Evaluators\SymbolicTimeSeriesPrognosisEvaluator.cs" />
+    <Compile Include="Symbolic\Evaluators\SymbolicTimeSeriesPrognosisMahalanobisEvaluator.cs">
+      <SubType>Code</SubType>
+    </Compile>
     <Compile Include="Symbolic\SymbolicTimeSeriesPrognosisSolution.cs" />
     <Compile Include="Symbolic\SymbolicTimeSeriesPrognosisModel.cs" />
-    <Compile Include="Symbolic\Evaluators\SymbolicTimeSeriesPrognosisNormalizedMseEvaluator.cs" />
     <Compile Include="Symbolic\Evaluators\SymbolicTimeSeriesPrognosisScaledNormalizedMseEvaluator.cs" />
     <Compile Include="Symbolic\Interfaces\ISingleObjectiveSymbolicTimeSeriesPrognosisEvaluator.cs" />
Index: branches/DataAnalysis/HeuristicLab.Problems.DataAnalysis.MultiVariate.TimeSeriesPrognosis/3.3/Symbolic/Analyzer/ValidationBestScaledSymbolicTimeSeriesPrognosisSolutionAnalyzer.cs
===================================================================
--- branches/DataAnalysis/HeuristicLab.Problems.DataAnalysis.MultiVariate.TimeSeriesPrognosis/3.3/Symbolic/Analyzer/ValidationBestScaledSymbolicTimeSeriesPrognosisSolutionAnalyzer.cs	(revision 4464)
+++ branches/DataAnalysis/HeuristicLab.Problems.DataAnalysis.MultiVariate.TimeSeriesPrognosis/3.3/Symbolic/Analyzer/ValidationBestScaledSymbolicTimeSeriesPrognosisSolutionAnalyzer.cs	(revision 4475)
@@ -125,10 +125,4 @@
       get { return (OptionalValueParameter<StringValue>)Parameters[ConditionVariableParameterName]; }
     }
-    public ScopeTreeLookupParameter<DoubleArray> AlphaParameter {
-      get { return (ScopeTreeLookupParameter<DoubleArray>)Parameters[AlphaParameterName]; }
-    }
-    public ScopeTreeLookupParameter<DoubleArray> BetaParameter {
-      get { return (ScopeTreeLookupParameter<DoubleArray>)Parameters[BetaParameterName]; }
-    }
     public IValueLookupParameter<ISymbolicTimeSeriesExpressionInterpreter> SymbolicExpressionTreeInterpreterParameter {
       get { return (IValueLookupParameter<ISymbolicTimeSeriesExpressionInterpreter>)Parameters[SymbolicExpressionTreeInterpreterParameterName]; }
@@ -137,4 +131,7 @@
       get { return (IValueLookupParameter<MultiVariateDataAnalysisProblemData>)Parameters[ProblemDataParameterName]; }
     }
+    public ILookupParameter<ISingleObjectiveSymbolicTimeSeriesPrognosisEvaluator> EvaluatorParameter {
+      get { return (ILookupParameter<ISingleObjectiveSymbolicTimeSeriesPrognosisEvaluator>)Parameters["Evaluator"]; }
+    }
     public IValueLookupParameter<IntValue> ValidationSamplesStartParameter {
       get { return (IValueLookupParameter<IntValue>)Parameters[ValidationSamplesStartParameterName]; }
@@ -172,4 +169,7 @@
     public IValueParameter<PercentValue> RelativeNumberOfEvaluatedSamplesParameter {
       get { return (IValueParameter<PercentValue>)Parameters[RelativeNumberOfEvaluatedSamplesParameterName]; }
+    }
+    public ILookupParameter<BoolValue> MaximizationParameter {
+      get { return (ILookupParameter<BoolValue>)Parameters["Maximization"]; }
     }
     #endregion
@@ -181,10 +181,4 @@
       get { return SymbolicExpressionTreeParameter.ActualValue; }
     }
-    public ItemArray<DoubleArray> Alpha {
-      get { return AlphaParameter.ActualValue; }
-    }
-    public ItemArray<DoubleArray> Beta {
-      get { return BetaParameter.ActualValue; }
-    }
     public ISymbolicTimeSeriesExpressionInterpreter SymbolicExpressionTreeInterpreter {
       get { return SymbolicExpressionTreeInterpreterParameter.ActualValue; }
@@ -222,4 +216,7 @@
     public PercentValue RelativeNumberOfEvaluatedSamples {
       get { return RelativeNumberOfEvaluatedSamplesParameter.Value; }
+    }
+    public BoolValue Maximization {
+      get { return MaximizationParameter.ActualValue; }
     }
     #endregion
@@ -230,6 +227,4 @@
       Parameters.Add(new ScopeTreeLookupParameter<SymbolicExpressionTree>(SymbolicExpressionTreeParameterName, "The symbolic expression trees to analyze."));
       Parameters.Add(new OptionalValueParameter<StringValue>(ConditionVariableParameterName, "The name of the condition variable indicating if a row should be considered for evaluation or not."));
-      Parameters.Add(new ScopeTreeLookupParameter<DoubleArray>(AlphaParameterName, "The alpha parameter for linear scaling."));
-      Parameters.Add(new ScopeTreeLookupParameter<DoubleArray>(BetaParameterName, "The beta parameter for linear scaling."));
       Parameters.Add(new ValueLookupParameter<ISymbolicTimeSeriesExpressionInterpreter>(SymbolicExpressionTreeInterpreterParameterName, "The interpreter that should be used for the analysis of symbolic expression trees."));
       Parameters.Add(new ValueLookupParameter<MultiVariateDataAnalysisProblemData>(ProblemDataParameterName, "The problem data for which the symbolic expression tree is a solution."));
@@ -237,4 +232,5 @@
       Parameters.Add(new ValueLookupParameter<IntValue>(ValidationSamplesEndParameterName, "The last index of the validation partition of the data set."));
       Parameters.Add(new ValueLookupParameter<IntValue>(PredictionHorizonParameterName, "The number of time steps for which to create a forecast."));
+      Parameters.Add(new LookupParameter<ISingleObjectiveSymbolicTimeSeriesPrognosisEvaluator>("Evaluator", ""));
       Parameters.Add(new ValueLookupParameter<DoubleArray>(UpperEstimationLimitParameterName, "The upper estimation limit that was set for the evaluation of the symbolic expression trees."));
       Parameters.Add(new ValueLookupParameter<DoubleArray>(LowerEstimationLimitParameterName, "The lower estimation limit that was set for the evaluation of the symbolic expression trees."));
@@ -246,5 +242,5 @@
       Parameters.Add(new LookupParameter<DataTable>(VariableFrequenciesParameterName, "The variable frequencies table to use for the calculation of variable impacts"));
       Parameters.Add(new ValueParameter<PercentValue>(RelativeNumberOfEvaluatedSamplesParameterName, "The relative number of samples of the dataset partition, which should be randomly chosen for evaluation between the start and end index.", new PercentValue(1)));
-
+      Parameters.Add(new LookupParameter<BoolValue>("Maximization"));
     }
 
@@ -252,16 +248,15 @@
     private ValidationBestScaledSymbolicTimeSeriesPrognosisSolutionAnalyzer(bool deserializing) : base(deserializing) { }
 
+    [StorableHook(Persistence.Default.CompositeSerializers.Storable.HookType.AfterDeserialization)]
+    private void Initialize() {
+      //if (!Parameters.ContainsKey("Evaluator")) {
+      //  Parameters.Add(new LookupParameter<ISingleObjectiveSymbolicTimeSeriesPrognosisEvaluator>("Evaluator", ""));
+      //}
+    }
+
     public override IOperation Apply() {
-      var alphas = Alpha;
-      var betas = Beta;
       var trees = SymbolicExpressionTree;
 
-      IEnumerable<SymbolicExpressionTree> scaledTrees;
-      if (alphas.Length == trees.Length) {
-        scaledTrees = from i in Enumerable.Range(0, trees.Length)
-                      select SymbolicVectorRegressionSolutionLinearScaler.Scale(trees[i], betas[i].ToArray(), alphas[i].ToArray());
-      } else {
-        scaledTrees = trees;
-      }
+      ISingleObjectiveSymbolicTimeSeriesPrognosisEvaluator evaluator = EvaluatorParameter.ActualValue;
 
       int trainingStart = ProblemData.TrainingSamplesStart.Value;
@@ -275,14 +270,20 @@
       int rowCount = (int)Math.Ceiling((validationEnd - validationStart) * RelativeNumberOfEvaluatedSamples.Value);
       IEnumerable<int> rows = RandomEnumerable.SampleRandomNumbers(Random.Next(), validationStart, validationEnd, rowCount);
-      double bestValidationNmse = double.MaxValue;
+      double bestValidationQuality = Maximization.Value ? double.MinValue : double.MaxValue;
       SymbolicExpressionTree bestTree = null;
       string conditionalVariableName = ConditionVariableName == null ? null : ConditionVariableName.Value;
-      foreach (var tree in scaledTrees) {
-        double validationNmse;
-        validationNmse = SymbolicTimeSeriesPrognosisNormalizedMseEvaluator.Evaluate(tree, ProblemData,
-          SymbolicExpressionTreeInterpreter, conditionalVariableName,
-          rows, PredictionHorizon.Value, LowerEstimationLimit, UpperEstimationLimit);
-        if (validationNmse < bestValidationNmse) {
-          bestValidationNmse = validationNmse;
+      if (conditionalVariableName != null) {
+        rows = from row in rows
+               where !ProblemData.Dataset[conditionalVariableName, row].IsAlmost(0.0)
+               select row;
+      }
+
+      foreach (var tree in trees) {
+        double validationQuality;
+        validationQuality = evaluator.Evaluate(tree, ProblemData,
+          SymbolicExpressionTreeInterpreter, rows, PredictionHorizon.Value, LowerEstimationLimit, UpperEstimationLimit);
+        if ((Maximization.Value && validationQuality > bestValidationQuality) ||
+           (!Maximization.Value && validationQuality < bestValidationQuality)) {
+          bestValidationQuality = validationQuality;
           bestTree = tree;
         }
@@ -290,15 +291,18 @@
 
 
-      if (BestSolutionQualityParameter.ActualValue == null || BestSolutionQualityParameter.ActualValue.Value > bestValidationNmse) {
-        var model = new SymbolicTimeSeriesPrognosisModel((ISymbolicTimeSeriesExpressionInterpreter)SymbolicExpressionTreeInterpreter.Clone(), bestTree);
+      if (BestSolutionQualityParameter.ActualValue == null ||
+        (Maximization.Value && BestSolutionQualityParameter.ActualValue.Value < bestValidationQuality) ||
+        (!Maximization.Value && BestSolutionQualityParameter.ActualValue.Value > bestValidationQuality)) {
+        var scaledTree = GetScaledTree(bestTree);
+        var model = new SymbolicTimeSeriesPrognosisModel((ISymbolicTimeSeriesExpressionInterpreter)SymbolicExpressionTreeInterpreter.Clone(), scaledTree);
         model.Name = "Time series prognosis model";
         model.Description = "Best solution on validation partition found over the whole run.";
 
-        var solution = new SymbolicTimeSeriesPrognosisSolution(ProblemData, model, PredictionHorizon.Value, conditionalVariableName);
+        var solution = new SymbolicTimeSeriesPrognosisSolution((MultiVariateDataAnalysisProblemData)ProblemData.Clone(), model, PredictionHorizon.Value, conditionalVariableName, LowerEstimationLimit.ToArray(), UpperEstimationLimit.ToArray());
         solution.Name = BestSolutionParameterName;
         solution.Description = "Best solution on validation partition found over the whole run.";
 
         BestSolutionParameter.ActualValue = solution;
-        BestSolutionQualityParameter.ActualValue = new DoubleValue(bestValidationNmse);
+        BestSolutionQualityParameter.ActualValue = new DoubleValue(bestValidationQuality);
 
         // BestSymbolicTimeSeriesPrognosisSolutionAnalyzer.UpdateBestSolutionResults(solution, ProblemData, Results, Generations, VariableFrequencies);
@@ -313,16 +317,46 @@
       Results[BestSolutionResultName].Value = BestSolutionParameter.ActualValue;
       Results[BestSolutionQualityParameterName].Value = new DoubleValue(BestSolutionQualityParameter.ActualValue.Value);
-      Results[CurrentBestValidationQualityParameterName].Value = new DoubleValue(bestValidationNmse);
+      Results[CurrentBestValidationQualityParameterName].Value = new DoubleValue(bestValidationQuality);
 
       DataTable validationValues = (DataTable)Results[BestSolutionQualityValuesParameterName].Value;
       AddValue(validationValues, BestSolutionQualityParameter.ActualValue.Value, BestSolutionQualityParameterName, BestSolutionQualityParameterName);
-      AddValue(validationValues, bestValidationNmse, CurrentBestValidationQualityParameterName, CurrentBestValidationQualityParameterName);
+      AddValue(validationValues, bestValidationQuality, CurrentBestValidationQualityParameterName, CurrentBestValidationQualityParameterName);
       #endregion
       return base.Apply();
     }
 
-    [StorableHook(HookType.AfterDeserialization)]
-    private void Initialize() {
-    }
+    private SymbolicExpressionTree GetScaledTree(SymbolicExpressionTree tree) {
+      double[] alpha, beta;
+      int trainingStart = ProblemData.TrainingSamplesStart.Value;
+      int trainingEnd = ProblemData.TrainingSamplesEnd.Value;
+      IEnumerable<int> trainingRows = Enumerable.Range(trainingStart, trainingEnd - trainingStart);
+      string conditionalVariableName = ConditionVariableName == null ? null : ConditionVariableName.Value;
+      if (conditionalVariableName != null) {
+        trainingRows = from row in trainingRows
+                       where !ProblemData.Dataset[conditionalVariableName, row].IsAlmost(0.0)
+                       select row;
+      }
+
+      // calculate scaling parameters based on one-step-predictions
+      IEnumerable<string> selectedTargetVariables = from item in ProblemData.TargetVariables
+                                                    where ProblemData.TargetVariables.ItemChecked(item)
+                                                    select item.Value;
+      int dimension = selectedTargetVariables.Count();
+
+      IEnumerable<double[]> oneStepPredictions =
+        SymbolicExpressionTreeInterpreter.GetSymbolicExpressionTreeValues(tree, ProblemData.Dataset, selectedTargetVariables, trainingRows, 1);
+      IEnumerable<double[]> originalValues = from row in trainingRows
+                                             select (from targetVariable in selectedTargetVariables
+                                                     select ProblemData.Dataset[targetVariable, row]).ToArray();
+      alpha = new double[dimension];
+      beta = new double[dimension];
+
+      SymbolicTimeSeriesPrognosisScaledNormalizedMseEvaluator.CalculateScalingParameters(originalValues, oneStepPredictions, ref beta, ref alpha);
+
+      // scale tree for solution
+      return SymbolicVectorRegressionSolutionLinearScaler.Scale(tree, beta, alpha);
+    }
+
+
 
     private static void AddValue(DataTable table, double data, string name, string description) {
Index: branches/DataAnalysis/HeuristicLab.Problems.DataAnalysis.MultiVariate.TimeSeriesPrognosis/3.3/Symbolic/Evaluators/SymbolicTimeSeriesPrognosisEvaluator.cs
===================================================================
--- branches/DataAnalysis/HeuristicLab.Problems.DataAnalysis.MultiVariate.TimeSeriesPrognosis/3.3/Symbolic/Evaluators/SymbolicTimeSeriesPrognosisEvaluator.cs	(revision 4475)
+++ branches/DataAnalysis/HeuristicLab.Problems.DataAnalysis.MultiVariate.TimeSeriesPrognosis/3.3/Symbolic/Evaluators/SymbolicTimeSeriesPrognosisEvaluator.cs	(revision 4475)
@@ -0,0 +1,168 @@
+#region License Information
+/* HeuristicLab
+ * Copyright (C) 2002-2010 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.Linq;
+using HeuristicLab.Common;
+using HeuristicLab.Core;
+using HeuristicLab.Data;
+using HeuristicLab.Persistence.Default.CompositeSerializers.Storable;
+using HeuristicLab.Problems.DataAnalysis.SupportVectorMachine;
+using HeuristicLab.Problems.DataAnalysis;
+using HeuristicLab.Problems.DataAnalysis.Evaluators;
+using HeuristicLab.Parameters;
+using HeuristicLab.Optimization;
+using HeuristicLab.Operators;
+using HeuristicLab.Problems.DataAnalysis.Regression.Symbolic;
+using HeuristicLab.Encodings.SymbolicExpressionTreeEncoding;
+using System.Collections.Generic;
+using HeuristicLab.Problems.DataAnalysis.Regression;
+using HeuristicLab.Problems.DataAnalysis.MultiVariate.TimeSeriesPrognosis.Symbolic.Interfaces;
+
+namespace HeuristicLab.Problems.DataAnalysis.MultiVariate.TimeSeriesPrognosis.Symbolic.Evaluators {
+  [Item("SymbolicTimeSeriesPrognosisEvaluator", "")]
+  [StorableClass]
+  public abstract class SymbolicTimeSeriesPrognosisEvaluator : SingleSuccessorOperator, ISingleObjectiveSymbolicTimeSeriesPrognosisEvaluator {
+    private const string RandomParameterName = "Random";
+    private const string DataAnalysisProblemDataParameterName = "MultiVariateDataAnalysisProblemData";
+    private const string TimeSeriesExpressionInterpreterParameterName = "TimeSeriesExpressionInterpreter";
+    private const string TimeSeriesPrognosisModelParameterName = "TimeSeriesPrognosisModel";
+    private const string PredictionHorizontParameterName = "PredictionHorizon";
+    private const string LowerEstimationLimitParameterName = "LowerEstimationLimit";
+    private const string UpperEstimationLimitParameterName = "UpperEstimationLimit";
+    private const string ConditionVariableParameterName = "ConditionVariableName";
+    private const string SamplesStartParameterName = "SamplesStart";
+    private const string SamplesEndParameterName = "SamplesEnd";
+    private const string QualityParameterName = "Quality";
+    private const string RelativeNumberOfEvaluatedSamplesParameterName = "RelativeNumberOfEvaluatedSamples";
+
+    #region parameter properties
+    public ILookupParameter<IRandom> RandomParameter {
+      get { return (ILookupParameter<IRandom>)Parameters[RandomParameterName]; }
+    }
+    public ILookupParameter<MultiVariateDataAnalysisProblemData> ProblemDataParameter {
+      get { return (ILookupParameter<MultiVariateDataAnalysisProblemData>)Parameters[DataAnalysisProblemDataParameterName]; }
+    }
+    public ILookupParameter<ISymbolicTimeSeriesExpressionInterpreter> TimeSeriesExpressionInterpreterParameter {
+      get { return (ILookupParameter<ISymbolicTimeSeriesExpressionInterpreter>)Parameters[TimeSeriesExpressionInterpreterParameterName]; }
+    }
+    public IValueLookupParameter<IntValue> PredictionHorizonParameter {
+      get { return (IValueLookupParameter<IntValue>)Parameters[PredictionHorizontParameterName]; }
+    }
+    public OptionalValueParameter<StringValue> ConditionVariableNameParameter {
+      get { return (OptionalValueParameter<StringValue>)Parameters[ConditionVariableParameterName]; }
+    }
+    public IValueLookupParameter<IntValue> SamplesStartParameter {
+      get { return (IValueLookupParameter<IntValue>)Parameters[SamplesStartParameterName]; }
+    }
+    public IValueLookupParameter<IntValue> SamplesEndParameter {
+      get { return (IValueLookupParameter<IntValue>)Parameters[SamplesEndParameterName]; }
+    }
+    public IValueLookupParameter<DoubleArray> LowerEstimationLimitParameter {
+      get { return (IValueLookupParameter<DoubleArray>)Parameters[LowerEstimationLimitParameterName]; }
+    }
+    public IValueLookupParameter<DoubleArray> UpperEstimationLimitParameter {
+      get { return (IValueLookupParameter<DoubleArray>)Parameters[UpperEstimationLimitParameterName]; }
+    }
+    public ILookupParameter<SymbolicExpressionTree> TimeSeriesPrognosisModelParameter {
+      get { return (ILookupParameter<SymbolicExpressionTree>)Parameters[TimeSeriesPrognosisModelParameterName]; }
+    }
+    public ILookupParameter<DoubleValue> QualityParameter {
+      get { return (ILookupParameter<DoubleValue>)Parameters[QualityParameterName]; }
+    }
+    public IValueParameter<PercentValue> RelativeNumberOfEvaluatedSamplesParameter {
+      get { return (IValueParameter<PercentValue>)Parameters[RelativeNumberOfEvaluatedSamplesParameterName]; }
+    }
+    #endregion
+    #region
+    public IRandom Random {
+      get { return RandomParameter.ActualValue; }
+    }
+    public MultiVariateDataAnalysisProblemData ProblemData {
+      get { return ProblemDataParameter.ActualValue; }
+    }
+    public ISymbolicTimeSeriesExpressionInterpreter TimeSeriesExpressionInterpreter {
+      get { return TimeSeriesExpressionInterpreterParameter.ActualValue; }
+    }
+    public IntValue PredictionHorizon {
+      get { return PredictionHorizonParameter.ActualValue; }
+    }
+    public StringValue ConditionVariableName {
+      get { return ConditionVariableNameParameter.Value; }
+    }
+    public IntValue SamplesStart {
+      get { return SamplesStartParameter.ActualValue; }
+    }
+    public IntValue SamplesEnd {
+      get { return SamplesEndParameter.ActualValue; }
+    }
+    public DoubleArray LowerEstimationLimit {
+      get { return LowerEstimationLimitParameter.ActualValue; }
+    }
+    public DoubleArray UpperEstimationLimit {
+      get { return UpperEstimationLimitParameter.ActualValue; }
+    }
+    public SymbolicExpressionTree TimeSeriesPrognosisModel {
+      get { return TimeSeriesPrognosisModelParameter.ActualValue; }
+    }
+    public PercentValue RelativeNumberOfEvaluatedSamples {
+      get { return RelativeNumberOfEvaluatedSamplesParameter.Value; }
+    }
+    #endregion
+
+    public SymbolicTimeSeriesPrognosisEvaluator()
+      : base() {
+      Parameters.Add(new LookupParameter<IRandom>(RandomParameterName, "A random number generator."));
+      Parameters.Add(new LookupParameter<MultiVariateDataAnalysisProblemData>(DataAnalysisProblemDataParameterName, "The data analysis problem data to use for training."));
+      Parameters.Add(new LookupParameter<ISymbolicTimeSeriesExpressionInterpreter>(TimeSeriesExpressionInterpreterParameterName, "The interpreter that should be used to evaluate the time series model represented as a symbolic expression tree."));
+      Parameters.Add(new ValueLookupParameter<IntValue>(SamplesStartParameterName, "The first index of the data set partition to use for training."));
+      Parameters.Add(new ValueLookupParameter<IntValue>(SamplesEndParameterName, "The last index of the data set partition to use for training."));
+      Parameters.Add(new ValueLookupParameter<IntValue>(PredictionHorizontParameterName, "The number of time steps for which to create a forecast."));
+      Parameters.Add(new ValueLookupParameter<DoubleArray>(LowerEstimationLimitParameterName, "The lower limit for estimated values."));
+      Parameters.Add(new ValueLookupParameter<DoubleArray>(UpperEstimationLimitParameterName, "The upper limit for estimated values."));
+      Parameters.Add(new OptionalValueParameter<StringValue>(ConditionVariableParameterName, "The name of the condition variable indicating if a row should be considered for evaluation or not."));
+      Parameters.Add(new LookupParameter<SymbolicExpressionTree>(TimeSeriesPrognosisModelParameterName, "The time series prognosis model encoded as a symbolic expression tree."));
+      Parameters.Add(new LookupParameter<DoubleValue>(QualityParameterName, "The quality of the time series prognosis model encoded as a symbolic expression tree."));
+      Parameters.Add(new ValueParameter<PercentValue>(RelativeNumberOfEvaluatedSamplesParameterName, "The relative number of samples of the dataset partition, which should be randomly chosen for evaluation between the start and end index.", new PercentValue(1)));
+    }
+
+    public override IOperation Apply() {
+      double quality;
+      string conditionVariableName = ConditionVariableName == null ? null : ConditionVariableName.Value;
+      int nRows = (int)Math.Ceiling((SamplesEnd.Value - SamplesStart.Value) * RelativeNumberOfEvaluatedSamples.Value);
+      IEnumerable<int> rows = RandomEnumerable.SampleRandomNumbers(Random.Next(), SamplesStart.Value, SamplesEnd.Value, nRows);
+      if (conditionVariableName != null) {
+        rows = from row in rows
+               where !ProblemData.Dataset[conditionVariableName, row].IsAlmost(0.0)
+               select row;
+      }
+
+      quality = Evaluate(TimeSeriesPrognosisModel, ProblemData, TimeSeriesExpressionInterpreter,
+        rows, PredictionHorizon.Value, LowerEstimationLimit, UpperEstimationLimit);
+      QualityParameter.ActualValue = new DoubleValue(quality);
+      return base.Apply();
+    }
+
+    public abstract double Evaluate(SymbolicExpressionTree tree, MultiVariateDataAnalysisProblemData problemData,
+      ISymbolicTimeSeriesExpressionInterpreter interpreter, 
+      IEnumerable<int> rows, int predictionHorizon, DoubleArray lowerEstimationLimit, DoubleArray upperEstimationLimit);
+  }
+}
Index: branches/DataAnalysis/HeuristicLab.Problems.DataAnalysis.MultiVariate.TimeSeriesPrognosis/3.3/Symbolic/Evaluators/SymbolicTimeSeriesPrognosisMahalanobisEvaluator.cs
===================================================================
--- branches/DataAnalysis/HeuristicLab.Problems.DataAnalysis.MultiVariate.TimeSeriesPrognosis/3.3/Symbolic/Evaluators/SymbolicTimeSeriesPrognosisMahalanobisEvaluator.cs	(revision 4475)
+++ branches/DataAnalysis/HeuristicLab.Problems.DataAnalysis.MultiVariate.TimeSeriesPrognosis/3.3/Symbolic/Evaluators/SymbolicTimeSeriesPrognosisMahalanobisEvaluator.cs	(revision 4475)
@@ -0,0 +1,129 @@
+#region License Information
+/* HeuristicLab
+ * Copyright (C) 2002-2010 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.Linq;
+using HeuristicLab.Common;
+using HeuristicLab.Core;
+using HeuristicLab.Data;
+using HeuristicLab.Persistence.Default.CompositeSerializers.Storable;
+using HeuristicLab.Problems.DataAnalysis.SupportVectorMachine;
+using HeuristicLab.Problems.DataAnalysis;
+using HeuristicLab.Problems.DataAnalysis.Evaluators;
+using HeuristicLab.Parameters;
+using HeuristicLab.Optimization;
+using HeuristicLab.Operators;
+using HeuristicLab.Problems.DataAnalysis.Regression.Symbolic;
+using HeuristicLab.Encodings.SymbolicExpressionTreeEncoding;
+using System.Collections.Generic;
+using HeuristicLab.Problems.DataAnalysis.Regression;
+using HeuristicLab.Problems.DataAnalysis.MultiVariate.TimeSeriesPrognosis.Symbolic.Interfaces;
+using HeuristicLab.Problems.DataAnalysis.MultiVariate.Evaluators;
+using HeuristicLab.Problems.DataAnalysis.Symbolic;
+
+namespace HeuristicLab.Problems.DataAnalysis.MultiVariate.TimeSeriesPrognosis.Symbolic.Evaluators {
+  [Item("SymbolicTimeSeriesPrognosisMahalanobisEvaluator", "")]
+  [StorableClass]
+  public class SymbolicTimeSeriesPrognosisMahalanobisEvaluator : SymbolicTimeSeriesPrognosisEvaluator {
+
+    public SymbolicTimeSeriesPrognosisMahalanobisEvaluator()
+      : base() {
+    }
+
+    public override double Evaluate(SymbolicExpressionTree tree, MultiVariateDataAnalysisProblemData problemData, ISymbolicTimeSeriesExpressionInterpreter interpreter, IEnumerable<int> rows, int predictionHorizon, DoubleArray lowerEstimationLimit, DoubleArray upperEstimationLimit) {
+      return Calculate(tree, problemData, interpreter, rows, predictionHorizon, lowerEstimationLimit, upperEstimationLimit);
+    }
+
+    public static double Calculate(SymbolicExpressionTree tree, MultiVariateDataAnalysisProblemData problemData,
+      ISymbolicTimeSeriesExpressionInterpreter interpreter,
+      IEnumerable<int> rows, int predictionHorizon,
+      DoubleArray lowerEstimationLimit, DoubleArray upperEstimationLimit) {
+      double[] alpha, beta;
+      double quality;
+
+      // calculate scaling parameters based on one-step-predictions
+      IEnumerable<string> selectedTargetVariables = from item in problemData.TargetVariables
+                                                    where problemData.TargetVariables.ItemChecked(item)
+                                                    select item.Value;
+      int dimension = selectedTargetVariables.Count();
+
+      IEnumerable<double[]> oneStepPredictions =
+        interpreter.GetSymbolicExpressionTreeValues(tree, problemData.Dataset, selectedTargetVariables, rows, 1);
+      IEnumerable<double[]> originalValues = from row in rows
+                                             select (from targetVariable in selectedTargetVariables
+                                                     select problemData.Dataset[targetVariable, row]).ToArray();
+      alpha = new double[dimension];
+      beta = new double[dimension];
+
+      SymbolicTimeSeriesPrognosisScaledNormalizedMseEvaluator.CalculateScalingParameters(originalValues, oneStepPredictions, ref beta, ref alpha);
+
+      // calculate the quality for the full horizon
+      quality = CalculateWithScaling(tree, problemData, interpreter,
+        rows, predictionHorizon,
+        lowerEstimationLimit, upperEstimationLimit,
+        beta, alpha);
+      return quality;
+
+    }
+
+    public static double CalculateWithScaling(SymbolicExpressionTree tree, MultiVariateDataAnalysisProblemData problemData,
+      ISymbolicTimeSeriesExpressionInterpreter interpreter,
+      IEnumerable<int> rows, int predictionHorizon,
+      DoubleArray lowerEstimationLimit, DoubleArray upperEstimationLimit,
+      double[] alpha, double[] beta) {
+
+
+      IEnumerable<string> selectedTargetVariables = from targetVariable in problemData.TargetVariables
+                                                    where problemData.TargetVariables.ItemChecked(targetVariable)
+                                                    select targetVariable.Value;
+
+      IEnumerable<double[]> estimatedValues =
+        interpreter.GetScaledSymbolicExpressionTreeValues(tree, problemData.Dataset, selectedTargetVariables,
+        rows, predictionHorizon, beta, alpha);
+
+      IEnumerable<double[]> originalValues = from row in rows
+                                             from step in Enumerable.Range(0, predictionHorizon)
+                                             select (from targetVariable in selectedTargetVariables
+                                                     select problemData.Dataset[targetVariable, row + step]).ToArray();
+
+      OnlineMeanMahalanobisDistanceEvaluator evaluator = new OnlineMeanMahalanobisDistanceEvaluator();
+      IEnumerable<double>[] targetValues = (from targetVariable in problemData.TargetVariables.CheckedItems
+                                            select problemData.Dataset.GetEnumeratedVariableValues(targetVariable.Value.Value, rows))
+                                           .ToArray();
+      evaluator.InitializeCovarianceMatrixFromSamples(targetValues);
+
+      var estimatedValuesEnumerator = estimatedValues.GetEnumerator();
+      var originalValuesEnumerator = originalValues.GetEnumerator();
+      while (originalValuesEnumerator.MoveNext() & estimatedValuesEnumerator.MoveNext()) {
+        double[] currentOriginal = originalValuesEnumerator.Current;
+        double[] currentEstimated = estimatedValuesEnumerator.Current;
+        for (int i = 0; i < currentEstimated.Length; i++) {
+          if (double.IsNaN(currentEstimated[i])) currentEstimated[i] = upperEstimationLimit[i];
+          else currentEstimated[i] = Math.Min(upperEstimationLimit[i], Math.Max(lowerEstimationLimit[i], currentEstimated[i]));
+        }
+
+        evaluator.Add(currentOriginal, currentEstimated);
+      }
+
+      return evaluator.MeanGeneralizedSquaredInterpointDistance;
+    }
+  }
+}
Index: branches/DataAnalysis/HeuristicLab.Problems.DataAnalysis.MultiVariate.TimeSeriesPrognosis/3.3/Symbolic/Evaluators/SymbolicTimeSeriesPrognosisNormalizedMseEvaluator.cs
===================================================================
--- branches/DataAnalysis/HeuristicLab.Problems.DataAnalysis.MultiVariate.TimeSeriesPrognosis/3.3/Symbolic/Evaluators/SymbolicTimeSeriesPrognosisNormalizedMseEvaluator.cs	(revision 4464)
+++ branches/DataAnalysis/HeuristicLab.Problems.DataAnalysis.MultiVariate.TimeSeriesPrognosis/3.3/Symbolic/Evaluators/SymbolicTimeSeriesPrognosisNormalizedMseEvaluator.cs	(revision 4475)
@@ -41,132 +41,20 @@
   [Item("SymbolicTimeSeriesPrognosisNormalizedMseEvaluator", "")]
   [StorableClass]
-  public class SymbolicTimeSeriesPrognosisNormalizedMseEvaluator : SingleSuccessorOperator, ISingleObjectiveSymbolicTimeSeriesPrognosisEvaluator {
-    private const string RandomParameterName = "Random";
-    private const string DataAnalysisProblemDataParameterName = "MultiVariateDataAnalysisProblemData";
-    private const string TimeSeriesExpressionInterpreterParameterName = "TimeSeriesExpressionInterpreter";
-    private const string TimeSeriesPrognosisModelParameterName = "TimeSeriesPrognosisModel";
-    private const string PredictionHorizontParameterName = "PredictionHorizon";
-    private const string LowerEstimationLimitParameterName = "LowerEstimationLimit";
-    private const string UpperEstimationLimitParameterName = "UpperEstimationLimit";
-    private const string ConditionVariableParameterName = "ConditionVariableName";
-    private const string SamplesStartParameterName = "SamplesStart";
-    private const string SamplesEndParameterName = "SamplesEnd";
-    private const string QualityParameterName = "Quality";
-    private const string RelativeNumberOfEvaluatedSamplesParameterName = "RelativeNumberOfEvaluatedSamples";
-
-    #region parameter properties
-    public ILookupParameter<IRandom> RandomParameter {
-      get { return (ILookupParameter<IRandom>)Parameters[RandomParameterName]; }
-    }
-    public ILookupParameter<MultiVariateDataAnalysisProblemData> ProblemDataParameter {
-      get { return (ILookupParameter<MultiVariateDataAnalysisProblemData>)Parameters[DataAnalysisProblemDataParameterName]; }
-    }
-    public ILookupParameter<ISymbolicTimeSeriesExpressionInterpreter> TimeSeriesExpressionInterpreterParameter {
-      get { return (ILookupParameter<ISymbolicTimeSeriesExpressionInterpreter>)Parameters[TimeSeriesExpressionInterpreterParameterName]; }
-    }
-    public IValueLookupParameter<IntValue> PredictionHorizonParameter {
-      get { return (IValueLookupParameter<IntValue>)Parameters[PredictionHorizontParameterName]; }
-    }
-    public OptionalValueParameter<StringValue> ConditionVariableNameParameter {
-      get { return (OptionalValueParameter<StringValue>)Parameters[ConditionVariableParameterName]; }
-    }
-    public IValueLookupParameter<IntValue> SamplesStartParameter {
-      get { return (IValueLookupParameter<IntValue>)Parameters[SamplesStartParameterName]; }
-    }
-    public IValueLookupParameter<IntValue> SamplesEndParameter {
-      get { return (IValueLookupParameter<IntValue>)Parameters[SamplesEndParameterName]; }
-    }
-    public IValueLookupParameter<DoubleArray> LowerEstimationLimitParameter {
-      get { return (IValueLookupParameter<DoubleArray>)Parameters[LowerEstimationLimitParameterName]; }
-    }
-    public IValueLookupParameter<DoubleArray> UpperEstimationLimitParameter {
-      get { return (IValueLookupParameter<DoubleArray>)Parameters[UpperEstimationLimitParameterName]; }
-    }
-    public ILookupParameter<SymbolicExpressionTree> TimeSeriesPrognosisModelParameter {
-      get { return (ILookupParameter<SymbolicExpressionTree>)Parameters[TimeSeriesPrognosisModelParameterName]; }
-    }
-    public ILookupParameter<DoubleValue> QualityParameter {
-      get { return (ILookupParameter<DoubleValue>)Parameters[QualityParameterName]; }
-    }
-    public IValueParameter<PercentValue> RelativeNumberOfEvaluatedSamplesParameter {
-      get { return (IValueParameter<PercentValue>)Parameters[RelativeNumberOfEvaluatedSamplesParameterName]; }
-    }
-    #endregion
-    #region
-    public IRandom Random {
-      get { return RandomParameter.ActualValue; }
-    }
-    public MultiVariateDataAnalysisProblemData ProblemData {
-      get { return ProblemDataParameter.ActualValue; }
-    }
-    public ISymbolicTimeSeriesExpressionInterpreter TimeSeriesExpressionInterpreter {
-      get { return TimeSeriesExpressionInterpreterParameter.ActualValue; }
-    }
-    public IntValue PredictionHorizon {
-      get { return PredictionHorizonParameter.ActualValue; }
-    }
-    public StringValue ConditionVariableName {
-      get { return ConditionVariableNameParameter.Value; }
-    }
-    public IntValue SamplesStart {
-      get { return SamplesStartParameter.ActualValue; }
-    }
-    public IntValue SamplesEnd {
-      get { return SamplesEndParameter.ActualValue; }
-    }
-    public DoubleArray LowerEstimationLimit {
-      get { return LowerEstimationLimitParameter.ActualValue; }
-    }
-    public DoubleArray UpperEstimationLimit {
-      get { return UpperEstimationLimitParameter.ActualValue; }
-    }
-    public SymbolicExpressionTree TimeSeriesPrognosisModel {
-      get { return TimeSeriesPrognosisModelParameter.ActualValue; }
-    }
-    public PercentValue RelativeNumberOfEvaluatedSamples {
-      get { return RelativeNumberOfEvaluatedSamplesParameter.Value; }
-    }
-    #endregion
+  public class SymbolicTimeSeriesPrognosisNormalizedMseEvaluator : SymbolicTimeSeriesPrognosisEvaluator {
 
     public SymbolicTimeSeriesPrognosisNormalizedMseEvaluator()
       : base() {
-      Parameters.Add(new LookupParameter<IRandom>(RandomParameterName, "A random number generator."));
-      Parameters.Add(new LookupParameter<MultiVariateDataAnalysisProblemData>(DataAnalysisProblemDataParameterName, "The data analysis problem data to use for training."));
-      Parameters.Add(new LookupParameter<ISymbolicTimeSeriesExpressionInterpreter>(TimeSeriesExpressionInterpreterParameterName, "The interpreter that should be used to evaluate the time series model represented as a symbolic expression tree."));
-      Parameters.Add(new ValueLookupParameter<IntValue>(SamplesStartParameterName, "The first index of the data set partition to use for training."));
-      Parameters.Add(new ValueLookupParameter<IntValue>(SamplesEndParameterName, "The last index of the data set partition to use for training."));
-      Parameters.Add(new ValueLookupParameter<IntValue>(PredictionHorizontParameterName, "The number of time steps for which to create a forecast."));
-      Parameters.Add(new ValueLookupParameter<DoubleArray>(LowerEstimationLimitParameterName, "The lower limit for estimated values."));
-      Parameters.Add(new ValueLookupParameter<DoubleArray>(UpperEstimationLimitParameterName, "The upper limit for estimated values."));
-      Parameters.Add(new OptionalValueParameter<StringValue>(ConditionVariableParameterName, "The name of the condition variable indicating if a row should be considered for evaluation or not."));
-      Parameters.Add(new LookupParameter<SymbolicExpressionTree>(TimeSeriesPrognosisModelParameterName, "The time series prognosis model encoded as a symbolic expression tree."));
-      Parameters.Add(new LookupParameter<DoubleValue>(QualityParameterName, "The quality of the time series prognosis model encoded as a symbolic expression tree."));
-      Parameters.Add(new ValueParameter<PercentValue>(RelativeNumberOfEvaluatedSamplesParameterName, "The relative number of samples of the dataset partition, which should be randomly chosen for evaluation between the start and end index.", new PercentValue(1)));
     }
 
-    public override IOperation Apply() {
-      double quality;
-      string conditionVariableName = ConditionVariableName == null ? null : ConditionVariableName.Value;
-      int nRows = (int)Math.Ceiling((SamplesEnd.Value - SamplesStart.Value) * RelativeNumberOfEvaluatedSamples.Value);
-      IEnumerable<int> rows = RandomEnumerable.SampleRandomNumbers(Random.Next(), SamplesStart.Value, SamplesEnd.Value, nRows);
-
-      quality = Evaluate(TimeSeriesPrognosisModel, ProblemData, TimeSeriesExpressionInterpreter,
-        conditionVariableName, rows, PredictionHorizon.Value, LowerEstimationLimit, UpperEstimationLimit);
-      QualityParameter.ActualValue = new DoubleValue(quality);
-      return base.Apply();
+    public override double Evaluate(SymbolicExpressionTree tree, MultiVariateDataAnalysisProblemData problemData, ISymbolicTimeSeriesExpressionInterpreter interpreter, IEnumerable<int> rows, int predictionHorizon, DoubleArray lowerEstimationLimit, DoubleArray upperEstimationLimit) {
+      return Calculate(tree, problemData, interpreter, rows, predictionHorizon, lowerEstimationLimit, upperEstimationLimit);
     }
 
-    public static double Evaluate(SymbolicExpressionTree tree, MultiVariateDataAnalysisProblemData problemData,
-      ISymbolicTimeSeriesExpressionInterpreter interpreter,
-     IEnumerable<int> rows, int predictionHorizon, DoubleArray lowerEstimationLimit, DoubleArray upperEstimationLimit) {
-      return Evaluate(tree, problemData, interpreter, null, rows, predictionHorizon, lowerEstimationLimit, upperEstimationLimit);
-    }
-
-    public static double Evaluate(SymbolicExpressionTree tree, MultiVariateDataAnalysisProblemData problemData,
-      ISymbolicTimeSeriesExpressionInterpreter interpreter, string conditionVariableName,
+    public static double Calculate(SymbolicExpressionTree tree, MultiVariateDataAnalysisProblemData problemData,
+      ISymbolicTimeSeriesExpressionInterpreter interpreter, 
       IEnumerable<int> rows, int predictionHorizon, DoubleArray lowerEstimationLimit, DoubleArray upperEstimationLimit) {
       double[] zeros = new double[problemData.TargetVariables.CheckedItems.Count()];
       double[] ones = Enumerable.Repeat(1.0, zeros.Length).ToArray();
-      return SymbolicTimeSeriesPrognosisScaledNormalizedMseEvaluator.Evaluate(tree, problemData, interpreter, conditionVariableName, rows,
+      return SymbolicTimeSeriesPrognosisScaledNormalizedMseEvaluator.CalculateWithScaling(tree, problemData, interpreter, rows,
         predictionHorizon, lowerEstimationLimit, upperEstimationLimit, ones, zeros);
     }
Index: branches/DataAnalysis/HeuristicLab.Problems.DataAnalysis.MultiVariate.TimeSeriesPrognosis/3.3/Symbolic/Evaluators/SymbolicTimeSeriesPrognosisScaledNormalizedMseEvaluator.cs
===================================================================
--- branches/DataAnalysis/HeuristicLab.Problems.DataAnalysis.MultiVariate.TimeSeriesPrognosis/3.3/Symbolic/Evaluators/SymbolicTimeSeriesPrognosisScaledNormalizedMseEvaluator.cs	(revision 4464)
+++ branches/DataAnalysis/HeuristicLab.Problems.DataAnalysis.MultiVariate.TimeSeriesPrognosis/3.3/Symbolic/Evaluators/SymbolicTimeSeriesPrognosisScaledNormalizedMseEvaluator.cs	(revision 4475)
@@ -37,162 +37,52 @@
 using HeuristicLab.Problems.DataAnalysis.Regression;
 using HeuristicLab.Problems.DataAnalysis.MultiVariate.TimeSeriesPrognosis.Symbolic.Interfaces;
+using HeuristicLab.Problems.DataAnalysis.MultiVariate.Evaluators;
 
 namespace HeuristicLab.Problems.DataAnalysis.MultiVariate.TimeSeriesPrognosis.Symbolic.Evaluators {
   [Item("SymbolicTimeSeriesPrognosisScaledNormalizedMseEvaluator", "")]
   [StorableClass]
-  public class SymbolicTimeSeriesPrognosisScaledNormalizedMseEvaluator : SingleSuccessorOperator, ISingleObjectiveSymbolicTimeSeriesPrognosisEvaluator {
-    private const string RandomParameterName = "Random";
-    private const string DataAnalysisProblemDataParameterName = "MultiVariateDataAnalysisProblemData";
-    private const string TimeSeriesExpressionInterpreterParameterName = "TimeSeriesExpressionInterpreter";
-    private const string TimeSeriesPrognosisModelParameterName = "TimeSeriesPrognosisModel";
-    private const string PredictionHorizontParameterName = "PredictionHorizon";
-    private const string ConditionVariableParameterName = "ConditionVariableName";
-    private const string SamplesStartParameterName = "SamplesStart";
-    private const string SamplesEndParameterName = "SamplesEnd";
-    private const string AlphaParameterName = "Alpha";
-    private const string BetaParameterName = "Beta";
-    private const string LowerEstimationLimitParameterName = "LowerEstimationLimit";
-    private const string UpperEstimationLimitParameterName = "UpperEstimationLimit";
-    private const string QualityParameterName = "Quality";
-    private const string RelativeNumberOfEvaluatedSamplesParameterName = "RelativeNumberOfEvaluatedSamples";
-
-    #region parameter properties
-    public ILookupParameter<IRandom> RandomParameter {
-      get { return (ILookupParameter<IRandom>)Parameters[RandomParameterName]; }
-    }
-    public ILookupParameter<MultiVariateDataAnalysisProblemData> ProblemDataParameter {
-      get { return (ILookupParameter<MultiVariateDataAnalysisProblemData>)Parameters[DataAnalysisProblemDataParameterName]; }
-    }
-    public ILookupParameter<ISymbolicTimeSeriesExpressionInterpreter> TimeSeriesExpressionInterpreterParameter {
-      get { return (ILookupParameter<ISymbolicTimeSeriesExpressionInterpreter>)Parameters[TimeSeriesExpressionInterpreterParameterName]; }
-    }
-    public IValueLookupParameter<IntValue> PredictionHorizonParameter {
-      get { return (IValueLookupParameter<IntValue>)Parameters[PredictionHorizontParameterName]; }
-    }
-    public OptionalValueParameter<StringValue> ConditionVariableNameParameter {
-      get { return (OptionalValueParameter<StringValue>)Parameters[ConditionVariableParameterName]; }
-    }
-    public IValueLookupParameter<IntValue> SamplesStartParameter {
-      get { return (IValueLookupParameter<IntValue>)Parameters[SamplesStartParameterName]; }
-    }
-    public IValueLookupParameter<IntValue> SamplesEndParameter {
-      get { return (IValueLookupParameter<IntValue>)Parameters[SamplesEndParameterName]; }
-    }
-    public ILookupParameter<SymbolicExpressionTree> TimeSeriesPrognosisModelParameter {
-      get { return (ILookupParameter<SymbolicExpressionTree>)Parameters[TimeSeriesPrognosisModelParameterName]; }
-    }
-    public ILookupParameter<DoubleValue> QualityParameter {
-      get { return (ILookupParameter<DoubleValue>)Parameters[QualityParameterName]; }
-    }
-    public ILookupParameter<DoubleArray> AlphaParameter {
-      get { return (ILookupParameter<DoubleArray>)Parameters[AlphaParameterName]; }
-    }
-    public ILookupParameter<DoubleArray> BetaParameter {
-      get { return (ILookupParameter<DoubleArray>)Parameters[BetaParameterName]; }
-    }
-    public IValueLookupParameter<DoubleArray> LowerEstimationLimitParameter {
-      get { return (IValueLookupParameter<DoubleArray>)Parameters[LowerEstimationLimitParameterName]; }
-    }
-    public IValueLookupParameter<DoubleArray> UpperEstimationLimitParameter {
-      get { return (IValueLookupParameter<DoubleArray>)Parameters[UpperEstimationLimitParameterName]; }
-    }
-    public IValueParameter<PercentValue> RelativeNumberOfEvaluatedSamplesParameter {
-      get { return (IValueParameter<PercentValue>)Parameters[RelativeNumberOfEvaluatedSamplesParameterName]; }
-    }
-
-    #endregion
-    #region properties
-    public IRandom Random {
-      get { return RandomParameter.ActualValue; }
-    }
-    public MultiVariateDataAnalysisProblemData ProblemData {
-      get { return ProblemDataParameter.ActualValue; }
-    }
-    public ISymbolicTimeSeriesExpressionInterpreter TimeSeriesExpressionInterpreter {
-      get { return TimeSeriesExpressionInterpreterParameter.ActualValue; }
-    }
-    public IntValue PredictionHorizon {
-      get { return PredictionHorizonParameter.ActualValue; }
-    }
-    public StringValue ConditionVariableName {
-      get { return ConditionVariableNameParameter.Value; }
-    }
-    public IntValue SamplesStart {
-      get { return SamplesStartParameter.ActualValue; }
-    }
-    public IntValue SamplesEnd {
-      get { return SamplesEndParameter.ActualValue; }
-    }
-    public DoubleArray LowerEstimationLimit {
-      get { return LowerEstimationLimitParameter.ActualValue; }
-    }
-    public DoubleArray UpperEstimationLimit {
-      get { return UpperEstimationLimitParameter.ActualValue; }
-    }
-    public SymbolicExpressionTree TimeSeriesPrognosisModel {
-      get { return TimeSeriesPrognosisModelParameter.ActualValue; }
-    }
-    public PercentValue RelativeNumberOfEvaluatedSamples {
-      get { return RelativeNumberOfEvaluatedSamplesParameter.Value; }
-    }
-    #endregion
+  public class SymbolicTimeSeriesPrognosisScaledNormalizedMseEvaluator : SymbolicTimeSeriesPrognosisEvaluator {
 
     public SymbolicTimeSeriesPrognosisScaledNormalizedMseEvaluator()
       : base() {
-      Parameters.Add(new LookupParameter<IRandom>(RandomParameterName, "A random number generator."));
-      Parameters.Add(new LookupParameter<MultiVariateDataAnalysisProblemData>(DataAnalysisProblemDataParameterName, "The data analysis problem data to use for training."));
-      Parameters.Add(new LookupParameter<ISymbolicTimeSeriesExpressionInterpreter>(TimeSeriesExpressionInterpreterParameterName, "The interpreter that should be used to evaluate the time series model represented as a symbolic expression tree."));
-      Parameters.Add(new ValueLookupParameter<IntValue>(SamplesStartParameterName, "The first index of the data set partition to use for training."));
-      Parameters.Add(new ValueLookupParameter<IntValue>(SamplesEndParameterName, "The last index of the data set partition to use for training."));
-      Parameters.Add(new ValueLookupParameter<IntValue>(PredictionHorizontParameterName, "The number of time steps for which to create a forecast."));
-      Parameters.Add(new ValueLookupParameter<DoubleArray>(LowerEstimationLimitParameterName, "The lower limit for estimated values."));
-      Parameters.Add(new ValueLookupParameter<DoubleArray>(UpperEstimationLimitParameterName, "The upper limit for estimated values."));
-      Parameters.Add(new OptionalValueParameter<StringValue>(ConditionVariableParameterName, "The name of the condition variable indicating if a row should be considered for evaluation or not."));
-      Parameters.Add(new LookupParameter<SymbolicExpressionTree>(TimeSeriesPrognosisModelParameterName, "The time series prognosis model encoded as a symbolic expression tree."));
-      Parameters.Add(new LookupParameter<DoubleValue>(QualityParameterName, "The quality of the time series prognosis model encoded as a symbolic expression tree."));
-      Parameters.Add(new LookupParameter<DoubleArray>(AlphaParameterName, "The alpha parameter for linear scaling based on one step predictions."));
-      Parameters.Add(new LookupParameter<DoubleArray>(BetaParameterName, "The beta parameter for linear scaling based on one step predictions."));
-      Parameters.Add(new ValueParameter<PercentValue>(RelativeNumberOfEvaluatedSamplesParameterName, "The relative number of samples of the dataset partition, which should be randomly chosen for evaluation between the start and end index.", new PercentValue(1)));
     }
 
-    public override IOperation Apply() {
+    public override double Evaluate(SymbolicExpressionTree tree, MultiVariateDataAnalysisProblemData problemData, ISymbolicTimeSeriesExpressionInterpreter interpreter, IEnumerable<int> rows, int predictionHorizon, DoubleArray lowerEstimationLimit, DoubleArray upperEstimationLimit) {
+      return Calculate(tree, problemData, interpreter, rows, predictionHorizon, lowerEstimationLimit, upperEstimationLimit);
+    }
+
+    public static double Calculate(SymbolicExpressionTree tree, MultiVariateDataAnalysisProblemData problemData, ISymbolicTimeSeriesExpressionInterpreter interpreter, IEnumerable<int> rows, int predictionHorizon, DoubleArray lowerEstimationLimit, DoubleArray upperEstimationLimit) {
       double[] alpha, beta;
       double quality;
-      string conditionVariableName = ConditionVariableName == null ? null : ConditionVariableName.Value;
-      int nRows = (int)Math.Ceiling((SamplesEnd.Value - SamplesStart.Value) * RelativeNumberOfEvaluatedSamples.Value);
 
-      IEnumerable<int> rows = RandomEnumerable.SampleRandomNumbers(Random.Next(), SamplesStart.Value, SamplesEnd.Value, nRows);
-      CalculateScalingParameters(TimeSeriesPrognosisModel, ProblemData, TimeSeriesExpressionInterpreter,
-        conditionVariableName, rows,
-        out beta, out alpha);
+      // calculate scaling parameters based on one-step-predictions
+      IEnumerable<string> selectedTargetVariables = from item in problemData.TargetVariables
+                                                    where problemData.TargetVariables.ItemChecked(item)
+                                                    select item.Value;
+      int dimension = selectedTargetVariables.Count();
 
-      quality = Evaluate(TimeSeriesPrognosisModel, ProblemData, TimeSeriesExpressionInterpreter,
-        conditionVariableName, rows, PredictionHorizon.Value,
-        LowerEstimationLimit, UpperEstimationLimit,
+      IEnumerable<double[]> oneStepPredictions =
+        interpreter.GetSymbolicExpressionTreeValues(tree, problemData.Dataset, selectedTargetVariables, rows, 1);
+      IEnumerable<double[]> originalValues = from row in rows
+                                             select (from targetVariable in selectedTargetVariables
+                                                     select problemData.Dataset[targetVariable, row]).ToArray();
+      alpha = new double[dimension];
+      beta = new double[dimension];
+
+      CalculateScalingParameters(originalValues, oneStepPredictions, ref beta, ref alpha);
+
+      // calculate the quality for the full horizon
+      quality = CalculateWithScaling(tree, problemData, interpreter,
+        rows, predictionHorizon,
+        lowerEstimationLimit, upperEstimationLimit,
         beta, alpha);
-      QualityParameter.ActualValue = new DoubleValue(quality);
-      AlphaParameter.ActualValue = new DoubleArray(alpha);
-      BetaParameter.ActualValue = new DoubleArray(beta);
-      return base.Apply();
+      return quality;
     }
 
-    public static double Evaluate(SymbolicExpressionTree tree, MultiVariateDataAnalysisProblemData problemData,
+    public static double CalculateWithScaling(SymbolicExpressionTree tree, MultiVariateDataAnalysisProblemData problemData,
       ISymbolicTimeSeriesExpressionInterpreter interpreter,
-      IEnumerable<int> rows, int predictionHorizon, 
-      DoubleArray lowerEstimationLimit, DoubleArray upperEstimationLimit,
-      double[] beta, double[] alpha) {
-      return Evaluate(tree, problemData, interpreter, null, rows, predictionHorizon, lowerEstimationLimit, upperEstimationLimit, beta, alpha);
-    }
-
-    public static double Evaluate(SymbolicExpressionTree tree, MultiVariateDataAnalysisProblemData problemData,
-      ISymbolicTimeSeriesExpressionInterpreter interpreter, string conditionVariableName,
       IEnumerable<int> rows, int predictionHorizon,
       DoubleArray lowerEstimationLimit, DoubleArray upperEstimationLimit,
       double[] beta, double[] alpha) {
-      if (conditionVariableName != null) {
-        rows = from row in rows
-               where !problemData.Dataset[conditionVariableName, row].IsAlmost(0.0)
-               select row;
-      }
       IEnumerable<string> selectedTargetVariables = from targetVariable in problemData.TargetVariables
                                                     where problemData.TargetVariables.ItemChecked(targetVariable)
@@ -208,7 +98,5 @@
                                                      select problemData.Dataset[targetVariable, row + step]).ToArray();
 
-      List<OnlineNormalizedMeanSquaredErrorEvaluator> evaluators = new List<OnlineNormalizedMeanSquaredErrorEvaluator>();
-      foreach (string targetVariable in selectedTargetVariables)
-        evaluators.Add(new OnlineNormalizedMeanSquaredErrorEvaluator());
+      var evaluator = new OnlineMultiVariateEvaluator<OnlineNormalizedMeanSquaredErrorEvaluator>();
 
       var estimatedValuesEnumerator = estimatedValues.GetEnumerator();
@@ -217,80 +105,64 @@
         double[] original = originalValuesEnumerator.Current;
         double[] estimated = estimatedValuesEnumerator.Current;
-        for (int i = 0; i < evaluators.Count; i++) {
+        for (int i = 0; i < estimated.Length; i++) {
           if (double.IsNaN(estimated[i])) estimated[i] = upperEstimationLimit[i];
           else estimated[i] = Math.Min(upperEstimationLimit[i], Math.Max(lowerEstimationLimit[i], estimated[i]));
-          evaluators[i].Add(original[i], estimated[i]);
         }
+        evaluator.Add(original, estimated);
       }
 
-      double quality = evaluators.Select(x => x.NormalizedMeanSquaredError).Sum();
+      double quality = evaluator.Value;
       return quality;
     }
 
-    public static void CalculateScalingParameters(SymbolicExpressionTree tree, MultiVariateDataAnalysisProblemData problemData,
-      ISymbolicTimeSeriesExpressionInterpreter interpreter,
-      IEnumerable<int> rows, 
-      out double[] betas, out double[] alphas) {
-      CalculateScalingParameters(tree, problemData, interpreter, null, rows, out betas, out alphas);
-    }
-
-    public static void CalculateScalingParameters(SymbolicExpressionTree tree, MultiVariateDataAnalysisProblemData problemData,
-      ISymbolicTimeSeriesExpressionInterpreter interpreter, string conditionVariableName,
-      IEnumerable<int> rows, out double[] betas, out double[] alphas) {
-      IEnumerable<string> selectedTargetVariables = from item in problemData.TargetVariables
-                                                    where problemData.TargetVariables.ItemChecked(item)
-                                                    select item.Value;
-      int dimension = selectedTargetVariables.Count();
-
-      if (conditionVariableName != null) {
-        rows = from row in rows
-               where !problemData.Dataset[conditionVariableName, row].IsAlmost(0.0)
-               select row;
-      }
-
-      IEnumerable<double[]> oneStepPredictions =
-        interpreter.GetSymbolicExpressionTreeValues(tree, problemData.Dataset, selectedTargetVariables, rows, 1);
-      IEnumerable<double[]> originalValues = from row in rows
-                                             select (from targetVariable in selectedTargetVariables
-                                                     select problemData.Dataset[targetVariable, row]).ToArray();
-
-      alphas = new double[dimension];
-      betas = new double[dimension];
-      int[] cnt = new int[dimension];
+    public static void CalculateScalingParameters(IEnumerable<double[]> originalValues, IEnumerable<double[]> estimatedValues, ref double[] beta, ref double[] alpha) {
       List<OnlineMeanAndVarianceCalculator> estimatedVarianceEvaluators = new List<OnlineMeanAndVarianceCalculator>();
       List<OnlineCovarianceEvaluator> covarianceEvaluators = new List<OnlineCovarianceEvaluator>();
       List<OnlineMeanAndVarianceCalculator> originalMeanCalculators = new List<OnlineMeanAndVarianceCalculator>();
-      foreach (var selectedTargetVariable in selectedTargetVariables) {
-        estimatedVarianceEvaluators.Add(new OnlineMeanAndVarianceCalculator());
-        covarianceEvaluators.Add(new OnlineCovarianceEvaluator());
-        originalMeanCalculators.Add(new OnlineMeanAndVarianceCalculator());
-      }
-      var estimatedEnumerator = oneStepPredictions.GetEnumerator();
+      int[] cnt = null;
+
+      var estimatedEnumerator = estimatedValues.GetEnumerator();
       var originalEnumerator = originalValues.GetEnumerator();
       while (estimatedEnumerator.MoveNext() & originalEnumerator.MoveNext()) {
         double[] original = originalEnumerator.Current;
         double[] estimated = estimatedEnumerator.Current;
-        for (int component = 0; component < dimension; component++) {
-          if (IsValidValue(original[component]) && IsValidValue(estimated[component])) {
-            cnt[component]++;
-            estimatedVarianceEvaluators[component].Add(estimated[component]);
-            covarianceEvaluators[component].Add(original[component], estimated[component]);
-            originalMeanCalculators[component].Add(original[component]);
+        int dimension = original.Length;
+        // initialize
+        if (cnt == null) {
+          cnt = new int[dimension];
+          for (int i = 0; i < dimension; i++) {
+            estimatedVarianceEvaluators.Add(new OnlineMeanAndVarianceCalculator());
+            covarianceEvaluators.Add(new OnlineCovarianceEvaluator());
+            originalMeanCalculators.Add(new OnlineMeanAndVarianceCalculator());
           }
+        } else if (cnt.Length == dimension) {
+          for (int component = 0; component < dimension; component++) {
+            if (IsValidValue(original[component]) && IsValidValue(estimated[component])) {
+              cnt[component]++;
+              estimatedVarianceEvaluators[component].Add(estimated[component]);
+              covarianceEvaluators[component].Add(original[component], estimated[component]);
+              originalMeanCalculators[component].Add(original[component]);
+            }
+          }
+        } else {
+          throw new ArgumentException("Dimension of input array doesn't match");
         }
       }
+
       if (estimatedEnumerator.MoveNext() || originalEnumerator.MoveNext())
         throw new InvalidOperationException("Number of elements in estimated and original series doesn't match.");
-      for (int component = 0; component < dimension; component++) {
+      if (cnt == null) throw new ArgumentException("No elements in estimated and original.");
+
+      for (int component = 0; component < cnt.Length; component++) {
         if (cnt[component] < 2) {
-          alphas[component] = 0;
-          betas[component] = 1;
+          alpha[component] = 0;
+          beta[component] = 1;
         } else {
           if (estimatedVarianceEvaluators[component].PopulationVariance.IsAlmost(0.0))
-            betas[component] = 1;
+            beta[component] = 1;
           else
-            betas[component] = covarianceEvaluators[component].Covariance / estimatedVarianceEvaluators[component].PopulationVariance;
+            beta[component] = covarianceEvaluators[component].Covariance / estimatedVarianceEvaluators[component].PopulationVariance;
 
-          alphas[component] = originalMeanCalculators[component].Mean - betas[component] * estimatedVarianceEvaluators[component].Mean;
+          alpha[component] = originalMeanCalculators[component].Mean - beta[component] * estimatedVarianceEvaluators[component].Mean;
         }
       }
Index: branches/DataAnalysis/HeuristicLab.Problems.DataAnalysis.MultiVariate.TimeSeriesPrognosis/3.3/Symbolic/Interfaces/ISingleObjectiveSymbolicTimeSeriesPrognosisEvaluator.cs
===================================================================
--- branches/DataAnalysis/HeuristicLab.Problems.DataAnalysis.MultiVariate.TimeSeriesPrognosis/3.3/Symbolic/Interfaces/ISingleObjectiveSymbolicTimeSeriesPrognosisEvaluator.cs	(revision 4464)
+++ branches/DataAnalysis/HeuristicLab.Problems.DataAnalysis.MultiVariate.TimeSeriesPrognosis/3.3/Symbolic/Interfaces/ISingleObjectiveSymbolicTimeSeriesPrognosisEvaluator.cs	(revision 4475)
@@ -35,4 +35,7 @@
 namespace HeuristicLab.Problems.DataAnalysis.MultiVariate.TimeSeriesPrognosis.Symbolic.Interfaces {
   public interface ISingleObjectiveSymbolicTimeSeriesPrognosisEvaluator : ISymbolicTimeSeriesPrognosisEvaluator, ISingleObjectiveEvaluator {
+    double Evaluate(SymbolicExpressionTree tree, MultiVariateDataAnalysisProblemData problemData,
+      ISymbolicTimeSeriesExpressionInterpreter interpreter,
+      IEnumerable<int> rows, int predictionHorizon, DoubleArray lowerEstimationLimit, DoubleArray upperEstimationLimit);
   }
 
Index: branches/DataAnalysis/HeuristicLab.Problems.DataAnalysis.MultiVariate.TimeSeriesPrognosis/3.3/Symbolic/SymbolicTimeSeriesExpressionInterpreter.cs
===================================================================
--- branches/DataAnalysis/HeuristicLab.Problems.DataAnalysis.MultiVariate.TimeSeriesPrognosis/3.3/Symbolic/SymbolicTimeSeriesExpressionInterpreter.cs	(revision 4464)
+++ branches/DataAnalysis/HeuristicLab.Problems.DataAnalysis.MultiVariate.TimeSeriesPrognosis/3.3/Symbolic/SymbolicTimeSeriesExpressionInterpreter.cs	(revision 4475)
@@ -201,11 +201,9 @@
 
     private Instruction PostProcessInstruction(Instruction instr) {
-      if (instr.opCode == OpCodes.Variable) {
+      if (instr.opCode == OpCodes.Variable || instr.opCode == OpCodes.LagVariable || 
+        instr.opCode == OpCodes.Integral || instr.opCode == OpCodes.MovingAverage || instr.opCode == OpCodes.Differential) {
         var variableTreeNode = instr.dynamicNode as VariableTreeNode;
         instr.iArg0 = (ushort)dataset.GetVariableIndex(variableTreeNode.VariableName);
-      } else if (instr.opCode == OpCodes.LagVariable) {
-        var variableTreeNode = instr.dynamicNode as LaggedVariableTreeNode;
-        instr.iArg0 = (ushort)dataset.GetVariableIndex(variableTreeNode.VariableName);
-      }
+      } 
       return instr;
     }
@@ -361,7 +359,7 @@
             double sum = 0.0;
             for (int relativeRow = movingAvgTreeNode.MinTimeOffset; relativeRow < movingAvgTreeNode.MaxTimeOffset; relativeRow++) {
-              sum += GetVariableValue(currentInstr.iArg0, relativeRow) * movingAvgTreeNode.Weight;
-            }
-            return sum / (movingAvgTreeNode.MaxTimeOffset - movingAvgTreeNode.MinTimeOffset);
+              sum += GetVariableValue(currentInstr.iArg0, relativeRow);
+            }
+            return movingAvgTreeNode.Weight * sum / (movingAvgTreeNode.MaxTimeOffset - movingAvgTreeNode.MinTimeOffset);
           }
         case OpCodes.Differential: {
@@ -369,8 +367,8 @@
             if (row + diffTreeNode.Lag - 2 < 0 || row + diffTreeNode.Lag >= dataset.Rows)
               return double.NaN;
-            double y_0 = GetVariableValue(currentInstr.iArg0, diffTreeNode.Lag) * diffTreeNode.Weight;
-            double y_1 = GetVariableValue(currentInstr.iArg0, diffTreeNode.Lag - 1) * diffTreeNode.Weight;
-            double y_2 = GetVariableValue(currentInstr.iArg0, diffTreeNode.Lag - 2) * diffTreeNode.Weight;
-            return (3 * y_0 - 4 * y_1 + 3 * y_2) / 2;
+            double y_0 = GetVariableValue(currentInstr.iArg0, diffTreeNode.Lag);
+            double y_1 = GetVariableValue(currentInstr.iArg0, diffTreeNode.Lag - 1);
+            double y_2 = GetVariableValue(currentInstr.iArg0, diffTreeNode.Lag - 2);
+            return diffTreeNode.Weight * (3 * y_0 - 4 * y_1 + 3 * y_2) / 2;
           }
         case OpCodes.Integral: {
@@ -380,7 +378,7 @@
             double sum = 0;
             for (int relativeRow = integralVarTreeNode.MinTimeOffset; relativeRow < integralVarTreeNode.MaxTimeOffset; relativeRow++) {
-              sum += GetVariableValue(currentInstr.iArg0, relativeRow) * integralVarTreeNode.Weight;
-            }
-            return sum;
+              sum += GetVariableValue(currentInstr.iArg0, relativeRow);
+            }
+            return integralVarTreeNode.Weight * sum;
           }
         case OpCodes.Constant: {
Index: branches/DataAnalysis/HeuristicLab.Problems.DataAnalysis.MultiVariate.TimeSeriesPrognosis/3.3/Symbolic/SymbolicTimeSeriesPrognosisSolution.cs
===================================================================
--- branches/DataAnalysis/HeuristicLab.Problems.DataAnalysis.MultiVariate.TimeSeriesPrognosis/3.3/Symbolic/SymbolicTimeSeriesPrognosisSolution.cs	(revision 4464)
+++ branches/DataAnalysis/HeuristicLab.Problems.DataAnalysis.MultiVariate.TimeSeriesPrognosis/3.3/Symbolic/SymbolicTimeSeriesPrognosisSolution.cs	(revision 4475)
@@ -31,4 +31,5 @@
 using System.Drawing;
 using System;
+using HeuristicLab.Data;
 
 namespace HeuristicLab.Problems.DataAnalysis.MultiVariate.TimeSeriesPrognosis.Symbolic {
@@ -44,4 +45,8 @@
     [Storable]
     private string conditionalEvaluationVariable;
+    [Storable]
+    private double[] lowerEstimationLimit;
+    [Storable]
+    private double[] upperEstimationLimit;
 
     public string Filename { get; set; }
@@ -54,5 +59,5 @@
     }
 
-    public SymbolicTimeSeriesPrognosisSolution(MultiVariateDataAnalysisProblemData problemData, SymbolicTimeSeriesPrognosisModel model, int horizon, string conditionalEvaluationVariable)
+    public SymbolicTimeSeriesPrognosisSolution(MultiVariateDataAnalysisProblemData problemData, SymbolicTimeSeriesPrognosisModel model, int horizon, string conditionalEvaluationVariable, double[] lowerEstimationLimit, double[] upperEstimationLimit)
       : this() {
       this.problemData = problemData;
@@ -60,4 +65,6 @@
       this.horizon = horizon;
       this.conditionalEvaluationVariable = conditionalEvaluationVariable;
+      this.lowerEstimationLimit = (double[])lowerEstimationLimit.Clone();
+      this.upperEstimationLimit = (double[])upperEstimationLimit.Clone();
     }
 
@@ -99,4 +106,11 @@
         }
       }
+    }
+
+    public double GetLowerEstimationLimit(int i) {
+      return lowerEstimationLimit[i];
+    }
+    public double GetUpperEstimationLimit(int i) {
+      return upperEstimationLimit[i];
     }
 
@@ -139,5 +153,5 @@
     public IEnumerable<double[]> EstimatedValues {
       get {
-        return model.GetEstimatedValues(problemData, 0, problemData.Dataset.Rows);
+        return ApplyEstimationLimits(model.GetEstimatedValues(problemData, 0, problemData.Dataset.Rows));
       }
     }
@@ -145,5 +159,5 @@
     public IEnumerable<double[]> EstimatedTrainingValues {
       get {
-        return model.GetEstimatedValues(problemData, problemData.TrainingSamplesStart.Value, problemData.TrainingSamplesEnd.Value);
+        return ApplyEstimationLimits(model.GetEstimatedValues(problemData, problemData.TrainingSamplesStart.Value, problemData.TrainingSamplesEnd.Value));
       }
     }
@@ -151,5 +165,5 @@
     public IEnumerable<double[]> EstimatedTestValues {
       get {
-        return model.GetEstimatedValues(problemData, problemData.TestSamplesStart.Value, problemData.TestSamplesEnd.Value);
+        return ApplyEstimationLimits(model.GetEstimatedValues(problemData, problemData.TestSamplesStart.Value, problemData.TestSamplesEnd.Value));
       }
     }
@@ -198,5 +212,16 @@
       clone.horizon = horizon;
       clone.conditionalEvaluationVariable = conditionalEvaluationVariable;
+      clone.lowerEstimationLimit = (double[])lowerEstimationLimit.Clone();
+      clone.upperEstimationLimit = (double[])upperEstimationLimit.Clone();
       return clone;
+    }
+
+    private IEnumerable<double[]> ApplyEstimationLimits(IEnumerable<double[]> values) {
+      foreach (var xs in values) {
+        for (int i = 0; i < xs.Length; i++) {
+          xs[i] = Math.Max(lowerEstimationLimit[i], Math.Min(upperEstimationLimit[i], xs[i]));
+        }
+        yield return xs;
+      }
     }
   }
Index: branches/DataAnalysis/HeuristicLab.Problems.DataAnalysis.MultiVariate/3.3/Evaluators/OnlineMeanMahalanobisDistanceEvaluator.cs
===================================================================
--- branches/DataAnalysis/HeuristicLab.Problems.DataAnalysis.MultiVariate/3.3/Evaluators/OnlineMeanMahalanobisDistanceEvaluator.cs	(revision 4475)
+++ branches/DataAnalysis/HeuristicLab.Problems.DataAnalysis.MultiVariate/3.3/Evaluators/OnlineMeanMahalanobisDistanceEvaluator.cs	(revision 4475)
@@ -0,0 +1,92 @@
+﻿using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using HeuristicLab.Core;
+using HeuristicLab.Data;
+using HeuristicLab.Problems.DataAnalysis.Evaluators;
+using HeuristicLab.Persistence.Default.CompositeSerializers.Storable;
+using HeuristicLab.Parameters;
+
+namespace HeuristicLab.Problems.DataAnalysis.MultiVariate.Evaluators {
+  public class OnlineMeanMahalanobisDistanceEvaluator : IMultiVariateOnlineEvaluator {
+    private int n;
+    private double distance;
+    private double[,] covMatrix;
+    public double MeanMahalanobisDistance {
+      get {
+        if (n == 0) throw new InvalidOperationException("no elements");
+        else
+          return Math.Sqrt(distance) / n;
+      }
+    }
+
+    public double MeanGeneralizedSquaredInterpointDistance {
+      get {
+        if (n == 0) throw new InvalidOperationException("no elements");
+        else
+          return distance / n;
+      }
+    }
+
+    public OnlineMeanMahalanobisDistanceEvaluator() {
+      Reset();
+    }
+
+    #region IMultiVariateOnlineEvaluator Members
+    public double Value {
+      get { return MeanMahalanobisDistance; }
+    }
+
+    public void Add(double[] original, double[] estimated) {
+      if (original.Length != estimated.Length) throw new ArgumentException("Number of elements of original and estimated doesn't match.");
+      if (original.Length != covMatrix.GetLength(0)) throw new ArgumentException("Original and estimated is not compatible with covariance matrix.");
+
+      double[] diff = new double[original.Length];
+      for (int i = 0; i < diff.Length; i++) {
+        diff[i] = original[i] - estimated[i];
+      }
+      double[] target = new double[original.Length];
+
+      alglib.ablas.rmatrixmv(covMatrix.GetLength(0), covMatrix.GetLength(1), ref covMatrix, 0, 0, 0, ref diff, 0, ref target, 0);
+
+      double sum = 0.0;
+      for (int i = 0; i < original.Length; i++) {
+        sum += diff[i] * target[i];
+      }
+      distance += sum;
+      n++;
+    }
+
+    public void Reset() {
+      n = 0;
+      distance = 0.0;
+    }
+
+    #endregion
+
+    public void InitializeCovarianceMatrixFromSamples(params IEnumerable<double>[] samples) {
+      covMatrix = new double[samples.Length, samples.Length];
+      OnlineCovarianceEvaluator covEvaluator = new OnlineCovarianceEvaluator();
+      for (int i = 0; i < samples.Length; i++) {
+        for (int j = i; j < samples.Length; j++) {
+          var xEnumerator = samples[i].GetEnumerator();
+          var yEnumerator = samples[j].GetEnumerator();
+          covEvaluator.Reset();
+          while (xEnumerator.MoveNext() & yEnumerator.MoveNext()) {
+            covEvaluator.Add(xEnumerator.Current, yEnumerator.Current);
+          }
+          if (xEnumerator.MoveNext() | yEnumerator.MoveNext()) {
+            throw new ArgumentException("Number of elements must be the same in all enumerations.");
+          }
+          covMatrix[i, j] = covEvaluator.Covariance;
+          covMatrix[j, i] = covEvaluator.Covariance;
+        }
+      }
+      int info = 0;
+      alglib.matinv.matinvreport report = new alglib.matinv.matinvreport();
+      alglib.matinv.rmatrixinverse(ref covMatrix, covMatrix.GetLength(0), ref info, ref report);
+      if (info != 1) throw new InvalidOperationException("Can't invert covariance matrix.");
+    }
+  }
+}
Index: branches/DataAnalysis/HeuristicLab.Problems.DataAnalysis.MultiVariate/3.3/Evaluators/OnlineMultiVariateEvaluator.cs
===================================================================
--- branches/DataAnalysis/HeuristicLab.Problems.DataAnalysis.MultiVariate/3.3/Evaluators/OnlineMultiVariateEvaluator.cs	(revision 4475)
+++ branches/DataAnalysis/HeuristicLab.Problems.DataAnalysis.MultiVariate/3.3/Evaluators/OnlineMultiVariateEvaluator.cs	(revision 4475)
@@ -0,0 +1,50 @@
+﻿using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using HeuristicLab.Core;
+using HeuristicLab.Data;
+using HeuristicLab.Problems.DataAnalysis.Evaluators;
+using HeuristicLab.Persistence.Default.CompositeSerializers.Storable;
+using HeuristicLab.Parameters;
+
+namespace HeuristicLab.Problems.DataAnalysis.MultiVariate.Evaluators {
+  public class OnlineMultiVariateEvaluator<T> : IMultiVariateOnlineEvaluator where T : IOnlineEvaluator, new() {
+    private List<T> evaluators;
+
+    public OnlineMultiVariateEvaluator() {
+
+      Reset();
+    }
+
+    #region IMultiVariateOnlineEvaluator Members
+    public double Value {
+      get { return evaluators.Sum(e => e.Value); }
+    }
+
+    public void Add(double[] original, double[] estimated) {
+      if (original.Length != estimated.Length) throw new ArgumentException("Number of elements of original and estimated doesn't match.");
+      if (evaluators == null) InitializeEvaluators(original.Length);
+      if (original.Length != evaluators.Count) throw new ArgumentException("Dimension doesn't match previous array dimensions.");
+      for (int i = 0; i < original.Length; i++) {
+        evaluators[i].Add(original[i], estimated[i]);
+      }
+    }
+
+    private void InitializeEvaluators(int count) {
+      evaluators = new List<T>();
+      for (int i = 0; i < count; i++) {
+        evaluators.Add(new T());
+      }
+    }
+
+    public void Reset() {
+      if (evaluators != null) {
+        foreach (var evaluator in evaluators)
+          evaluator.Reset();
+      }
+    }
+
+    #endregion
+  }
+}
Index: branches/DataAnalysis/HeuristicLab.Problems.DataAnalysis.MultiVariate/3.3/HeuristicLab.Problems.DataAnalysis.MultiVariate-3.3.csproj
===================================================================
--- branches/DataAnalysis/HeuristicLab.Problems.DataAnalysis.MultiVariate/3.3/HeuristicLab.Problems.DataAnalysis.MultiVariate-3.3.csproj	(revision 4464)
+++ branches/DataAnalysis/HeuristicLab.Problems.DataAnalysis.MultiVariate/3.3/HeuristicLab.Problems.DataAnalysis.MultiVariate-3.3.csproj	(revision 4475)
@@ -109,5 +109,8 @@
     <None Include="HeuristicLabProblemsDataAnalysisMultiVariatePlugin.cs.frame" />
     <None Include="Properties\AssemblyInfo.frame" />
+    <Compile Include="Evaluators\OnlineMultiVariateEvaluator.cs" />
+    <Compile Include="Evaluators\OnlineMeanMahalanobisDistanceEvaluator.cs" />
     <Compile Include="HeuristicLabProblemsDataAnalysisMultiVariatePlugin.cs" />
+    <Compile Include="Interfaces\IMultiVariateOnlineEvaluator.cs" />
     <Compile Include="Interfaces\IMultiVariateDataAnalysisEvaluator.cs" />
     <Compile Include="Interfaces\IMultiVariateDataAnalysisModel.cs" />
@@ -143,4 +146,12 @@
       <Project>{125D3006-67F5-48CB-913E-73C0548F17FA}</Project>
       <Name>HeuristicLab.Encodings.SymbolicExpressionTreeEncoding-3.3</Name>
+    </ProjectReference>
+    <ProjectReference Include="..\..\HeuristicLab.ExtLibs\HeuristicLab.ALGLIB\2.5.0\ALGLIB-2.5.0\ALGLIB-2.5.0.csproj">
+      <Project>{29E4B033-1FEF-4FE1-AE17-0A9319D7C54E}</Project>
+      <Name>ALGLIB-2.5.0</Name>
+    </ProjectReference>
+    <ProjectReference Include="..\..\HeuristicLab.ExtLibs\HeuristicLab.ALGLIB\2.5.0\HeuristicLab.ALGLIB-2.5.0\HeuristicLab.ALGLIB-2.5.0.csproj">
+      <Project>{01BBCB5A-144A-4A7E-908E-079849E2F7CF}</Project>
+      <Name>HeuristicLab.ALGLIB-2.5.0 %28HeuristicLab.ExtLibs\HeuristicLab.ALGLIB\HeuristicLab.ALGLIB-2.5.0\HeuristicLab.ALGLIB-2.5.0%29</Name>
     </ProjectReference>
     <ProjectReference Include="..\..\HeuristicLab.Operators\3.3\HeuristicLab.Operators-3.3.csproj">
Index: branches/DataAnalysis/HeuristicLab.Problems.DataAnalysis.MultiVariate/3.3/Interfaces/IMultiVariateOnlineEvaluator.cs
===================================================================
--- branches/DataAnalysis/HeuristicLab.Problems.DataAnalysis.MultiVariate/3.3/Interfaces/IMultiVariateOnlineEvaluator.cs	(revision 4475)
+++ branches/DataAnalysis/HeuristicLab.Problems.DataAnalysis.MultiVariate/3.3/Interfaces/IMultiVariateOnlineEvaluator.cs	(revision 4475)
@@ -0,0 +1,31 @@
+#region License Information
+/* HeuristicLab
+ * Copyright (C) 2002-2010 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.Core;
+using HeuristicLab.Optimization;
+
+namespace HeuristicLab.Problems.DataAnalysis.MultiVariate {
+  public interface IMultiVariateOnlineEvaluator {
+    double Value { get; }
+    void Reset();
+    void Add(double[] original, double[] estimated);
+  }
+}
Index: branches/DataAnalysis/HeuristicLab.Problems.DataAnalysis.Regression/3.3/Symbolic/Analyzers/BestSymbolicRegressionSolutionAnalyzer.cs
===================================================================
--- branches/DataAnalysis/HeuristicLab.Problems.DataAnalysis.Regression/3.3/Symbolic/Analyzers/BestSymbolicRegressionSolutionAnalyzer.cs	(revision 4464)
+++ branches/DataAnalysis/HeuristicLab.Problems.DataAnalysis.Regression/3.3/Symbolic/Analyzers/BestSymbolicRegressionSolutionAnalyzer.cs	(revision 4475)
@@ -92,5 +92,5 @@
         var model = new SymbolicRegressionModel((ISymbolicExpressionTreeInterpreter)SymbolicExpressionTreeInterpreter.Clone(),
           SymbolicExpressionTree[i]);
-        var solution = new SymbolicRegressionSolution(ProblemData, model, lowerEstimationLimit, upperEstimationLimit);
+        var solution = new SymbolicRegressionSolution((DataAnalysisProblemData)ProblemData.Clone(), model, lowerEstimationLimit, upperEstimationLimit);
         solution.Name = BestSolutionParameterName;
         solution.Description = "Best solution on validation partition found over the whole run.";
Index: branches/DataAnalysis/HeuristicLab.Problems.DataAnalysis.Regression/3.3/Symbolic/Analyzers/FixedValidationBestScaledSymbolicRegressionSolutionAnalyzer.cs
===================================================================
--- branches/DataAnalysis/HeuristicLab.Problems.DataAnalysis.Regression/3.3/Symbolic/Analyzers/FixedValidationBestScaledSymbolicRegressionSolutionAnalyzer.cs	(revision 4464)
+++ branches/DataAnalysis/HeuristicLab.Problems.DataAnalysis.Regression/3.3/Symbolic/Analyzers/FixedValidationBestScaledSymbolicRegressionSolutionAnalyzer.cs	(revision 4475)
@@ -321,5 +321,5 @@
       var scaledBestTrainingTree = GetScaledTree(bestTrainingTree);
 
-      SymbolicRegressionSolution bestTrainingSolution = new SymbolicRegressionSolution(ProblemData,
+      SymbolicRegressionSolution bestTrainingSolution = new SymbolicRegressionSolution((DataAnalysisProblemData)ProblemData.Clone(),
         new SymbolicRegressionModel(SymbolicExpressionTreeInterpreter, scaledBestTrainingTree),
         lowerEstimationLimit, upperEstimationLimit);
@@ -336,5 +336,5 @@
         var model = new SymbolicRegressionModel((ISymbolicExpressionTreeInterpreter)SymbolicExpressionTreeInterpreter.Clone(),
           scaledTree);
-        var solution = new SymbolicRegressionSolution(ProblemData, model, lowerEstimationLimit, upperEstimationLimit);
+        var solution = new SymbolicRegressionSolution((DataAnalysisProblemData)ProblemData.Clone(), model, lowerEstimationLimit, upperEstimationLimit);
         solution.Name = BestSolutionParameterName;
         solution.Description = "Best solution on validation partition found over the whole run.";
Index: branches/DataAnalysis/HeuristicLab.Problems.DataAnalysis.Views/3.3/RunCollectionMonteCarloVariableImpactView.cs
===================================================================
--- branches/DataAnalysis/HeuristicLab.Problems.DataAnalysis.Views/3.3/RunCollectionMonteCarloVariableImpactView.cs	(revision 4464)
+++ branches/DataAnalysis/HeuristicLab.Problems.DataAnalysis.Views/3.3/RunCollectionMonteCarloVariableImpactView.cs	(revision 4475)
@@ -38,5 +38,5 @@
   [View("RunCollection Monte-Carlo Variable Impact View")]
   public partial class RunCollectionMonteCarloVariableImpactView : AsynchronousContentView {
-    private const string validationBestModelResultName = "Best solution (on validiation set)";
+    private const string validationBestModelResultName = "Best solution (on validation set)";
     public RunCollectionMonteCarloVariableImpactView() {
       InitializeComponent();
Index: branches/DataAnalysis/HeuristicLab.Problems.DataAnalysis.Views/3.3/RunCollectionWinklerVariableImpactView.cs
===================================================================
--- branches/DataAnalysis/HeuristicLab.Problems.DataAnalysis.Views/3.3/RunCollectionWinklerVariableImpactView.cs	(revision 4464)
+++ branches/DataAnalysis/HeuristicLab.Problems.DataAnalysis.Views/3.3/RunCollectionWinklerVariableImpactView.cs	(revision 4475)
@@ -38,5 +38,5 @@
   [View("RunCollection Winkler Variable Impact View")]
   public partial class RunCollectionWinklerVariableImpactView : AsynchronousContentView {
-    private const string validationBestModelResultName = "Best solution (on validiation set)";
+    private const string validationBestModelResultName = "Best solution (on validation set)";
     public RunCollectionWinklerVariableImpactView() {
       InitializeComponent();
