Index: branches/Sliding Window GP/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/HeuristicLab.Problems.DataAnalysis.Symbolic-3.4.csproj
===================================================================
--- branches/Sliding Window GP/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/HeuristicLab.Problems.DataAnalysis.Symbolic-3.4.csproj	(revision 10402)
+++ branches/Sliding Window GP/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/HeuristicLab.Problems.DataAnalysis.Symbolic-3.4.csproj	(revision 10403)
@@ -206,4 +206,5 @@
     <Compile Include="Interfaces\ISymbolicDataAnalysisExpressionTreeInterpreter.cs" />
     <Compile Include="Interfaces\ISymbolicDataAnalysisProblem.cs" />
+    <Compile Include="SlidingWindow\SlidingWindowQualitiesAnalyzer.cs" />
     <Compile Include="SlidingWindow\SlidingWindowVisualizer.cs" />
     <Compile Include="SymbolicDataAnalysisExpressionPruningOperator.cs" />
Index: branches/Sliding Window GP/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/SlidingWindow/SlidingWindowQualitiesAnalyzer.cs
===================================================================
--- branches/Sliding Window GP/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/SlidingWindow/SlidingWindowQualitiesAnalyzer.cs	(revision 10403)
+++ branches/Sliding Window GP/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/SlidingWindow/SlidingWindowQualitiesAnalyzer.cs	(revision 10403)
@@ -0,0 +1,142 @@
+﻿#region License Information
+/* HeuristicLab
+ * Copyright (C) 2002-2013 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.Linq;
+using HeuristicLab.Analysis;
+using HeuristicLab.Common;
+using HeuristicLab.Core;
+using HeuristicLab.Data;
+using HeuristicLab.Optimization;
+using HeuristicLab.Parameters;
+using HeuristicLab.Persistence.Default.CompositeSerializers.Storable;
+
+namespace HeuristicLab.Problems.DataAnalysis.Symbolic.SlidingWindow {
+  [StorableClass]
+  [Item("Sliding Window Qualities Analyzer", "Analyzer that computes the qualities of the best solution on past, current, and future regions of the sliding window training data.")]
+  public sealed class SlidingWindowQualitiesAnalyzer : SymbolicDataAnalysisAnalyzer {
+    private const string SlidingWindowQualitiesResultName = "Sliding Window Qualities";
+    private const string ProblemDataParameterName = "ProblemData";
+    private const string EvaluatorParameterName = "Evaluator";
+    private const string FitnessCalculationPartitionParameterName = "FitnessCalculationPartition";
+    private const string ValidationPartitionParameterName = "ValidationPartition";
+    private const string SymbolicExpressionTreeInterpreterParameterName = "SymbolicExpressionTreeInterpreter";
+
+    public IValueLookupParameter<IDataAnalysisProblemData> ProblemDataParameter {
+      get { return (IValueLookupParameter<IDataAnalysisProblemData>)Parameters[ProblemDataParameterName]; }
+    }
+    public ILookupParameter<IntRange> FitnessCalculationPartitionParameter {
+      get { return (ILookupParameter<IntRange>)Parameters[FitnessCalculationPartitionParameterName]; }
+    }
+    public ILookupParameter<IntRange> ValidationPartitionParameter {
+      get { return (ILookupParameter<IntRange>)Parameters[ValidationPartitionParameterName]; }
+    }
+    public ILookupParameter<IEvaluator> EvaluatorParameter {
+      get { return (ILookupParameter<IEvaluator>)Parameters[EvaluatorParameterName]; }
+    }
+
+    public ILookupParameter<ISymbolicDataAnalysisExpressionTreeInterpreter> SymbolicExpressionTreeInterpreter {
+      get { return (ILookupParameter<ISymbolicDataAnalysisExpressionTreeInterpreter>)Parameters[SymbolicExpressionTreeInterpreterParameterName]; }
+    }
+
+    public override IDeepCloneable Clone(Cloner cloner) {
+      return new SlidingWindowQualitiesAnalyzer(this, cloner);
+    }
+    private SlidingWindowQualitiesAnalyzer(SlidingWindowQualitiesAnalyzer original, Cloner cloner)
+      : base(original, cloner) {
+    }
+
+
+
+    [StorableConstructor]
+    private SlidingWindowQualitiesAnalyzer(bool deserializing) : base(deserializing) { }
+
+    public SlidingWindowQualitiesAnalyzer() {
+      Parameters.Add(new ValueLookupParameter<IDataAnalysisProblemData>(ProblemDataParameterName, "The problem data on which the symbolic data analysis solution should be evaluated."));
+      Parameters.Add(new LookupParameter<IEvaluator>(EvaluatorParameterName, ""));
+      Parameters.Add(new LookupParameter<IntRange>(FitnessCalculationPartitionParameterName, ""));
+      Parameters.Add(new LookupParameter<ISymbolicDataAnalysisExpressionTreeInterpreter>(SymbolicExpressionTreeInterpreterParameterName, ""));
+
+      ProblemDataParameter.Hidden = true;
+    }
+
+    [StorableHook(HookType.AfterDeserialization)]
+    private void AfterDeserialization() {
+    }
+
+    public override IOperation Apply() {
+      if (FitnessCalculationPartitionParameter.ActualValue == null)
+        // do nothing because the sliding window hasn't been initialized yet
+        return base.Apply();
+
+
+      var results = ResultCollectionParameter.ActualValue;
+      if (!results.ContainsKey("Best training solution")) return base.Apply();
+
+      var problemData = (IRegressionProblemData)ProblemDataParameter.ActualValue;
+      var evaluator = (SymbolicDataAnalysisSingleObjectiveEvaluator<IRegressionProblemData>)EvaluatorParameter.ActualValue;
+      var context = new Core.ExecutionContext(ExecutionContext, evaluator, new Scope());
+      var fitnessCalculationPartition = FitnessCalculationPartitionParameter.ActualValue;
+
+      var bestSolution = (ISymbolicDataAnalysisSolution)results["Best training solution"].Value;
+      var bestModel = bestSolution.Model;
+      var bestTree = bestModel.SymbolicExpressionTree;
+      // add result
+      if (!results.ContainsKey(SlidingWindowQualitiesResultName)) {
+        results.Add(new Result(SlidingWindowQualitiesResultName, new DataTable(SlidingWindowQualitiesResultName)));
+      }
+      var swQualitiesTable = (DataTable)results[SlidingWindowQualitiesResultName].Value;
+
+      // compute before quality
+      var beforeQuality = 0.0;
+      if (!swQualitiesTable.Rows.ContainsKey("Before Quality"))
+        swQualitiesTable.Rows.Add(new DataRow("Before Quality") { VisualProperties = { StartIndexZero = true } });
+      if (fitnessCalculationPartition.Start > problemData.TrainingPartition.Start) {
+        var beforeRange = new IntRange(problemData.TrainingPartition.Start, fitnessCalculationPartition.Start);
+        beforeQuality = evaluator.Evaluate(context, bestTree, problemData, Enumerable.Range(beforeRange.Start, beforeRange.Size));
+      }
+      swQualitiesTable.Rows["Before Quality"].Values.Add(beforeQuality);
+
+      // compute current quality
+      var currentQuality = ((DoubleValue)results["CurrentBestQuality"].Value).Value;
+      if (!swQualitiesTable.Rows.ContainsKey("Current Quality"))
+        swQualitiesTable.Rows.Add(new DataRow("Current Quality") { VisualProperties = { StartIndexZero = true } });
+      swQualitiesTable.Rows["Current Quality"].Values.Add(currentQuality);
+
+      // compute after quality
+      if (fitnessCalculationPartition.End < problemData.TrainingPartition.End) {
+        var afterRange = new IntRange(fitnessCalculationPartition.End, problemData.TrainingPartition.End);
+        var afterQuality = evaluator.Evaluate(context, bestTree, problemData,
+          Enumerable.Range(afterRange.Start, afterRange.Size));
+        if (!swQualitiesTable.Rows.ContainsKey("After Quality"))
+          swQualitiesTable.Rows.Add(new DataRow("After Quality") { VisualProperties = { StartIndexZero = true } });
+        swQualitiesTable.Rows["After Quality"].Values.Add(afterQuality);
+      }
+      // compute test quality
+      if (!swQualitiesTable.Rows.ContainsKey("Test Quality"))
+        swQualitiesTable.Rows.Add(new DataRow("Test Quality") { VisualProperties = { StartIndexZero = true } });
+      var regressionSolution = (IRegressionSolution)bestSolution;
+      swQualitiesTable.Rows["Test Quality"].Values.Add(regressionSolution.TestRSquared);
+      return base.Apply();
+    }
+
+    public override bool EnabledByDefault { get { return false; } }
+  }
+}
