Index: /branches/HeuristicLab.TimeSeries/HeuristicLab.Problems.DataAnalysis.Symbolic.TimeSeriesPrognosis/3.4/Interfaces/ISymbolicTimeSeriesPrognogisExpressionTreeInterpreter.cs
===================================================================
--- /branches/HeuristicLab.TimeSeries/HeuristicLab.Problems.DataAnalysis.Symbolic.TimeSeriesPrognosis/3.4/Interfaces/ISymbolicTimeSeriesPrognogisExpressionTreeInterpreter.cs	(revision 8009)
+++ /branches/HeuristicLab.TimeSeries/HeuristicLab.Problems.DataAnalysis.Symbolic.TimeSeriesPrognosis/3.4/Interfaces/ISymbolicTimeSeriesPrognogisExpressionTreeInterpreter.cs	(revision 8010)
@@ -27,4 +27,5 @@
     string TargetVariable { get; set; }
     IEnumerable<IEnumerable<double>> GetSymbolicExpressionTreeValues(ISymbolicExpressionTree tree, Dataset dataset, IEnumerable<int> rows, int horizon);
+    IEnumerable<IEnumerable<double>> GetSymbolicExpressionTreeValues(ISymbolicExpressionTree tree, Dataset dataset, IEnumerable<int> rows, IEnumerable<int> horizon);
   }
 }
Index: /branches/HeuristicLab.TimeSeries/HeuristicLab.Problems.DataAnalysis.Symbolic.TimeSeriesPrognosis/3.4/SingleObjective/SymbolicTimeSeriesPrognosisSingleObjectiveMeanSquaredErrorEvaluator.cs
===================================================================
--- /branches/HeuristicLab.TimeSeries/HeuristicLab.Problems.DataAnalysis.Symbolic.TimeSeriesPrognosis/3.4/SingleObjective/SymbolicTimeSeriesPrognosisSingleObjectiveMeanSquaredErrorEvaluator.cs	(revision 8009)
+++ /branches/HeuristicLab.TimeSeries/HeuristicLab.Problems.DataAnalysis.Symbolic.TimeSeriesPrognosis/3.4/SingleObjective/SymbolicTimeSeriesPrognosisSingleObjectiveMeanSquaredErrorEvaluator.cs	(revision 8010)
@@ -54,6 +54,6 @@
       double quality = Calculate(interpreter, solution,
         EstimationLimitsParameter.ActualValue.Lower, EstimationLimitsParameter.ActualValue.Upper,
-        ProblemDataParameter.ActualValue,
-        rows, HorizonParameter.ActualValue.Value, ApplyLinearScaling);
+        ProblemDataParameter.ActualValue, rows, EvaluationPartitionParameter.ActualValue,
+        HorizonParameter.ActualValue.Value, ApplyLinearScaling);
       QualityParameter.ActualValue = new DoubleValue(quality);
 
@@ -61,8 +61,8 @@
     }
 
-    public static double Calculate(ISymbolicTimeSeriesPrognosisExpressionTreeInterpreter interpreter, ISymbolicExpressionTree solution, double lowerEstimationLimit, double upperEstimationLimit, ITimeSeriesPrognosisProblemData problemData, IEnumerable<int> rows, int horizon, bool applyLinearScaling) {
-      int horizion2 = problemData.TrainingPartition.End - problemData.TrainingPartition.Start;
-      IEnumerable<double> targetValues = problemData.Dataset.GetDoubleValues(problemData.TargetVariable, rows.Take(1).Select(r => Enumerable.Range(r, horizion2)).First());
-      IEnumerable<double> estimatedValues = interpreter.GetSymbolicExpressionTreeValues(solution, problemData.Dataset, rows.Take(1), horizion2).SelectMany(x => x);
+    public static double Calculate(ISymbolicTimeSeriesPrognosisExpressionTreeInterpreter interpreter, ISymbolicExpressionTree solution, double lowerEstimationLimit, double upperEstimationLimit, ITimeSeriesPrognosisProblemData problemData, IEnumerable<int> rows, IntRange evaluationPartition, int horizon, bool applyLinearScaling) {
+      var horizions = rows.Select(r => Math.Min(horizon, evaluationPartition.End - r));
+      IEnumerable<double> targetValues = problemData.Dataset.GetDoubleValues(problemData.TargetVariable, rows.Zip(horizions, Enumerable.Range).SelectMany(r => r));
+      IEnumerable<double> estimatedValues = interpreter.GetSymbolicExpressionTreeValues(solution, problemData.Dataset, rows, horizions).SelectMany(x => x);
       IEnumerable<double> boundedEstimatedValues = estimatedValues.LimitToRange(lowerEstimationLimit, upperEstimationLimit);
       OnlineCalculatorError errorState;
@@ -71,5 +71,5 @@
       if (applyLinearScaling) {
         var mseCalculator = new OnlineMeanSquaredErrorCalculator();
-        CalculateWithScaling(targetValues, boundedEstimatedValues, mseCalculator, problemData.Dataset.Rows);
+        CalculateWithScaling(targetValues, boundedEstimatedValues, mseCalculator, problemData.Dataset.Rows * horizon);
         errorState = mseCalculator.ErrorState;
         mse = mseCalculator.MeanSquaredError;
@@ -79,4 +79,5 @@
       if (errorState != OnlineCalculatorError.None) return Double.NaN;
       else return mse;
+
     }
 
@@ -86,10 +87,12 @@
       EstimationLimitsParameter.ExecutionContext = context;
       HorizonParameter.ExecutionContext = context;
+      EvaluationPartitionParameter.ExecutionContext = context;
 
-      double mse = Calculate(SymbolicDataAnalysisTreeInterpreterParameter.ActualValue as ISymbolicTimeSeriesPrognosisExpressionTreeInterpreter, tree, EstimationLimitsParameter.ActualValue.Lower, EstimationLimitsParameter.ActualValue.Upper, problemData, rows, HorizonParameter.ActualValue.Value, ApplyLinearScaling);
+      double mse = Calculate((ISymbolicTimeSeriesPrognosisExpressionTreeInterpreter)SymbolicDataAnalysisTreeInterpreterParameter.ActualValue, tree, EstimationLimitsParameter.ActualValue.Lower, EstimationLimitsParameter.ActualValue.Upper, problemData, rows, EvaluationPartitionParameter.ActualValue, HorizonParameter.ActualValue.Value, ApplyLinearScaling);
 
       HorizonParameter.ExecutionContext = null;
       SymbolicDataAnalysisTreeInterpreterParameter.ExecutionContext = null;
       EstimationLimitsParameter.ExecutionContext = null;
+      EvaluationPartitionParameter.ExecutionContext = null;
 
       return mse;
Index: /branches/HeuristicLab.TimeSeries/HeuristicLab.Problems.DataAnalysis.Symbolic.TimeSeriesPrognosis/3.4/SymbolicTimeSeriesPrognosisModel.cs
===================================================================
--- /branches/HeuristicLab.TimeSeries/HeuristicLab.Problems.DataAnalysis.Symbolic.TimeSeriesPrognosis/3.4/SymbolicTimeSeriesPrognosisModel.cs	(revision 8009)
+++ /branches/HeuristicLab.TimeSeries/HeuristicLab.Problems.DataAnalysis.Symbolic.TimeSeriesPrognosis/3.4/SymbolicTimeSeriesPrognosisModel.cs	(revision 8010)
@@ -86,6 +86,6 @@
     }
 
-    public IEnumerable<IEnumerable<double>> GetPrognosedValues(Dataset dataset, IEnumerable<int> rows, int horizon) {
-      var estimatedValues = Interpreter.GetSymbolicExpressionTreeValues(SymbolicExpressionTree, dataset, rows, horizon);
+    public IEnumerable<IEnumerable<double>> GetPrognosedValues(Dataset dataset, IEnumerable<int> rows, IEnumerable<int> horizons) {
+      var estimatedValues = Interpreter.GetSymbolicExpressionTreeValues(SymbolicExpressionTree, dataset, rows, horizons);
       return estimatedValues.Select(predictionPerRow => predictionPerRow.LimitToRange(lowerEstimationLimit, upperEstimationLimit));
     }
Index: /branches/HeuristicLab.TimeSeries/HeuristicLab.Problems.DataAnalysis.Symbolic.TimeSeriesPrognosis/3.4/SymbolicTimeSeriesPrognosisSolution.cs
===================================================================
--- /branches/HeuristicLab.TimeSeries/HeuristicLab.Problems.DataAnalysis.Symbolic.TimeSeriesPrognosis/3.4/SymbolicTimeSeriesPrognosisSolution.cs	(revision 8009)
+++ /branches/HeuristicLab.TimeSeries/HeuristicLab.Problems.DataAnalysis.Symbolic.TimeSeriesPrognosis/3.4/SymbolicTimeSeriesPrognosisSolution.cs	(revision 8010)
@@ -25,4 +25,5 @@
 using HeuristicLab.Optimization;
 using HeuristicLab.Persistence.Default.CompositeSerializers.Storable;
+using HeuristicLab.Encodings.SymbolicExpressionTreeEncoding;
 
 namespace HeuristicLab.Problems.DataAnalysis.Symbolic.TimeSeriesPrognosis {
Index: /branches/HeuristicLab.TimeSeries/HeuristicLab.Problems.DataAnalysis.Views/3.4/Solution Views/TimeSeriesPrognosisSolutionView.Designer.cs
===================================================================
--- /branches/HeuristicLab.TimeSeries/HeuristicLab.Problems.DataAnalysis.Views/3.4/Solution Views/TimeSeriesPrognosisSolutionView.Designer.cs	(revision 8009)
+++ /branches/HeuristicLab.TimeSeries/HeuristicLab.Problems.DataAnalysis.Views/3.4/Solution Views/TimeSeriesPrognosisSolutionView.Designer.cs	(revision 8010)
@@ -99,5 +99,4 @@
       this.horizonTextBox.Size = new System.Drawing.Size(100, 20);
       this.horizonTextBox.TabIndex = 1;
-      this.horizonTextBox.KeyDown += new System.Windows.Forms.KeyEventHandler(this.horizonTextBox_KeyDown);
       this.horizonTextBox.Validating += new System.ComponentModel.CancelEventHandler(this.horizonTextBox_Validating);
       this.horizonTextBox.Validated += new System.EventHandler(this.horizonTextBox_Validated);
Index: /branches/HeuristicLab.TimeSeries/HeuristicLab.Problems.DataAnalysis.Views/3.4/Solution Views/TimeSeriesPrognosisSolutionView.cs
===================================================================
--- /branches/HeuristicLab.TimeSeries/HeuristicLab.Problems.DataAnalysis.Views/3.4/Solution Views/TimeSeriesPrognosisSolutionView.cs	(revision 8009)
+++ /branches/HeuristicLab.TimeSeries/HeuristicLab.Problems.DataAnalysis.Views/3.4/Solution Views/TimeSeriesPrognosisSolutionView.cs	(revision 8010)
@@ -61,5 +61,5 @@
       int val;
       if (int.TryParse(horizonTextBox.Text, out val)) {
-        e.Cancel = val <= 0 || val >= Content.ProblemData.TrainingPartition.End - Content.ProblemData.TrainingPartition.Start;
+        //e.Cancel = val <= 0 || val >= Content.ProblemData.TrainingPartition.End - Content.ProblemData.TrainingPartition.Start;
       } else {
         e.Cancel = true;
@@ -72,14 +72,4 @@
       Content.Horizon = val;
     }
-
-    private void horizonTextBox_KeyDown(object sender, KeyEventArgs e) {
-      if (e.KeyCode == Keys.Enter) {
-        e.Handled = true;
-        this.Focus();
-      } else {
-        e.Handled = false;
-      }
-    }
-
   }
 }
Index: /branches/HeuristicLab.TimeSeries/HeuristicLab.Problems.DataAnalysis.Views/3.4/TimeSeriesPrognosis/TimeSeriesPrognosisSolutionLineChartView.cs
===================================================================
--- /branches/HeuristicLab.TimeSeries/HeuristicLab.Problems.DataAnalysis.Views/3.4/TimeSeriesPrognosis/TimeSeriesPrognosisSolutionLineChartView.cs	(revision 8009)
+++ /branches/HeuristicLab.TimeSeries/HeuristicLab.Problems.DataAnalysis.Views/3.4/TimeSeriesPrognosis/TimeSeriesPrognosisSolutionLineChartView.cs	(revision 8010)
@@ -25,4 +25,5 @@
 using System.Windows.Forms;
 using System.Windows.Forms.DataVisualization.Charting;
+using HeuristicLab.Common;
 using HeuristicLab.MainForm;
 using HeuristicLab.MainForm.WindowsForms;
@@ -77,9 +78,9 @@
           this.chart.Series[PROGNOSEDVALUES_TRAINING_SERIES_NAME].Points
             .DataBindXY(Content.ProblemData.TrainingIndizes.ToArray(),
-                        Content.GetPrognosedValues(Content.ProblemData.TrainingIndizes.Take(1), Content.ProblemData.TrainingPartition.Size).SelectMany(x => x).ToArray());
+                        Content.GetPrognosedValues(Content.ProblemData.TrainingIndizes.Take(1), Content.ProblemData.TrainingIndizes.Count().ToEnumerable()).First().ToArray());
         } else {
           this.chart.Series[PROGNOSEDVALUES_TRAINING_SERIES_NAME].Points
             .DataBindXY(Content.ProblemData.TrainingIndizes.ToArray(),
-                        Content.GetPrognosedValues(Content.ProblemData.TrainingIndizes, 1).SelectMany(x => x).ToArray());
+                        Content.GetPrognosedValues(Content.ProblemData.TrainingIndizes, Enumerable.Repeat(1, Content.ProblemData.TrainingIndizes.Count())).SelectMany(x => x).ToArray());
         }
         this.chart.Series[PROGNOSEDVALUES_TRAINING_SERIES_NAME].Tag = Content;
@@ -95,9 +96,9 @@
           this.chart.Series[PROGNOSEDVALUES_TEST_SERIES_NAME].Points
             .DataBindXY(Content.ProblemData.TestIndizes.ToArray(),
-                        Content.GetPrognosedValues(Content.ProblemData.TestIndizes.Take(1), Content.ProblemData.TestPartition.Size).SelectMany(x => x).ToArray());
+                        Content.GetPrognosedValues(Content.ProblemData.TestIndizes.Take(1), Content.ProblemData.TestIndizes.Count().ToEnumerable()).First().ToArray());
         } else {
           this.chart.Series[PROGNOSEDVALUES_TEST_SERIES_NAME].Points
             .DataBindXY(Content.ProblemData.TestIndizes.ToArray(),
-                        Content.GetPrognosedValues(Content.ProblemData.TestIndizes, 1).SelectMany(x => x).ToArray());
+                       Content.GetPrognosedValues(Content.ProblemData.TestIndizes, Enumerable.Repeat(1, Content.ProblemData.TestIndizes.Count())).SelectMany(x => x).ToArray());
         }
         this.chart.Series[PROGNOSEDVALUES_TEST_SERIES_NAME].Tag = Content;
@@ -220,10 +221,10 @@
           case PROGNOSEDVALUES_TRAINING_SERIES_NAME:
             indizes = Content.ProblemData.TrainingIndizes.ToArray();
-            predictedValues = Content.GetPrognosedValues(Content.ProblemData.TrainingIndizes.Take(1), Content.ProblemData.TrainingPartition.Size).First();
+            predictedValues = Content.GetPrognosedValues(Content.ProblemData.TrainingIndizes.Take(1), Content.ProblemData.TrainingPartition.Size.ToEnumerable()).First();
             break;
           case PROGNOSEDVALUES_TEST_SERIES_NAME:
             testPrognosisStart = Content.ProblemData.TestPartition.Start;
             indizes = Content.ProblemData.TestIndizes.ToArray();
-            predictedValues = Content.GetPrognosedValues(Content.ProblemData.TestIndizes.Take(1), Content.ProblemData.TestPartition.Size).First();
+            predictedValues = Content.GetPrognosedValues(Content.ProblemData.TestIndizes.Take(1), Content.ProblemData.TestPartition.Size.ToEnumerable()).First();
             break;
         }
Index: /branches/HeuristicLab.TimeSeries/HeuristicLab.Problems.DataAnalysis.Views/3.4/TimeSeriesPrognosis/TimeSeriesPrognosisSolutionPrognosedValuesView.cs
===================================================================
--- /branches/HeuristicLab.TimeSeries/HeuristicLab.Problems.DataAnalysis.Views/3.4/TimeSeriesPrognosis/TimeSeriesPrognosisSolutionPrognosedValuesView.cs	(revision 8009)
+++ /branches/HeuristicLab.TimeSeries/HeuristicLab.Problems.DataAnalysis.Views/3.4/TimeSeriesPrognosis/TimeSeriesPrognosisSolutionPrognosedValuesView.cs	(revision 8010)
@@ -23,4 +23,5 @@
 using System.Linq;
 using System.Windows.Forms;
+using HeuristicLab.Common;
 using HeuristicLab.Data;
 using HeuristicLab.Data.Views;
@@ -94,6 +95,6 @@
 
       string[,] values = new string[Content.ProblemData.Dataset.Rows, 4];
-      var prognosedTraining = Content.GetPrognosedValues(Content.ProblemData.TrainingIndizes.Take(1), Content.ProblemData.TrainingPartition.Size).First();
-      var prognosedTest = Content.GetPrognosedValues(Content.ProblemData.TrainingIndizes.Take(1), Content.ProblemData.TestPartition.Size).First();
+      var prognosedTraining = Content.GetPrognosedValues(Content.ProblemData.TrainingIndizes.Take(1), Content.ProblemData.TrainingPartition.Size.ToEnumerable()).First();
+      var prognosedTest = Content.GetPrognosedValues(Content.ProblemData.TestIndizes.Take(1), Content.ProblemData.TestPartition.Size.ToEnumerable()).First();
       double[] target = Content.ProblemData.Dataset.GetDoubleValues(targetVariable).ToArray();
 
Index: /branches/HeuristicLab.TimeSeries/HeuristicLab.Problems.DataAnalysis/3.4/HeuristicLab.Problems.DataAnalysis-3.4.csproj
===================================================================
--- /branches/HeuristicLab.TimeSeries/HeuristicLab.Problems.DataAnalysis/3.4/HeuristicLab.Problems.DataAnalysis-3.4.csproj	(revision 8009)
+++ /branches/HeuristicLab.TimeSeries/HeuristicLab.Problems.DataAnalysis/3.4/HeuristicLab.Problems.DataAnalysis-3.4.csproj	(revision 8010)
@@ -140,4 +140,7 @@
     </Compile>
     <Compile Include="Implementation\Regression\RegressionEnsembleSolution.cs" />
+    <Compile Include="Implementation\TimeSeriesPrognosis\Models\TimeSeriesPrognosisConstantModel.cs" />
+    <Compile Include="Implementation\TimeSeriesPrognosis\Models\TimeSeriesPrognosisMovingAverageModel.cs" />
+    <Compile Include="Implementation\TimeSeriesPrognosis\Models\TimeSeriesPrognosisAutoRegressiveModel.cs" />
     <Compile Include="Implementation\TimeSeriesPrognosis\TimeSeriesPrognosisProblem.cs" />
     <Compile Include="Implementation\TimeSeriesPrognosis\TimeSeriesPrognosisProblemData.cs" />
Index: /branches/HeuristicLab.TimeSeries/HeuristicLab.Problems.DataAnalysis/3.4/Implementation/TimeSeriesPrognosis/Models/TimeSeriesPrognosisAutoRegressiveModel.cs
===================================================================
--- /branches/HeuristicLab.TimeSeries/HeuristicLab.Problems.DataAnalysis/3.4/Implementation/TimeSeriesPrognosis/Models/TimeSeriesPrognosisAutoRegressiveModel.cs	(revision 8010)
+++ /branches/HeuristicLab.TimeSeries/HeuristicLab.Problems.DataAnalysis/3.4/Implementation/TimeSeriesPrognosis/Models/TimeSeriesPrognosisAutoRegressiveModel.cs	(revision 8010)
@@ -0,0 +1,90 @@
+﻿#region License Information
+/* HeuristicLab
+ * Copyright (C) 2002-2012 Heuristic and Evolutionary Algorithms Laboratory (HEAL)
+ *
+ * This file is part of HeuristicLab.
+ *
+ * HeuristicLab is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * HeuristicLab is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with HeuristicLab. If not, see <http://www.gnu.org/licenses/>.
+ */
+#endregion
+
+using System;
+using System.Collections.Generic;
+using HeuristicLab.Common;
+using HeuristicLab.Core;
+using HeuristicLab.Persistence.Default.CompositeSerializers.Storable;
+
+namespace HeuristicLab.Problems.DataAnalysis {
+  [StorableClass]
+  [Item("Autoregressive TimeSeries Model", "A linear autoregressive time series model used to predict future values.")]
+  public class TimeSeriesPrognosisAutoRegressiveModel : NamedItem, ITimeSeriesPrognosisModel {
+    //Currently it is only possible to calculate AR(1)
+    //The paramater calculation for AR(p) is described in http://en.wikipedia.org/wiki/Autoregressive_model and should be inserted in the future
+
+    [Storable]
+    public double Alpha { get; private set; }
+    [Storable]
+    public double Beta { get; private set; }
+    [Storable]
+    public string TargetVariable { get; private set; }
+    [Storable]
+    public int TimeOffset { get; private set; }
+
+    [StorableConstructor]
+    protected TimeSeriesPrognosisAutoRegressiveModel(bool deserializing) : base(deserializing) { }
+    protected TimeSeriesPrognosisAutoRegressiveModel(TimeSeriesPrognosisAutoRegressiveModel original, Cloner cloner)
+      : base(original, cloner) {
+      this.Alpha = original.Alpha;
+      this.Beta = original.Beta;
+      this.TargetVariable = original.TargetVariable;
+      this.TimeOffset = original.TimeOffset;
+    }
+    public override IDeepCloneable Clone(Cloner cloner) {
+      return new TimeSeriesPrognosisAutoRegressiveModel(this, cloner);
+    }
+    public TimeSeriesPrognosisAutoRegressiveModel(double alpha, double beta, string targetVariable)
+      : base() {
+      Alpha = alpha;
+      Beta = beta;
+      TargetVariable = targetVariable;
+      TimeOffset = -1;
+    }
+
+    public IEnumerable<IEnumerable<double>> GetPrognosedValues(Dataset dataset, IEnumerable<int> rows, IEnumerable<int> horizons) {
+      var rowsEnumerator = rows.GetEnumerator();
+      var horizonsEnumerator = horizons.GetEnumerator();
+      // produce a n-step forecast for all rows
+      while (rowsEnumerator.MoveNext() & horizonsEnumerator.MoveNext()) {
+        int row = rowsEnumerator.Current;
+        int horizon = horizonsEnumerator.Current;
+        double[] prognosis = new double[horizon];
+
+        if (row == 0) continue;
+        prognosis[0] = dataset.GetDoubleValue(TargetVariable, row + TimeOffset);
+        for (int i = 1; i < horizon; i++) {
+          prognosis[i] = Beta * prognosis[i - 1] + Alpha;
+        }
+        yield return prognosis;
+      }
+
+      if (rowsEnumerator.MoveNext() || horizonsEnumerator.MoveNext())
+        throw new ArgumentException("Number of elements in rows and horizon enumerations doesn't match.");
+    }
+
+    public ITimeSeriesPrognosisSolution CreateTimeSeriesPrognosisSolution(ITimeSeriesPrognosisProblemData problemData) {
+      return new TimeSeriesPrognosisSolution(this, problemData);
+    }
+
+  }
+}
Index: /branches/HeuristicLab.TimeSeries/HeuristicLab.Problems.DataAnalysis/3.4/Implementation/TimeSeriesPrognosis/Models/TimeSeriesPrognosisConstantModel.cs
===================================================================
--- /branches/HeuristicLab.TimeSeries/HeuristicLab.Problems.DataAnalysis/3.4/Implementation/TimeSeriesPrognosis/Models/TimeSeriesPrognosisConstantModel.cs	(revision 8010)
+++ /branches/HeuristicLab.TimeSeries/HeuristicLab.Problems.DataAnalysis/3.4/Implementation/TimeSeriesPrognosis/Models/TimeSeriesPrognosisConstantModel.cs	(revision 8010)
@@ -0,0 +1,57 @@
+﻿#region License Information
+/* HeuristicLab
+ * Copyright (C) 2002-2012 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.Collections.Generic;
+using System.Linq;
+using HeuristicLab.Common;
+using HeuristicLab.Core;
+using HeuristicLab.Persistence.Default.CompositeSerializers.Storable;
+
+namespace HeuristicLab.Problems.DataAnalysis {
+  [StorableClass]
+  [Item("Constant TimeSeries Model", "A time series model that returns for all prediciton the same constant value.")]
+  public class TimeSeriesPrognosisConstantModel : NamedItem, ITimeSeriesPrognosisModel {
+    [Storable]
+    public double Constant { get; private set; }
+
+    [StorableConstructor]
+    protected TimeSeriesPrognosisConstantModel(bool deserializing) : base(deserializing) { }
+    protected TimeSeriesPrognosisConstantModel(TimeSeriesPrognosisConstantModel original, Cloner cloner)
+      : base(original, cloner) {
+      Constant = original.Constant;
+    }
+    public override IDeepCloneable Clone(Cloner cloner) {
+      return new TimeSeriesPrognosisConstantModel(this, cloner);
+    }
+
+    public TimeSeriesPrognosisConstantModel(double constant) {
+      Constant = constant;
+    }
+
+    public IEnumerable<IEnumerable<double>> GetPrognosedValues(Dataset dataset, IEnumerable<int> rows, IEnumerable<int> horizons) {
+      return horizons.Select(horizon => Enumerable.Repeat(Constant, horizon));
+    }
+
+    public ITimeSeriesPrognosisSolution CreateTimeSeriesPrognosisSolution(ITimeSeriesPrognosisProblemData problemData) {
+      return new TimeSeriesPrognosisSolution(this, problemData);
+    }
+  }
+}
Index: /branches/HeuristicLab.TimeSeries/HeuristicLab.Problems.DataAnalysis/3.4/Implementation/TimeSeriesPrognosis/Models/TimeSeriesPrognosisMovingAverageModel.cs
===================================================================
--- /branches/HeuristicLab.TimeSeries/HeuristicLab.Problems.DataAnalysis/3.4/Implementation/TimeSeriesPrognosis/Models/TimeSeriesPrognosisMovingAverageModel.cs	(revision 8010)
+++ /branches/HeuristicLab.TimeSeries/HeuristicLab.Problems.DataAnalysis/3.4/Implementation/TimeSeriesPrognosis/Models/TimeSeriesPrognosisMovingAverageModel.cs	(revision 8010)
@@ -0,0 +1,87 @@
+﻿#region License Information
+/* HeuristicLab
+ * Copyright (C) 2002-2012 Heuristic and Evolutionary Algorithms Laboratory (HEAL)
+ *
+ * This file is part of HeuristicLab.
+ *
+ * HeuristicLab is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * HeuristicLab is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with HeuristicLab. If not, see <http://www.gnu.org/licenses/>.
+ */
+#endregion
+
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using HeuristicLab.Common;
+using HeuristicLab.Core;
+using HeuristicLab.Persistence.Default.CompositeSerializers.Storable;
+
+namespace HeuristicLab.Problems.DataAnalysis {
+  [StorableClass]
+  [Item("Moveing Average TimeSeries Model", "A moving average time series model used to predict future values.")]
+  public class TimeSeriesPrognosisMovingAverageModel : NamedItem, ITimeSeriesPrognosisModel {
+    [Storable]
+    public string TargetVariable { get; private set; }
+    [Storable]
+    public int WindowSize { get; private set; }
+
+    [StorableConstructor]
+    protected TimeSeriesPrognosisMovingAverageModel(bool deserializing) : base(deserializing) { }
+    protected TimeSeriesPrognosisMovingAverageModel(TimeSeriesPrognosisMovingAverageModel original, Cloner cloner)
+      : base(original, cloner) {
+      this.TargetVariable = original.TargetVariable;
+      this.WindowSize = original.WindowSize;
+    }
+    public override IDeepCloneable Clone(Cloner cloner) {
+      return new TimeSeriesPrognosisMovingAverageModel(this, cloner);
+    }
+    public TimeSeriesPrognosisMovingAverageModel(int windowSize, string targetVariable)
+      : base() {
+      TargetVariable = targetVariable;
+      WindowSize = Math.Abs(windowSize);
+    }
+
+    public IEnumerable<IEnumerable<double>> GetPrognosedValues(Dataset dataset, IEnumerable<int> rows, IEnumerable<int> horizons) {
+      var rowsEnumerator = rows.GetEnumerator();
+      var horizonsEnumerator = horizons.GetEnumerator();
+      // produce a n-step forecast for all rows
+      while (rowsEnumerator.MoveNext() & horizonsEnumerator.MoveNext()) {
+        int row = rowsEnumerator.Current;
+        int horizon = horizonsEnumerator.Current;
+        int startIndex = row - WindowSize;
+
+        if (row == 0) continue;
+        if (startIndex < 0) startIndex = 0;
+        int count = row - startIndex - 1;
+
+        List<double> targetValues = dataset.GetDoubleValues(TargetVariable, Enumerable.Range(startIndex, count)).ToList();
+        int position = 0;
+        for (int i = 0; i < horizon; i++) {
+          double prognosis = targetValues.GetRange(position, count).Average();
+          targetValues.Add(prognosis);
+          if (count < WindowSize) count++;
+          else position++;
+        }
+        yield return targetValues.GetRange(targetValues.Count - horizon, horizon);
+      }
+
+      if (rowsEnumerator.MoveNext() || horizonsEnumerator.MoveNext())
+        throw new ArgumentException("Number of elements in rows and horizon enumerations doesn't match.");
+    }
+
+    public ITimeSeriesPrognosisSolution CreateTimeSeriesPrognosisSolution(ITimeSeriesPrognosisProblemData problemData) {
+      return new TimeSeriesPrognosisSolution(this, problemData);
+    }
+
+  }
+}
Index: /branches/HeuristicLab.TimeSeries/HeuristicLab.Problems.DataAnalysis/3.4/Implementation/TimeSeriesPrognosis/TimeSeriesPrognosisSolution.cs
===================================================================
--- /branches/HeuristicLab.TimeSeries/HeuristicLab.Problems.DataAnalysis/3.4/Implementation/TimeSeriesPrognosis/TimeSeriesPrognosisSolution.cs	(revision 8009)
+++ /branches/HeuristicLab.TimeSeries/HeuristicLab.Problems.DataAnalysis/3.4/Implementation/TimeSeriesPrognosis/TimeSeriesPrognosisSolution.cs	(revision 8010)
@@ -29,10 +29,9 @@
   /// </summary>
   [StorableClass]
-  public abstract class TimeSeriesPrognosisSolution : TimeSeriesPrognosisSolutionBase {
-
+  public class TimeSeriesPrognosisSolution : TimeSeriesPrognosisSolutionBase {
     [StorableConstructor]
     protected TimeSeriesPrognosisSolution(bool deserializing) : base(deserializing) { }
     protected TimeSeriesPrognosisSolution(TimeSeriesPrognosisSolution original, Cloner cloner) : base(original, cloner) { }
-    protected TimeSeriesPrognosisSolution(ITimeSeriesPrognosisModel model, ITimeSeriesPrognosisProblemData problemData) : base(model, problemData) { }
+    protected internal TimeSeriesPrognosisSolution(ITimeSeriesPrognosisModel model, ITimeSeriesPrognosisProblemData problemData) : base(model, problemData) { }
 
     protected override void RecalculateResults() {
@@ -40,6 +39,6 @@
     }
 
-    public override IEnumerable<IEnumerable<double>> GetPrognosedValues(IEnumerable<int> rows, int horizon) {
-      return Model.GetPrognosedValues(ProblemData.Dataset, rows, horizon);
+    public override IEnumerable<IEnumerable<double>> GetPrognosedValues(IEnumerable<int> rows, IEnumerable<int> horizons) {
+      return Model.GetPrognosedValues(ProblemData.Dataset, rows, horizons);
     }
   }
Index: /branches/HeuristicLab.TimeSeries/HeuristicLab.Problems.DataAnalysis/3.4/Implementation/TimeSeriesPrognosis/TimeSeriesPrognosisSolutionBase.cs
===================================================================
--- /branches/HeuristicLab.TimeSeries/HeuristicLab.Problems.DataAnalysis/3.4/Implementation/TimeSeriesPrognosis/TimeSeriesPrognosisSolutionBase.cs	(revision 8009)
+++ /branches/HeuristicLab.TimeSeries/HeuristicLab.Problems.DataAnalysis/3.4/Implementation/TimeSeriesPrognosis/TimeSeriesPrognosisSolutionBase.cs	(revision 8010)
@@ -74,5 +74,5 @@
     }
 
-    public abstract IEnumerable<IEnumerable<double>> GetPrognosedValues(IEnumerable<int> rows, int horizon);
+    public abstract IEnumerable<IEnumerable<double>> GetPrognosedValues(IEnumerable<int> rows, IEnumerable<int> horizon);
 
     #region Results
@@ -192,120 +192,83 @@
 
     protected void CalculateResults() {
-      string targetVariable = ProblemData.TargetVariable;
-
-      var trainingMseCalculators = new OnlineMeanSquaredErrorCalculator();
-      var testMseCalculators = new OnlineMeanSquaredErrorCalculator();
-      var trainingMaeCalculators = new OnlineMeanAbsoluteErrorCalculator();
-      var testMaeCalculators = new OnlineMeanAbsoluteErrorCalculator();
-      var trainingRSquaredCalculators = new OnlinePearsonsRSquaredCalculator();
-      var testRSquaredCalculators = new OnlinePearsonsRSquaredCalculator();
-      var trainingRelErrorCalculators = new OnlineMeanAbsolutePercentageErrorCalculator();
-      var testRelErrorCalculators = new OnlineMeanAbsolutePercentageErrorCalculator();
-      var trainingNmseCalculators = new OnlineNormalizedMeanSquaredErrorCalculator();
-      var testNmseCalculators = new OnlineNormalizedMeanSquaredErrorCalculator();
-
-      var trainingDsCalculators = new OnlineDirectionalSymmetryCalculator();
-      var testDsCalculators = new OnlineDirectionalSymmetryCalculator();
-      var trainingWdsCalculators = new OnlineWeightedDirectionalSymmetryCalculator();
-      var testWdsCalculators = new OnlineWeightedDirectionalSymmetryCalculator();
-      var trainingTheilsULastCalculators = new OnlineTheilsUStatisticCalculator();
-      var testTheilsULastCalculators = new OnlineTheilsUStatisticCalculator();
-      var trainingTheilsUMeanCalculators = new OnlineTheilsUStatisticCalculator();
-      var testTheilsUMeanCalculators = new OnlineTheilsUStatisticCalculator();
-      var trainingTheilsUMovingAverageCalculators = new OnlineTheilsUStatisticCalculator();
-      var testTheilsUMovingAverageCalculators = new OnlineTheilsUStatisticCalculator();
-
-      double mean = ProblemData.Dataset.GetDoubleValues(targetVariable, ProblemData.TrainingIndizes).Average();
-
-      foreach (var row in ProblemData.TrainingIndizes) {
-        if (row + horizon < ProblemData.Dataset.Rows) {
-          var actualContinuation = ProblemData.Dataset.GetDoubleValues(targetVariable, Enumerable.Range(row, horizon)).ToList();
-          var prognosedContinuation = GetPrognosedValues(new List<int> { row }, horizon).First().ToList();
-
-          int maWindow = 10 * horizon;
-          var movingAverageContinuation = from h in Enumerable.Range(0, horizon)
-                                          select (from r in Enumerable.Range(row + h - maWindow, maWindow - h)
-                                                  where r > 0
-                                                  select ProblemData.Dataset.GetDoubleValue(targetVariable, r)
-                                                 ).Average();
-
-          double startValue = ProblemData.Dataset.GetDoubleValue(targetVariable, row - 1);
-
-          trainingDsCalculators.Add(startValue, actualContinuation, prognosedContinuation);
-          trainingWdsCalculators.Add(startValue, actualContinuation, prognosedContinuation);
-          trainingTheilsULastCalculators.Add(startValue, actualContinuation, prognosedContinuation);
-          trainingTheilsUMeanCalculators.Add(startValue, actualContinuation.Select(x => mean), actualContinuation, prognosedContinuation);
-          trainingTheilsUMovingAverageCalculators.Add(startValue, movingAverageContinuation, actualContinuation, prognosedContinuation);
-
-          var actualContinuationEnumerator = actualContinuation.GetEnumerator();
-          var prognosedContinuationEnumerator = prognosedContinuation.GetEnumerator();
-
-          while (actualContinuationEnumerator.MoveNext() & prognosedContinuationEnumerator.MoveNext()) {
-            trainingMseCalculators.Add(actualContinuationEnumerator.Current, prognosedContinuationEnumerator.Current);
-            trainingMaeCalculators.Add(actualContinuationEnumerator.Current, prognosedContinuationEnumerator.Current);
-            trainingRelErrorCalculators.Add(actualContinuationEnumerator.Current, prognosedContinuationEnumerator.Current);
-            trainingRSquaredCalculators.Add(actualContinuationEnumerator.Current, prognosedContinuationEnumerator.Current);
-            trainingNmseCalculators.Add(actualContinuationEnumerator.Current, prognosedContinuationEnumerator.Current);
-          }
-          if (actualContinuationEnumerator.MoveNext() | prognosedContinuationEnumerator.MoveNext())
-            throw new ArgumentException("Different number of elements in Actual continuation and prognosed continuation.");
-        }
-      }
-
-      mean = ProblemData.Dataset.GetDoubleValues(targetVariable, ProblemData.TestIndizes).Average();
-      foreach (var row in ProblemData.TestIndizes) {
-        if (row + horizon < ProblemData.Dataset.Rows) {
-          var actualContinuation = ProblemData.Dataset.GetDoubleValues(targetVariable, Enumerable.Range(row, horizon)).ToList();
-          var prognosedContinuation = GetPrognosedValues(new List<int> { row }, horizon).First().ToList();
-
-          int maWindow = 10 * horizon;
-          var movingAverageContinuation = from h in Enumerable.Range(0, horizon)
-                                          select (from r in Enumerable.Range(row + h - maWindow, maWindow - h)
-                                                  where r > 0
-                                                  select ProblemData.Dataset.GetDoubleValue(targetVariable, r)
-                                                 ).Average();
-
-          double startValue = ProblemData.Dataset.GetDoubleValue(targetVariable, row - 1);
-          testDsCalculators.Add(startValue, actualContinuation, prognosedContinuation);
-          testWdsCalculators.Add(startValue, actualContinuation, prognosedContinuation);
-          testTheilsULastCalculators.Add(startValue, actualContinuation, prognosedContinuation);
-          testTheilsUMeanCalculators.Add(startValue, actualContinuation.Select(x => mean), actualContinuation, prognosedContinuation);
-          testTheilsUMovingAverageCalculators.Add(startValue, movingAverageContinuation, actualContinuation, prognosedContinuation);
-
-          var actualContinuationEnumerator = actualContinuation.GetEnumerator();
-          var prognosedContinuationEnumerator = prognosedContinuation.GetEnumerator();
-          while (actualContinuationEnumerator.MoveNext() & prognosedContinuationEnumerator.MoveNext()) {
-            testMseCalculators.Add(actualContinuationEnumerator.Current, prognosedContinuationEnumerator.Current);
-            testMaeCalculators.Add(actualContinuationEnumerator.Current, prognosedContinuationEnumerator.Current);
-            testRelErrorCalculators.Add(actualContinuationEnumerator.Current, prognosedContinuationEnumerator.Current);
-            testRSquaredCalculators.Add(actualContinuationEnumerator.Current, prognosedContinuationEnumerator.Current);
-            testNmseCalculators.Add(actualContinuationEnumerator.Current, prognosedContinuationEnumerator.Current);
-          }
-          if (actualContinuationEnumerator.MoveNext() | prognosedContinuationEnumerator.MoveNext())
-            throw new ArgumentException("Different number of elements in Actual continuation and prognosed continuation.");
-        }
-      }
-
-      TrainingMeanSquaredError = trainingMseCalculators.ErrorState == OnlineCalculatorError.None ? trainingMseCalculators.Value : double.PositiveInfinity;
-      TestMeanSquaredError = testMseCalculators.ErrorState == OnlineCalculatorError.None ? testMseCalculators.Value : double.PositiveInfinity;
-      TrainingMeanAbsoluteError = trainingMaeCalculators.ErrorState == OnlineCalculatorError.None ? trainingMaeCalculators.Value : double.PositiveInfinity;
-      TestMeanAbsoluteError = testMaeCalculators.ErrorState == OnlineCalculatorError.None ? testMaeCalculators.Value : double.PositiveInfinity;
-      TrainingRelativeError = trainingRelErrorCalculators.ErrorState == OnlineCalculatorError.None ? trainingRelErrorCalculators.Value : double.PositiveInfinity;
-      TestRelativeError = testRelErrorCalculators.ErrorState == OnlineCalculatorError.None ? testRelErrorCalculators.Value : double.PositiveInfinity;
-      TrainingRSquared = trainingRSquaredCalculators.ErrorState == OnlineCalculatorError.None ? trainingRSquaredCalculators.Value : 0.0;
-      TestRSquared = testRSquaredCalculators.ErrorState == OnlineCalculatorError.None ? testRSquaredCalculators.Value : 0.0;
-      TrainingNormalizedMeanSquaredError = trainingNmseCalculators.ErrorState == OnlineCalculatorError.None ? trainingNmseCalculators.Value : double.PositiveInfinity;
-      TestNormalizedMeanSquaredError = testNmseCalculators.ErrorState == OnlineCalculatorError.None ? testNmseCalculators.Value : double.PositiveInfinity;
-
-      TrainingDirectionalSymmetry = trainingDsCalculators.ErrorState == OnlineCalculatorError.None ? trainingDsCalculators.Value : 0.0;
-      TestDirectionalSymmetry = testDsCalculators.ErrorState == OnlineCalculatorError.None ? testDsCalculators.Value : 0.0;
-      TrainingWeightedDirectionalSymmetry = trainingWdsCalculators.ErrorState == OnlineCalculatorError.None ? trainingWdsCalculators.Value : double.PositiveInfinity;
-      TestWeightedDirectionalSymmetry = testWdsCalculators.ErrorState == OnlineCalculatorError.None ? testWdsCalculators.Value : double.PositiveInfinity;
-      TrainingTheilsUStatisticLast = trainingTheilsULastCalculators.ErrorState == OnlineCalculatorError.None ? trainingTheilsULastCalculators.Value : double.PositiveInfinity;
-      TestTheilsUStatisticLast = testTheilsULastCalculators.ErrorState == OnlineCalculatorError.None ? testTheilsULastCalculators.Value : double.PositiveInfinity;
-      TrainingTheilsUStatisticMean = trainingTheilsUMeanCalculators.ErrorState == OnlineCalculatorError.None ? trainingTheilsUMeanCalculators.Value : double.PositiveInfinity;
-      TestTheilsUStatisticMean = testTheilsUMeanCalculators.ErrorState == OnlineCalculatorError.None ? testTheilsUMeanCalculators.Value : double.PositiveInfinity;
-      TrainingTheilsUStatisticMovingAverage = trainingTheilsUMovingAverageCalculators.ErrorState == OnlineCalculatorError.None ? trainingTheilsUMovingAverageCalculators.Value : double.PositiveInfinity;
-      TestTheilsUStatisticMovingAverage = testTheilsUMovingAverageCalculators.ErrorState == OnlineCalculatorError.None ? testTheilsUMovingAverageCalculators.Value : double.PositiveInfinity;
+      OnlineCalculatorError errorState;
+      //mean model
+      double trainingMean = ProblemData.Dataset.GetDoubleValues(ProblemData.TargetVariable, ProblemData.TrainingIndizes).Average();
+      var meanModel = new TimeSeriesPrognosisConstantModel(trainingMean);
+
+      //AR1 model
+      double alpha, beta;
+      IEnumerable<double> trainingStartValues = ProblemData.Dataset.GetDoubleValues(ProblemData.TargetVariable, ProblemData.TrainingIndizes.Select(r => r - 1).Where(r => r > 0)).ToList();
+      OnlineLinearScalingParameterCalculator.Calculate(ProblemData.Dataset.GetDoubleValues(ProblemData.TargetVariable, ProblemData.TrainingIndizes.Where(x => x > 0)), trainingStartValues, out alpha, out beta, out errorState);
+      var AR1model = new TimeSeriesPrognosisAutoRegressiveModel(alpha, beta, ProblemData.TargetVariable);
+
+      //MA model
+      int movingAverageWindowSize = 10 + horizon;
+      var MovingAverageModel = new TimeSeriesPrognosisMovingAverageModel(movingAverageWindowSize, ProblemData.TargetVariable);
+
+      #region Calculate training quality measures
+      var trainingHorizions = ProblemData.TrainingIndizes.Select(r => Math.Min(horizon, ProblemData.TrainingPartition.End - r)).ToList();
+      IEnumerable<IEnumerable<double>> trainingTargetValues = ProblemData.TrainingIndizes.Zip(trainingHorizions, Enumerable.Range).Select(r => ProblemData.Dataset.GetDoubleValues(ProblemData.TargetVariable, r)).ToList();
+      IEnumerable<IEnumerable<double>> trainingEstimatedValues = Model.GetPrognosedValues(ProblemData.Dataset, ProblemData.TrainingIndizes, trainingHorizions).ToList();
+
+      TrainingMeanSquaredError = OnlineMeanSquaredErrorCalculator.Calculate(trainingTargetValues.SelectMany(x => x), trainingEstimatedValues.SelectMany(x => x), out errorState);
+      TrainingMeanSquaredError = errorState == OnlineCalculatorError.None ? TrainingMeanSquaredError : double.PositiveInfinity;
+      TrainingMeanAbsoluteError = OnlineMeanAbsoluteErrorCalculator.Calculate(trainingTargetValues.SelectMany(x => x), trainingEstimatedValues.SelectMany(x => x), out errorState);
+      TrainingMeanAbsoluteError = errorState == OnlineCalculatorError.None ? TrainingMeanAbsoluteError : double.PositiveInfinity;
+      TrainingRelativeError = OnlineMeanAbsolutePercentageErrorCalculator.Calculate(trainingTargetValues.SelectMany(x => x), trainingEstimatedValues.SelectMany(x => x), out errorState);
+      TrainingRelativeError = errorState == OnlineCalculatorError.None ? TrainingRelativeError : double.PositiveInfinity;
+      TrainingRSquared = OnlinePearsonsRSquaredCalculator.Calculate(trainingTargetValues.SelectMany(x => x), trainingEstimatedValues.SelectMany(x => x), out errorState);
+      TrainingRSquared = errorState == OnlineCalculatorError.None ? TrainingRSquared : 0.0;
+      TrainingNormalizedMeanSquaredError = OnlineNormalizedMeanSquaredErrorCalculator.Calculate(trainingTargetValues.SelectMany(x => x), trainingEstimatedValues.SelectMany(x => x), out errorState);
+      TrainingNormalizedMeanSquaredError = errorState == OnlineCalculatorError.None ? TrainingNormalizedMeanSquaredError : double.PositiveInfinity;
+
+      IEnumerable<IEnumerable<double>> trainingMeanModelPredictions = meanModel.GetPrognosedValues(ProblemData.Dataset, ProblemData.TrainingIndizes, trainingHorizions);
+      IEnumerable<IEnumerable<double>> trainingAR1ModelPredictions = AR1model.GetPrognosedValues(ProblemData.Dataset, ProblemData.TrainingIndizes, trainingHorizions);
+      IEnumerable<IEnumerable<double>> trainingMovingAverageModelPredictions = MovingAverageModel.GetPrognosedValues(ProblemData.Dataset, ProblemData.TrainingIndizes, trainingHorizions);
+
+      TrainingDirectionalSymmetry = OnlineDirectionalSymmetryCalculator.Calculate(trainingStartValues, trainingTargetValues, trainingEstimatedValues, out errorState);
+      TrainingDirectionalSymmetry = errorState == OnlineCalculatorError.None ? TrainingDirectionalSymmetry : 0.0;
+      TrainingWeightedDirectionalSymmetry = OnlineWeightedDirectionalSymmetryCalculator.Calculate(trainingStartValues, trainingTargetValues, trainingEstimatedValues, out errorState);
+      TrainingWeightedDirectionalSymmetry = errorState == OnlineCalculatorError.None ? TrainingWeightedDirectionalSymmetry : 0.0;
+      TrainingTheilsUStatisticLast = OnlineTheilsUStatisticCalculator.Calculate(trainingStartValues, trainingTargetValues, trainingAR1ModelPredictions, trainingEstimatedValues, out errorState);
+      TrainingTheilsUStatisticLast = errorState == OnlineCalculatorError.None ? TrainingTheilsUStatisticLast : double.PositiveInfinity; ;
+      TrainingTheilsUStatisticMean = OnlineTheilsUStatisticCalculator.Calculate(trainingStartValues, trainingTargetValues, trainingMeanModelPredictions, trainingEstimatedValues, out errorState);
+      TrainingTheilsUStatisticMean = errorState == OnlineCalculatorError.None ? TrainingTheilsUStatisticMean : double.PositiveInfinity; ;
+      TrainingTheilsUStatisticMovingAverage = OnlineTheilsUStatisticCalculator.Calculate(trainingStartValues, trainingTargetValues, trainingMovingAverageModelPredictions, trainingEstimatedValues, out errorState);
+      TrainingTheilsUStatisticMovingAverage = errorState == OnlineCalculatorError.None ? TrainingTheilsUStatisticMovingAverage : double.PositiveInfinity; ; ;
+      #endregion
+
+      #region  Calculate test quality measures
+      var testHorizions = ProblemData.TestIndizes.Select(r => Math.Min(horizon, ProblemData.TestPartition.End - r)).ToList();
+      IEnumerable<IEnumerable<double>> testTargetValues = ProblemData.TestIndizes.Zip(testHorizions, Enumerable.Range).Select(r => ProblemData.Dataset.GetDoubleValues(ProblemData.TargetVariable, r)).ToList();
+      IEnumerable<IEnumerable<double>> testEstimatedValues = Model.GetPrognosedValues(ProblemData.Dataset, ProblemData.TestIndizes, testHorizions).ToList();
+
+      TestMeanSquaredError = OnlineMeanSquaredErrorCalculator.Calculate(testTargetValues.SelectMany(x => x), testEstimatedValues.SelectMany(x => x), out errorState);
+      TestMeanSquaredError = errorState == OnlineCalculatorError.None ? TestMeanSquaredError : double.PositiveInfinity;
+      TestMeanAbsoluteError = OnlineMeanAbsoluteErrorCalculator.Calculate(testTargetValues.SelectMany(x => x), testEstimatedValues.SelectMany(x => x), out errorState);
+      TestMeanAbsoluteError = errorState == OnlineCalculatorError.None ? TestMeanAbsoluteError : double.PositiveInfinity;
+      TestRelativeError = OnlineMeanAbsolutePercentageErrorCalculator.Calculate(testTargetValues.SelectMany(x => x), testEstimatedValues.SelectMany(x => x), out errorState);
+      TestRelativeError = errorState == OnlineCalculatorError.None ? TestRelativeError : double.PositiveInfinity;
+      TestRSquared = OnlinePearsonsRSquaredCalculator.Calculate(testTargetValues.SelectMany(x => x), testEstimatedValues.SelectMany(x => x), out errorState);
+      TestRSquared = errorState == OnlineCalculatorError.None ? TestRSquared : 0.0;
+      TestNormalizedMeanSquaredError = OnlineNormalizedMeanSquaredErrorCalculator.Calculate(testTargetValues.SelectMany(x => x), testEstimatedValues.SelectMany(x => x), out errorState);
+      TestNormalizedMeanSquaredError = errorState == OnlineCalculatorError.None ? TestNormalizedMeanSquaredError : double.PositiveInfinity;
+
+      IEnumerable<double> testStartValues = ProblemData.Dataset.GetDoubleValues(ProblemData.TargetVariable, ProblemData.TestIndizes.Select(r => r - 1).Where(r => r > 0)).ToList();
+      IEnumerable<IEnumerable<double>> testMeanModelPredictions = meanModel.GetPrognosedValues(ProblemData.Dataset, ProblemData.TestIndizes, testHorizions);
+      IEnumerable<IEnumerable<double>> testAR1ModelPredictions = AR1model.GetPrognosedValues(ProblemData.Dataset, ProblemData.TestIndizes, testHorizions);
+      IEnumerable<IEnumerable<double>> testMovingAverageModelPredictions = MovingAverageModel.GetPrognosedValues(ProblemData.Dataset, ProblemData.TestIndizes, testHorizions);
+
+      TestDirectionalSymmetry = OnlineDirectionalSymmetryCalculator.Calculate(testStartValues, testTargetValues, testEstimatedValues, out errorState);
+      TestDirectionalSymmetry = errorState == OnlineCalculatorError.None ? TestDirectionalSymmetry : 0.0;
+      TestWeightedDirectionalSymmetry = OnlineWeightedDirectionalSymmetryCalculator.Calculate(testStartValues, testTargetValues, testEstimatedValues, out errorState);
+      TestWeightedDirectionalSymmetry = errorState == OnlineCalculatorError.None ? TestWeightedDirectionalSymmetry : 0.0;
+      TestTheilsUStatisticLast = OnlineTheilsUStatisticCalculator.Calculate(testStartValues, testTargetValues, testAR1ModelPredictions, testEstimatedValues, out errorState);
+      TestTheilsUStatisticLast = errorState == OnlineCalculatorError.None ? TestTheilsUStatisticLast : double.PositiveInfinity; ;
+      TestTheilsUStatisticMean = OnlineTheilsUStatisticCalculator.Calculate(testStartValues, testTargetValues, testMeanModelPredictions, testEstimatedValues, out errorState);
+      TestTheilsUStatisticMean = errorState == OnlineCalculatorError.None ? TestTheilsUStatisticMean : double.PositiveInfinity; ;
+      TestTheilsUStatisticMovingAverage = OnlineTheilsUStatisticCalculator.Calculate(testStartValues, testTargetValues, testMovingAverageModelPredictions, testEstimatedValues, out errorState);
+      TestTheilsUStatisticMovingAverage = errorState == OnlineCalculatorError.None ? TestTheilsUStatisticMovingAverage : double.PositiveInfinity; ; ;
+      #endregion     
     }
   }
Index: /branches/HeuristicLab.TimeSeries/HeuristicLab.Problems.DataAnalysis/3.4/Interfaces/TimeSeriesPrognosis/ITimeSeriesPrognosisModel.cs
===================================================================
--- /branches/HeuristicLab.TimeSeries/HeuristicLab.Problems.DataAnalysis/3.4/Interfaces/TimeSeriesPrognosis/ITimeSeriesPrognosisModel.cs	(revision 8009)
+++ /branches/HeuristicLab.TimeSeries/HeuristicLab.Problems.DataAnalysis/3.4/Interfaces/TimeSeriesPrognosis/ITimeSeriesPrognosisModel.cs	(revision 8010)
@@ -23,5 +23,5 @@
 namespace HeuristicLab.Problems.DataAnalysis {
   public interface ITimeSeriesPrognosisModel : IDataAnalysisModel {
-    IEnumerable<IEnumerable<double>> GetPrognosedValues(Dataset dataset, IEnumerable<int> rows, int horizon);
+    IEnumerable<IEnumerable<double>> GetPrognosedValues(Dataset dataset, IEnumerable<int> rows, IEnumerable<int> horizons);
     ITimeSeriesPrognosisSolution CreateTimeSeriesPrognosisSolution(ITimeSeriesPrognosisProblemData problemData);
   }
Index: /branches/HeuristicLab.TimeSeries/HeuristicLab.Problems.DataAnalysis/3.4/Interfaces/TimeSeriesPrognosis/ITimeSeriesPrognosisSolution.cs
===================================================================
--- /branches/HeuristicLab.TimeSeries/HeuristicLab.Problems.DataAnalysis/3.4/Interfaces/TimeSeriesPrognosis/ITimeSeriesPrognosisSolution.cs	(revision 8009)
+++ /branches/HeuristicLab.TimeSeries/HeuristicLab.Problems.DataAnalysis/3.4/Interfaces/TimeSeriesPrognosis/ITimeSeriesPrognosisSolution.cs	(revision 8010)
@@ -27,5 +27,5 @@
     new ITimeSeriesPrognosisProblemData ProblemData { get; set; }
 
-    IEnumerable<IEnumerable<double>> GetPrognosedValues(IEnumerable<int> rows, int horizon);
+    IEnumerable<IEnumerable<double>> GetPrognosedValues(IEnumerable<int> rows, IEnumerable<int> horizon);
 
     double TrainingMeanSquaredError { get; }
Index: /branches/HeuristicLab.TimeSeries/HeuristicLab.Problems.DataAnalysis/3.4/OnlineCalculators/OnlineTheilsUStatisticCalculator.cs
===================================================================
--- /branches/HeuristicLab.TimeSeries/HeuristicLab.Problems.DataAnalysis/3.4/OnlineCalculators/OnlineTheilsUStatisticCalculator.cs	(revision 8009)
+++ /branches/HeuristicLab.TimeSeries/HeuristicLab.Problems.DataAnalysis/3.4/OnlineCalculators/OnlineTheilsUStatisticCalculator.cs	(revision 8010)
@@ -23,5 +23,4 @@
 using System.Collections.Generic;
 using System.Linq;
-using HeuristicLab.Common;
 
 namespace HeuristicLab.Problems.DataAnalysis {
@@ -97,13 +96,15 @@
     #endregion
 
-    public static double Calculate(IEnumerable<double> startValues, IEnumerable<IEnumerable<double>> actualContinuations, IEnumerable<IEnumerable<double>> predictedContinuations, out OnlineCalculatorError errorState) {
+    public static double Calculate(IEnumerable<double> startValues, IEnumerable<IEnumerable<double>> actualContinuations, IEnumerable<IEnumerable<double>> referenceContinuations, IEnumerable<IEnumerable<double>> predictedContinuations, out OnlineCalculatorError errorState) {
       IEnumerator<double> startValueEnumerator = startValues.GetEnumerator();
       IEnumerator<IEnumerable<double>> actualContinuationsEnumerator = actualContinuations.GetEnumerator();
+      IEnumerator<IEnumerable<double>> referenceContinuationsEnumerator = referenceContinuations.GetEnumerator();
       IEnumerator<IEnumerable<double>> predictedContinuationsEnumerator = predictedContinuations.GetEnumerator();
+
       OnlineTheilsUStatisticCalculator calculator = new OnlineTheilsUStatisticCalculator();
 
       // always move forward all enumerators (do not use short-circuit evaluation!)
-      while (startValueEnumerator.MoveNext() & actualContinuationsEnumerator.MoveNext() & predictedContinuationsEnumerator.MoveNext()) {
-        calculator.Add(startValueEnumerator.Current, actualContinuationsEnumerator.Current, predictedContinuationsEnumerator.Current);
+      while (startValueEnumerator.MoveNext() & actualContinuationsEnumerator.MoveNext() & referenceContinuationsEnumerator.MoveNext() & predictedContinuationsEnumerator.MoveNext()) {
+        calculator.Add(startValueEnumerator.Current, actualContinuationsEnumerator.Current, referenceContinuationsEnumerator.Current, predictedContinuationsEnumerator.Current);
         if (calculator.ErrorState != OnlineCalculatorError.None) break;
       }
@@ -111,6 +112,6 @@
       // check if all enumerators are at the end to make sure both enumerations have the same length
       if (calculator.ErrorState == OnlineCalculatorError.None &&
-          (startValueEnumerator.MoveNext() || actualContinuationsEnumerator.MoveNext() || predictedContinuationsEnumerator.MoveNext())) {
-        throw new ArgumentException("Number of elements in startValues, actualContinuations and estimatedValues predictedContinuations doesn't match.");
+          (startValueEnumerator.MoveNext() || actualContinuationsEnumerator.MoveNext() || referenceContinuationsEnumerator.MoveNext() || predictedContinuationsEnumerator.MoveNext())) {
+        throw new ArgumentException("Number of elements in startValues, actualContinuations, referenceContinuation and estimatedValues predictedContinuations doesn't match.");
       } else {
         errorState = calculator.ErrorState;
Index: /branches/HeuristicLab.TimeSeries/HeuristicLab.TimeSeries-3.3.sln
===================================================================
--- /branches/HeuristicLab.TimeSeries/HeuristicLab.TimeSeries-3.3.sln	(revision 8009)
+++ /branches/HeuristicLab.TimeSeries/HeuristicLab.TimeSeries-3.3.sln	(revision 8010)
@@ -7,4 +7,5 @@
 		ConfigMerger.exe = ConfigMerger.exe
 		..\documentation\License\gpl-3.0.txt = ..\documentation\License\gpl-3.0.txt
+		HeuristicLab.TimeSeries-3.32.vsmdi = HeuristicLab.TimeSeries-3.32.vsmdi
 		LocalTestRun.testrunconfig = LocalTestRun.testrunconfig
 		MergeConfigs.cmd = MergeConfigs.cmd
@@ -32,4 +33,7 @@
 EndProject
 Global
+	GlobalSection(TestCaseManagementSettings) = postSolution
+		CategoryFile = HeuristicLab.TimeSeries-3.32.vsmdi
+	EndGlobalSection
 	GlobalSection(SolutionConfigurationPlatforms) = preSolution
 		Debug|Any CPU = Debug|Any CPU
Index: /branches/HeuristicLab.TimeSeries/HeuristicLab.TimeSeries-3.32.vsmdi
===================================================================
--- /branches/HeuristicLab.TimeSeries/HeuristicLab.TimeSeries-3.32.vsmdi	(revision 8010)
+++ /branches/HeuristicLab.TimeSeries/HeuristicLab.TimeSeries-3.32.vsmdi	(revision 8010)
@@ -0,0 +1,6 @@
+﻿<?xml version="1.0" encoding="UTF-8"?>
+<TestLists xmlns="http://microsoft.com/schemas/VisualStudio/TeamTest/2010">
+  <TestList name="Lists of Tests" id="8c43106b-9dc1-4907-a29f-aa66a61bf5b6">
+    <RunConfiguration id="f9392825-866f-4434-be36-358db28f0c59" name="Local Test Run" storage="localtestrun.testrunconfig" type="Microsoft.VisualStudio.TestTools.Common.TestRunConfiguration, Microsoft.VisualStudio.QualityTools.Common, Version=10.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a" />
+  </TestList>
+</TestLists>
