Index: /branches/HeuristicLab.TimeSeries/HeuristicLab.Problems.DataAnalysis.Symbolic.TimeSeriesPrognosis.Views/3.4/HeuristicLab.Problems.DataAnalysis.Symbolic.TimeSeriesPrognosis.Views-3.4.csproj
===================================================================
--- /branches/HeuristicLab.TimeSeries/HeuristicLab.Problems.DataAnalysis.Symbolic.TimeSeriesPrognosis.Views/3.4/HeuristicLab.Problems.DataAnalysis.Symbolic.TimeSeriesPrognosis.Views-3.4.csproj	(revision 7128)
+++ /branches/HeuristicLab.TimeSeries/HeuristicLab.Problems.DataAnalysis.Symbolic.TimeSeriesPrognosis.Views/3.4/HeuristicLab.Problems.DataAnalysis.Symbolic.TimeSeriesPrognosis.Views-3.4.csproj	(revision 7129)
@@ -110,5 +110,17 @@
   </ItemGroup>
   <ItemGroup>
+    <Compile Include="InteractiveSymbolicTimeSeriesPrognosisSolutionSimplifierView.cs">
+      <SubType>UserControl</SubType>
+    </Compile>
+    <Compile Include="InteractiveSymbolicTimeSeriesPrognosisSolutionSimplifierView.Designer.cs">
+      <DependentUpon>InteractiveSymbolicTimeSeriesPrognosisSolutionSimplifierView.cs</DependentUpon>
+    </Compile>
     <Compile Include="Plugin.cs" />
+    <Compile Include="SymbolicTimeSeriesPrognosisSolutionView.cs">
+      <SubType>UserControl</SubType>
+    </Compile>
+    <Compile Include="SymbolicTimeSeriesPrognosisSolutionView.Designer.cs">
+      <DependentUpon>SymbolicTimeSeriesPrognosisSolutionView.cs</DependentUpon>
+    </Compile>
     <None Include="HeuristicLab.snk" />
     <None Include="Plugin.cs.frame" />
Index: /branches/HeuristicLab.TimeSeries/HeuristicLab.Problems.DataAnalysis.Symbolic.TimeSeriesPrognosis.Views/3.4/InteractiveSymbolicTimeSeriesPrognosisSolutionSimplifierView.cs
===================================================================
--- /branches/HeuristicLab.TimeSeries/HeuristicLab.Problems.DataAnalysis.Symbolic.TimeSeriesPrognosis.Views/3.4/InteractiveSymbolicTimeSeriesPrognosisSolutionSimplifierView.cs	(revision 7128)
+++ /branches/HeuristicLab.TimeSeries/HeuristicLab.Problems.DataAnalysis.Symbolic.TimeSeriesPrognosis.Views/3.4/InteractiveSymbolicTimeSeriesPrognosisSolutionSimplifierView.cs	(revision 7129)
@@ -50,5 +50,5 @@
 
     protected override void UpdateModel(ISymbolicExpressionTree tree) {
-      var model = new SymbolicTimeSeriesPrognosisModel(tree, Content.Model.Interpreter);
+      var model = new SymbolicTimeSeriesPrognosisModel(tree, Content.Model.Interpreter, Content.ProblemData.TargetVariables.ToArray());
       SymbolicTimeSeriesPrognosisModel.Scale(model, Content.ProblemData);
       Content.Model = model;
@@ -67,28 +67,32 @@
       var dataset = Content.ProblemData.Dataset;
       var rows = Content.ProblemData.TrainingIndizes;
-      string targetVariable = Content.ProblemData.TargetVariable;
-      Dictionary<ISymbolicExpressionTreeNode, double> impactValues = new Dictionary<ISymbolicExpressionTreeNode, double>();
-      List<ISymbolicExpressionTreeNode> nodes = tree.Root.GetSubtree(0).GetSubtree(0).IterateNodesPostfix().ToList();
-      var originalOutput = interpreter.GetSymbolicExpressionTreeValues(tree, dataset, rows)
+      Dictionary<ISymbolicExpressionTreeNode, double> impactValues =
+        new Dictionary<ISymbolicExpressionTreeNode, double>();
+      var originalOutput = interpreter.GetSymbolicExpressionTreeValues(tree, dataset, Content.ProblemData.TargetVariables.ToArray(), rows, 1)
         .ToArray();
-      var targetValues = dataset.GetDoubleValues(targetVariable, rows);
-      OnlineCalculatorError errorState;
-      double originalR2 = OnlinePearsonsRSquaredCalculator.Calculate(targetValues, originalOutput, out errorState);
-      if (errorState != OnlineCalculatorError.None) originalR2 = 0.0;
+      int i = 0;
+      foreach (var targetVariable in Content.ProblemData.TargetVariables) {
+        List<ISymbolicExpressionTreeNode> nodes = tree.Root.GetSubtree(0).GetSubtree(i).IterateNodesPostfix().ToList();
+        var targetValues = dataset.GetDoubleValues(targetVariable, rows);
+        OnlineCalculatorError errorState;
+        double originalR2 = OnlinePearsonsRSquaredCalculator.Calculate(targetValues, originalOutput.Select(v => v.ElementAt(i).First()), out errorState);
+        if (errorState != OnlineCalculatorError.None) originalR2 = 0.0;
 
-      foreach (ISymbolicExpressionTreeNode node in nodes) {
-        var parent = node.Parent;
-        constantNode.Value = CalculateReplacementValue(node, tree);
-        ISymbolicExpressionTreeNode replacementNode = constantNode;
-        SwitchNode(parent, node, replacementNode);
-        var newOutput = interpreter.GetSymbolicExpressionTreeValues(tree, dataset, rows);
-        double newR2 = OnlinePearsonsRSquaredCalculator.Calculate(targetValues, newOutput, out errorState);
-        if (errorState != OnlineCalculatorError.None) newR2 = 0.0;
+        foreach (ISymbolicExpressionTreeNode node in nodes) {
+          var parent = node.Parent;
+          constantNode.Value = CalculateReplacementValue(node, tree);
+          ISymbolicExpressionTreeNode replacementNode = constantNode;
+          SwitchNode(parent, node, replacementNode);
+          var newOutput = interpreter.GetSymbolicExpressionTreeValues(tree, dataset, Content.ProblemData.TargetVariables.ToArray(), rows, 1);
+          double newR2 = OnlinePearsonsRSquaredCalculator.Calculate(targetValues, newOutput.Select(v => v.ElementAt(i).First()), out errorState);
+          if (errorState != OnlineCalculatorError.None) newR2 = 0.0;
 
-        // impact = 0 if no change
-        // impact < 0 if new solution is better
-        // impact > 0 if new solution is worse
-        impactValues[node] = originalR2 - newR2;
-        SwitchNode(parent, replacementNode, node);
+          // impact = 0 if no change
+          // impact < 0 if new solution is better
+          // impact > 0 if new solution is worse
+          impactValues[node] = originalR2 - newR2;
+          SwitchNode(parent, replacementNode, node);
+        }
+        i++;
       }
       return impactValues;
@@ -107,5 +111,7 @@
       var interpreter = Content.Model.Interpreter;
       var rows = Content.ProblemData.TrainingIndizes;
-      return interpreter.GetSymbolicExpressionTreeValues(tempTree, Content.ProblemData.Dataset, rows).Median();
+      var allPrognosedValues = interpreter.GetSymbolicExpressionTreeValues(tempTree, Content.ProblemData.Dataset, Content.ProblemData.TargetVariables.ToArray(), rows, 1);
+      
+      return allPrognosedValues.Select(x=>x.First().First()).Median();
     }
 
Index: /branches/HeuristicLab.TimeSeries/HeuristicLab.Problems.DataAnalysis.Symbolic.TimeSeriesPrognosis/3.4/HeuristicLab.Problems.DataAnalysis.Symbolic.TimeSeriesPrognosis-3.4.csproj
===================================================================
--- /branches/HeuristicLab.TimeSeries/HeuristicLab.Problems.DataAnalysis.Symbolic.TimeSeriesPrognosis/3.4/HeuristicLab.Problems.DataAnalysis.Symbolic.TimeSeriesPrognosis-3.4.csproj	(revision 7128)
+++ /branches/HeuristicLab.TimeSeries/HeuristicLab.Problems.DataAnalysis.Symbolic.TimeSeriesPrognosis/3.4/HeuristicLab.Problems.DataAnalysis.Symbolic.TimeSeriesPrognosis-3.4.csproj	(revision 7129)
@@ -117,6 +117,7 @@
     <Compile Include="Plugin.cs" />
     <Compile Include="SingleObjective\SymbolicTimeSeriesPrognosisSingleObjectiveEvaluator.cs" />
-    <Compile Include="SingleObjective\SymbolicTimeSeriesPrognosisSingleObjectiveMeanSquaredErrorEvaluator.cs" />
-    <Compile Include="SingleObjective\SymbolicTimeSeriesPrognosisSingleObjectivePearsonRSquaredEvaluator.cs" />
+    <Compile Include="SingleObjective\SymbolicTimeSeriesPrognosisSingleObjectiveMeanSquaredErrorEvaluator.cs">
+      <SubType>Code</SubType>
+    </Compile>
     <Compile Include="SingleObjective\SymbolicTimeSeriesPrognosisSingleObjectiveProblem.cs" />
     <Compile Include="SingleObjective\SymbolicTimeSeriesPrognosisSingleObjectiveTrainingBestSolutionAnalyzer.cs" />
Index: /branches/HeuristicLab.TimeSeries/HeuristicLab.Problems.DataAnalysis.Symbolic.TimeSeriesPrognosis/3.4/Interfaces/ISymbolicTimeSeriesPrognosisModel.cs
===================================================================
--- /branches/HeuristicLab.TimeSeries/HeuristicLab.Problems.DataAnalysis.Symbolic.TimeSeriesPrognosis/3.4/Interfaces/ISymbolicTimeSeriesPrognosisModel.cs	(revision 7128)
+++ /branches/HeuristicLab.TimeSeries/HeuristicLab.Problems.DataAnalysis.Symbolic.TimeSeriesPrognosis/3.4/Interfaces/ISymbolicTimeSeriesPrognosisModel.cs	(revision 7129)
@@ -22,6 +22,5 @@
 using HeuristicLab.Encodings.SymbolicExpressionTreeEncoding;
 namespace HeuristicLab.Problems.DataAnalysis.Symbolic.TimeSeriesPrognosis {
-  public interface ISymbolicTimeSeriesPrognosisModel : ITimeSeriesPrognosisModel {
-    ISymbolicExpressionTree SymbolicExpressionTree { get; }
+  public interface ISymbolicTimeSeriesPrognosisModel : ITimeSeriesPrognosisModel, ISymbolicDataAnalysisModel {
     ISymbolicTimeSeriesPrognosisExpressionTreeInterpreter Interpreter { get; }
   }
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 7128)
+++ /branches/HeuristicLab.TimeSeries/HeuristicLab.Problems.DataAnalysis.Symbolic.TimeSeriesPrognosis/3.4/SingleObjective/SymbolicTimeSeriesPrognosisSingleObjectiveMeanSquaredErrorEvaluator.cs	(revision 7129)
@@ -61,21 +61,109 @@
 
     public static double Calculate(ISymbolicTimeSeriesPrognosisExpressionTreeInterpreter interpreter, ISymbolicExpressionTree solution, double lowerEstimationLimit, double upperEstimationLimit, ITimeSeriesPrognosisProblemData problemData, IEnumerable<int> rows, int horizon) {
-      var allPredictedContinuations = interpreter.GetSymbolicExpressionTreeValues(solution, problemData.Dataset, problemData.TargetVariables.ToArray(), rows, horizon);
-      var meanCalculator = new OnlineMeanAndVarianceCalculator();
-      var allPredictedContinuationsEnumerator = allPredictedContinuations.GetEnumerator();
-      foreach (var targetVariable in problemData.TargetVariables) {
-        if (!allPredictedContinuationsEnumerator.MoveNext()) throw new InvalidOperationException();
-        var actualContinuations = from r in rows
-                                  select problemData.Dataset.GetDoubleValues(targetVariable, Enumerable.Range(r, horizon));
-        var actualContinuationsEnumerator = actualContinuations.GetEnumerator();
-        var predictedContinuationsEnumerator = allPredictedContinuationsEnumerator.Current.GetEnumerator();
-        while (actualContinuationsEnumerator.MoveNext() & predictedContinuationsEnumerator.MoveNext()) {
-          OnlineCalculatorError errorState;
-          meanCalculator.Add(OnlineMeanSquaredErrorCalculator.Calculate(predictedContinuationsEnumerator.Current.LimitToRange(lowerEstimationLimit, upperEstimationLimit),
-                                                                        actualContinuationsEnumerator.Current, out errorState));
-          if (errorState != OnlineCalculatorError.None) return double.NaN;
+      double[] alpha;
+      double[] beta;
+      DetermineScalingFactors(solution, problemData, interpreter, rows, out alpha, out beta);
+      var scaledSolution = Scale(solution, alpha, beta);
+
+      var meanSquaredErrorCalculators = Enumerable.Range(0, problemData.TargetVariables.Count())
+        .Select(i => new OnlineMeanSquaredErrorCalculator()).ToArray();
+
+      var allPredictedContinuations = interpreter.GetSymbolicExpressionTreeValues(scaledSolution, problemData.Dataset,
+                                                                                  problemData.TargetVariables.ToArray(),
+                                                                                  rows, horizon);
+      var allContinuationsEnumerator = allPredictedContinuations.GetEnumerator();
+      var rowsEnumerator = rows.GetEnumerator();
+      while (allContinuationsEnumerator.MoveNext() & rowsEnumerator.MoveNext()) {
+        var componentEnumerator = allContinuationsEnumerator.Current.GetEnumerator();
+        var mseCalculatorsEnumerator = meanSquaredErrorCalculators.AsEnumerable().GetEnumerator();
+        var targetVarEnumerator = problemData.TargetVariables.GetEnumerator();
+        while (componentEnumerator.MoveNext() & mseCalculatorsEnumerator.MoveNext() & targetVarEnumerator.MoveNext()) {
+          var stepEnumerator = componentEnumerator.Current.GetEnumerator();
+          var actualContinuationEnumerator = problemData.Dataset.GetDoubleValues(targetVarEnumerator.Current,
+                                                                       Enumerable.Range(rowsEnumerator.Current, horizon)).GetEnumerator();
+          while (stepEnumerator.MoveNext() & actualContinuationEnumerator.MoveNext()) {
+            double e = Math.Min(upperEstimationLimit, Math.Max(lowerEstimationLimit, stepEnumerator.Current));
+            mseCalculatorsEnumerator.Current.Add(actualContinuationEnumerator.Current, e);
+            if (mseCalculatorsEnumerator.Current.ErrorState == OnlineCalculatorError.InvalidValueAdded)
+              return double.NaN;
+          }
         }
       }
-      return meanCalculator.Mean;
+      var meanCalculator = new OnlineMeanAndVarianceCalculator();
+      foreach (var calc in meanSquaredErrorCalculators) {
+        if (calc.ErrorState != OnlineCalculatorError.None) return double.NaN;
+        meanCalculator.Add(calc.MeanSquaredError);
+      }
+      //int i = 0;
+      //foreach (var targetVariable in problemData.TargetVariables) {
+      //  var predictedContinuations = allPredictedContinuations.Select(v => v.ElementAt(i));
+      //  for (int h = 0; h < horizon; h++) {
+      //    OnlineCalculatorError errorState;
+      //    meanCalculator.Add(OnlineMeanSquaredErrorCalculator.Calculate(predictedContinuations
+      //                                                                    .Select(x => x.ElementAt(h))
+      //                                                                    .LimitToRange(lowerEstimationLimit,
+      //                                                                                  upperEstimationLimit),
+      //                                                                  actualContinuations.Select(x => x.ElementAt(h)),
+      //                                                                  out errorState));
+      //    if (errorState != OnlineCalculatorError.None) return double.NaN;
+      //  }
+      //}
+      return meanCalculator.MeanErrorState == OnlineCalculatorError.None ? meanCalculator.Mean : double.NaN;
+    }
+
+    private static ISymbolicExpressionTree Scale(ISymbolicExpressionTree solution, double[] alpha, double[] beta) {
+      var clone = (ISymbolicExpressionTree)solution.Clone();
+      int n = alpha.Length;
+      for (int i = 0; i < n; i++) {
+        var parent = clone.Root.GetSubtree(0);
+        var rpb = clone.Root.GetSubtree(0).GetSubtree(i);
+        var scaledRpb = MakeSum(
+          MakeProduct(rpb,
+            MakeConstant(beta[i], clone.Root.Grammar), clone.Root.Grammar),
+            MakeConstant(alpha[i], clone.Root.Grammar), clone.Root.Grammar);
+        parent.RemoveSubtree(i);
+        parent.InsertSubtree(i, scaledRpb);
+      }
+      return clone;
+    }
+
+    private static ISymbolicExpressionTreeNode MakeSum(ISymbolicExpressionTreeNode a, ISymbolicExpressionTreeNode b, ISymbolicExpressionTreeGrammar grammar) {
+      var sum = grammar.Symbols.Where(s => s is Addition).First().CreateTreeNode();
+      sum.AddSubtree(a);
+      sum.AddSubtree(b);
+      return sum;
+    }
+
+    private static ISymbolicExpressionTreeNode MakeProduct(ISymbolicExpressionTreeNode a, ISymbolicExpressionTreeNode b, ISymbolicExpressionTreeGrammar grammar) {
+      var prod = grammar.Symbols.Where(s => s is Multiplication).First().CreateTreeNode();
+      prod.AddSubtree(a);
+      prod.AddSubtree(b);
+      return prod;
+    }
+
+    private static ISymbolicExpressionTreeNode MakeConstant(double c, ISymbolicExpressionTreeGrammar grammar) {
+      var node = (ConstantTreeNode)grammar.Symbols.Where(s => s is Constant).First().CreateTreeNode();
+      node.Value = c;
+      return node;
+    }
+
+    private static void DetermineScalingFactors(ISymbolicExpressionTree solution, ITimeSeriesPrognosisProblemData problemData, ISymbolicTimeSeriesPrognosisExpressionTreeInterpreter interpreter, IEnumerable<int> rows, out double[] alpha, out double[] beta) {
+      string[] targetVariables = problemData.TargetVariables.ToArray();
+      int nComponents = targetVariables.Length;
+      alpha = new double[nComponents];
+      beta = new double[nComponents];
+      var oneStepPredictions = interpreter.GetSymbolicExpressionTreeValues(solution, problemData.Dataset,
+                                                                     targetVariables, rows,
+                                                                     1);
+      for (int i = 0; i < nComponents; i++) {
+        var target = problemData.Dataset.GetDoubleValues(targetVariables[i], rows);
+        var prediction = oneStepPredictions.Select(v => v.ElementAt(i).First());
+        OnlineCalculatorError errorState;
+        OnlineLinearScalingParameterCalculator.Calculate(prediction, target, out alpha[i], out beta[i], out errorState);
+        if (errorState != OnlineCalculatorError.None) {
+          alpha[i] = 0;
+          beta[i] = 1;
+        }
+      }
     }
 
Index: /branches/HeuristicLab.TimeSeries/HeuristicLab.Problems.DataAnalysis.Symbolic.TimeSeriesPrognosis/3.4/SingleObjective/SymbolicTimeSeriesPrognosisSingleObjectiveProblem.cs
===================================================================
--- /branches/HeuristicLab.TimeSeries/HeuristicLab.Problems.DataAnalysis.Symbolic.TimeSeriesPrognosis/3.4/SingleObjective/SymbolicTimeSeriesPrognosisSingleObjectiveProblem.cs	(revision 7128)
+++ /branches/HeuristicLab.TimeSeries/HeuristicLab.Problems.DataAnalysis.Symbolic.TimeSeriesPrognosis/3.4/SingleObjective/SymbolicTimeSeriesPrognosisSingleObjectiveProblem.cs	(revision 7129)
@@ -52,5 +52,5 @@
 
     public SymbolicTimeSeriesPrognosisSingleObjectiveProblem()
-      : base(new TimeSeriesPrognosisProblemData(), new SymbolicTimeSeriesPrognosisSingleObjectivePearsonRSquaredEvaluator(), new SymbolicDataAnalysisExpressionTreeCreator()) {
+      : base(new TimeSeriesPrognosisProblemData(), new SymbolicTimeSeriesPrognosisSingleObjectiveMeanSquaredErrorEvaluator(), new SymbolicDataAnalysisExpressionTreeCreator()) {
       Parameters.Add(new FixedValueParameter<DoubleLimit>(EstimationLimitsParameterName, EstimationLimitsParameterDescription));
 
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 7128)
+++ /branches/HeuristicLab.TimeSeries/HeuristicLab.Problems.DataAnalysis.Symbolic.TimeSeriesPrognosis/3.4/SymbolicTimeSeriesPrognosisModel.cs	(revision 7129)
@@ -53,4 +53,8 @@
     }
 
+    ISymbolicDataAnalysisExpressionTreeInterpreter ISymbolicDataAnalysisModel.Interpreter {
+      get { return (ISymbolicDataAnalysisExpressionTreeInterpreter)interpreter; }
+    }
+
     #endregion
 
@@ -102,7 +106,7 @@
         double beta;
         OnlineCalculatorError errorState;
-        OnlineLinearScalingParameterCalculator.Calculate(estimatedValues[i].Select(x => x.First()), targetValues,
+        OnlineLinearScalingParameterCalculator.Calculate(estimatedValues.Select(x => x.ElementAt(i).First()), targetValues,
           out alpha, out beta, out errorState);
-        if (errorState != OnlineCalculatorError.None) return;
+        if (errorState != OnlineCalculatorError.None) continue;
 
         ConstantTreeNode alphaTreeNode = null;
Index: /branches/HeuristicLab.TimeSeries/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/SymbolicDataAnalysisExpressionTreeILEmittingInterpreter.cs
===================================================================
--- /branches/HeuristicLab.TimeSeries/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/SymbolicDataAnalysisExpressionTreeILEmittingInterpreter.cs	(revision 7128)
+++ /branches/HeuristicLab.TimeSeries/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/SymbolicDataAnalysisExpressionTreeILEmittingInterpreter.cs	(revision 7129)
@@ -179,4 +179,10 @@
 
     public IEnumerable<double> GetSymbolicExpressionTreeValues(ISymbolicExpressionTree tree, Dataset dataset, IEnumerable<int> rows) {
+      return from prog in GetSymbolicExpressionTreeValues(tree, dataset, new string[] { "#NOTHING#" }, rows, 1)
+             select prog.First().First();
+    }
+
+    // for each row for each target variable one prognosis (=enumerable of future values)
+    public IEnumerable<IEnumerable<IEnumerable<double>>> GetSymbolicExpressionTreeValues(ISymbolicExpressionTree tree, Dataset dataset, string[] targetVariables, IEnumerable<int> rows, int horizon) {
       if (CheckExpressionsWithIntervalArithmetic.Value)
         throw new NotSupportedException("Interval arithmetic is not yet supported in the symbolic data analysis interpreter.");
@@ -186,7 +192,4 @@
 
       Dictionary<string, int> doubleVariableNames = dataset.DoubleVariables.Select((x, i) => new { x, i }).ToDictionary(e => e.x, e => e.i);
-      IList<double>[] columns = (from v in doubleVariableNames.Keys
-                                 select dataset.GetReadOnlyDoubleValues(v))
-                                .ToArray();
 
       for (int i = 0; i < code.Length; i++) {
@@ -208,20 +211,43 @@
       }
       var state = new InterpreterState(code);
-
       Type[] methodArgs = { typeof(int), typeof(IList<double>[]) };
-      DynamicMethod testFun = new DynamicMethod("TestFun", typeof(double), methodArgs, typeof(SymbolicDataAnalysisExpressionTreeILEmittingInterpreter).Module);
-
-      ILGenerator il = testFun.GetILGenerator();
-      CompileInstructions(il, state, dataset);
-      il.Emit(System.Reflection.Emit.OpCodes.Conv_R8);
-      il.Emit(System.Reflection.Emit.OpCodes.Ret);
-      var function = (CompiledFunction)testFun.CreateDelegate(typeof(CompiledFunction));
-
-      foreach (var row in rows) {
-        yield return function(row, columns);
-      }
-    }
-    public IEnumerable<IEnumerable<IEnumerable<double>>> GetSymbolicExpressionTreeValues(ISymbolicExpressionTree tree, Dataset dataset, string[] targetVariables, IEnumerable<int> rows, int horizon) {
-      throw new NotImplementedException();
+
+      CompiledFunction[] function = new CompiledFunction[targetVariables.Length];
+      for (int i = 0; i < function.Length; i++) {
+        DynamicMethod testFun = new DynamicMethod("TestFun", typeof(double), methodArgs, typeof(SymbolicDataAnalysisExpressionTreeILEmittingInterpreter).Module);
+        ILGenerator il = testFun.GetILGenerator();
+        CompileInstructions(il, state, dataset);
+        il.Emit(System.Reflection.Emit.OpCodes.Conv_R8);
+        il.Emit(System.Reflection.Emit.OpCodes.Ret);
+        function[i] = (CompiledFunction)testFun.CreateDelegate(typeof(CompiledFunction));
+      }
+      int nComponents = tree.Root.GetSubtree(0).SubtreeCount;
+      // produce a n-step forecast for each target variable for all rows
+      var values = doubleVariableNames.Keys
+        .Select(v => targetVariables.Contains(v) ?
+          (IList<double>)dataset.GetDoubleValues(v).ToList() :
+          dataset.GetReadOnlyDoubleValues(v))
+        .Concat(new List<double>[] { Enumerable.Repeat(0.0, dataset.Rows).ToList() }) // append list for calculated target variable
+        .ToArray();
+      doubleVariableNames.Add("#NOTHING#", values.Count() - 1);
+      foreach (var rowEnum in rows) {
+        int row = rowEnum;
+        foreach (var horizonRow in Enumerable.Range(row, horizon)) {
+          for (int i = 0; i < nComponents; i++) {
+            var componentProg = function[i](horizonRow, values);
+            // set cachedValues for prognosis of future values
+            values[doubleVariableNames[targetVariables[i]]][horizonRow] = componentProg;
+          }
+        }
+
+        yield return from component in Enumerable.Range(0, nComponents)
+                     select from horizonRow in Enumerable.Range(row, horizon)
+                            select values[doubleVariableNames[targetVariables[component]]][horizonRow];
+        // reset start value
+        foreach (var v in targetVariables) {
+          if (v != "#NOTHING#")
+            values[doubleVariableNames[v]][row] = dataset.GetDoubleValue(v, row);
+        }
+      }
     }
 
Index: /branches/HeuristicLab.TimeSeries/HeuristicLab.Problems.DataAnalysis.Views/3.4/HeuristicLab.Problems.DataAnalysis.Views-3.4.csproj
===================================================================
--- /branches/HeuristicLab.TimeSeries/HeuristicLab.Problems.DataAnalysis.Views/3.4/HeuristicLab.Problems.DataAnalysis.Views-3.4.csproj	(revision 7128)
+++ /branches/HeuristicLab.TimeSeries/HeuristicLab.Problems.DataAnalysis.Views/3.4/HeuristicLab.Problems.DataAnalysis.Views-3.4.csproj	(revision 7129)
@@ -257,4 +257,10 @@
       <DependentUpon>RegressionSolutionScatterPlotView.cs</DependentUpon>
     </Compile>
+    <Compile Include="TimeSeriesPrognosis\TimeSeriesPrognosisSolutionLineChartView.cs">
+      <SubType>UserControl</SubType>
+    </Compile>
+    <Compile Include="TimeSeriesPrognosis\TimeSeriesPrognosisSolutionLineChartView.Designer.cs">
+      <DependentUpon>TimeSeriesPrognosisSolutionLineChartView.cs</DependentUpon>
+    </Compile>
     <Compile Include="TimeSeriesPrognosis\TimeSeriesPrognosisSolutionPrognosedValuesView.cs">
       <SubType>UserControl</SubType>
@@ -378,5 +384,9 @@
     </BootstrapperPackage>
   </ItemGroup>
-  <ItemGroup />
+  <ItemGroup>
+    <EmbeddedResource Include="TimeSeriesPrognosis\TimeSeriesPrognosisSolutionLineChartView.resx">
+      <DependentUpon>TimeSeriesPrognosisSolutionLineChartView.cs</DependentUpon>
+    </EmbeddedResource>
+  </ItemGroup>
   <Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
   <!-- To modify your build process, add your task inside one of the targets below and uncomment it. 
Index: /branches/HeuristicLab.TimeSeries/HeuristicLab.Problems.DataAnalysis.Views/3.4/TimeSeriesPrognosis/TimeSeriesPrognosisSolutionLineChartView.Designer.cs
===================================================================
--- /branches/HeuristicLab.TimeSeries/HeuristicLab.Problems.DataAnalysis.Views/3.4/TimeSeriesPrognosis/TimeSeriesPrognosisSolutionLineChartView.Designer.cs	(revision 7128)
+++ /branches/HeuristicLab.TimeSeries/HeuristicLab.Problems.DataAnalysis.Views/3.4/TimeSeriesPrognosis/TimeSeriesPrognosisSolutionLineChartView.Designer.cs	(revision 7129)
@@ -44,7 +44,10 @@
     /// </summary>
     private void InitializeComponent() {
-      System.Windows.Forms.DataVisualization.Charting.ChartArea chartArea1 = new System.Windows.Forms.DataVisualization.Charting.ChartArea();
-      System.Windows.Forms.DataVisualization.Charting.Legend legend1 = new System.Windows.Forms.DataVisualization.Charting.Legend();
+      System.Windows.Forms.DataVisualization.Charting.ChartArea chartArea2 = new System.Windows.Forms.DataVisualization.Charting.ChartArea();
+      System.Windows.Forms.DataVisualization.Charting.Legend legend2 = new System.Windows.Forms.DataVisualization.Charting.Legend();
       this.chart = new HeuristicLab.Visualization.ChartControlsExtensions.EnhancedChart();
+      this.targetVariableComboBox = new System.Windows.Forms.ComboBox();
+      this.label = new System.Windows.Forms.Label();
+      this.prognosedValuesCheckbox = new System.Windows.Forms.CheckBox();
       ((System.ComponentModel.ISupportInitialize)(this.chart)).BeginInit();
       this.SuspendLayout();
@@ -52,14 +55,16 @@
       // chart
       // 
-      chartArea1.Name = "ChartArea";
-      this.chart.ChartAreas.Add(chartArea1);
-      this.chart.Dock = System.Windows.Forms.DockStyle.Fill;
-      legend1.Alignment = System.Drawing.StringAlignment.Center;
-      legend1.Docking = System.Windows.Forms.DataVisualization.Charting.Docking.Top;
-      legend1.Name = "Default";
-      this.chart.Legends.Add(legend1);
-      this.chart.Location = new System.Drawing.Point(0, 0);
+      this.chart.Anchor = ((System.Windows.Forms.AnchorStyles)((((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom)
+                  | System.Windows.Forms.AnchorStyles.Left)
+                  | System.Windows.Forms.AnchorStyles.Right)));
+      chartArea2.Name = "ChartArea";
+      this.chart.ChartAreas.Add(chartArea2);
+      legend2.Alignment = System.Drawing.StringAlignment.Center;
+      legend2.Docking = System.Windows.Forms.DataVisualization.Charting.Docking.Top;
+      legend2.Name = "Default";
+      this.chart.Legends.Add(legend2);
+      this.chart.Location = new System.Drawing.Point(0, 31);
       this.chart.Name = "chart";
-      this.chart.Size = new System.Drawing.Size(358, 225);
+      this.chart.Size = new System.Drawing.Size(388, 194);
       this.chart.TabIndex = 0;
       this.chart.CustomizeLegend += new System.EventHandler<System.Windows.Forms.DataVisualization.Charting.CustomizeLegendEventArgs>(this.chart_CustomizeLegend);
@@ -68,4 +73,35 @@
       this.chart.MouseMove += new System.Windows.Forms.MouseEventHandler(this.chart_MouseMove);
       // 
+      // targetVariableComboBox
+      // 
+      this.targetVariableComboBox.FormattingEnabled = true;
+      this.targetVariableComboBox.Location = new System.Drawing.Point(91, 4);
+      this.targetVariableComboBox.Name = "targetVariableComboBox";
+      this.targetVariableComboBox.Size = new System.Drawing.Size(173, 21);
+      this.targetVariableComboBox.TabIndex = 1;
+      this.targetVariableComboBox.SelectedIndexChanged += new System.EventHandler(this.targetVariableComboBox_SelectedIndexChanged);
+      // 
+      // label
+      // 
+      this.label.AutoSize = true;
+      this.label.Location = new System.Drawing.Point(4, 7);
+      this.label.Name = "label";
+      this.label.Size = new System.Drawing.Size(81, 13);
+      this.label.TabIndex = 2;
+      this.label.Text = "Target variable:";
+      // 
+      // prognosedValuesCheckbox
+      // 
+      this.prognosedValuesCheckbox.AutoSize = true;
+      this.prognosedValuesCheckbox.Checked = true;
+      this.prognosedValuesCheckbox.CheckState = System.Windows.Forms.CheckState.Checked;
+      this.prognosedValuesCheckbox.Location = new System.Drawing.Point(271, 7);
+      this.prognosedValuesCheckbox.Name = "prognosedValuesCheckbox";
+      this.prognosedValuesCheckbox.Size = new System.Drawing.Size(112, 17);
+      this.prognosedValuesCheckbox.TabIndex = 3;
+      this.prognosedValuesCheckbox.Text = "Prognosed Values";
+      this.prognosedValuesCheckbox.UseVisualStyleBackColor = true;
+      this.prognosedValuesCheckbox.CheckedChanged += new System.EventHandler(this.prognosedValuesCheckbox_CheckedChanged);
+      // 
       // TimeSeriesPrognosisSolutionLineChartView
       // 
@@ -73,9 +109,13 @@
       this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F);
       this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
+      this.Controls.Add(this.prognosedValuesCheckbox);
+      this.Controls.Add(this.label);
+      this.Controls.Add(this.targetVariableComboBox);
       this.Controls.Add(this.chart);
       this.Name = "TimeSeriesPrognosisSolutionLineChartView";
-      this.Size = new System.Drawing.Size(358, 225);
+      this.Size = new System.Drawing.Size(388, 225);
       ((System.ComponentModel.ISupportInitialize)(this.chart)).EndInit();
       this.ResumeLayout(false);
+      this.PerformLayout();
 
     }
@@ -84,4 +124,7 @@
 
     private HeuristicLab.Visualization.ChartControlsExtensions.EnhancedChart chart;
+    private System.Windows.Forms.ComboBox targetVariableComboBox;
+    private System.Windows.Forms.Label label;
+    private System.Windows.Forms.CheckBox prognosedValuesCheckbox;
   }
 }
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 7128)
+++ /branches/HeuristicLab.TimeSeries/HeuristicLab.Problems.DataAnalysis.Views/3.4/TimeSeriesPrognosis/TimeSeriesPrognosisSolutionLineChartView.cs	(revision 7129)
@@ -36,4 +36,5 @@
     private const string PROGNOSEDVALUES_TEST_SERIES_NAME = "Prognosed Values (test)";
     private const string PROGNOSEDVALUES_ALL_SERIES_NAME = "Prognosed Values (all samples)";
+    private string prevTargetVariable;
 
     public new ITimeSeriesPrognosisSolution Content {
@@ -57,4 +58,17 @@
     }
 
+    private void UpdateTargetVariables() {
+      // populate combobox
+      targetVariableComboBox.Items.Clear();
+      if (Content != null) {
+        foreach (var targetVariable in Content.ProblemData.TargetVariables)
+          targetVariableComboBox.Items.Add(targetVariable);
+
+        targetVariableComboBox.SelectedIndex = 0;
+      }
+    }
+
+
+
     private void RedrawChart() {
       this.chart.Series.Clear();
@@ -62,15 +76,25 @@
         this.chart.ChartAreas[0].AxisX.Minimum = 0;
         this.chart.ChartAreas[0].AxisX.Maximum = Content.ProblemData.Dataset.Rows - 1;
+        string targetVariable = (string)targetVariableComboBox.SelectedItem;
+        int varIndex = Content.ProblemData.TargetVariables.ToList().IndexOf(targetVariable);
 
         this.chart.Series.Add(TARGETVARIABLE_SERIES_NAME);
-        this.chart.Series[TARGETVARIABLE_SERIES_NAME].LegendText = Content.ProblemData.TargetVariable;
+        this.chart.Series[TARGETVARIABLE_SERIES_NAME].LegendText = targetVariable;
         this.chart.Series[TARGETVARIABLE_SERIES_NAME].ChartType = SeriesChartType.FastLine;
         this.chart.Series[TARGETVARIABLE_SERIES_NAME].Points.DataBindXY(Enumerable.Range(0, Content.ProblemData.Dataset.Rows).ToArray(),
-          Content.ProblemData.Dataset.GetDoubleValues(Content.ProblemData.TargetVariable).ToArray());
+          Content.ProblemData.Dataset.GetDoubleValues(targetVariable).ToArray());
 
         this.chart.Series.Add(PROGNOSEDVALUES_TRAINING_SERIES_NAME);
         this.chart.Series[PROGNOSEDVALUES_TRAINING_SERIES_NAME].LegendText = PROGNOSEDVALUES_TRAINING_SERIES_NAME;
         this.chart.Series[PROGNOSEDVALUES_TRAINING_SERIES_NAME].ChartType = SeriesChartType.FastLine;
-        this.chart.Series[PROGNOSEDVALUES_TRAINING_SERIES_NAME].Points.DataBindXY(Content.ProblemData.TrainingIndizes.ToArray(), Content.PrognosedTrainingValues.ToArray());
+        if (prognosedValuesCheckbox.Checked) {
+          this.chart.Series[PROGNOSEDVALUES_TRAINING_SERIES_NAME].Points
+            .DataBindXY(Content.ProblemData.TrainingIndizes.ToArray(),
+                        Content.PrognosedTrainingValues.ElementAt(varIndex).ToArray());
+        } else {
+          this.chart.Series[PROGNOSEDVALUES_TRAINING_SERIES_NAME].Points
+            .DataBindXY(Content.ProblemData.TrainingIndizes.ToArray(),
+                        Content.GetPrognosedValues(Content.ProblemData.TrainingIndizes, 1).Select(v => v.ElementAt(varIndex).First()).ToArray());
+        }
         this.chart.Series[PROGNOSEDVALUES_TRAINING_SERIES_NAME].Tag = Content;
         this.chart.DataManipulator.InsertEmptyPoints(1, IntervalType.Number, PROGNOSEDVALUES_TRAINING_SERIES_NAME);
@@ -82,21 +106,15 @@
         this.chart.Series[PROGNOSEDVALUES_TEST_SERIES_NAME].LegendText = PROGNOSEDVALUES_TEST_SERIES_NAME;
         this.chart.Series[PROGNOSEDVALUES_TEST_SERIES_NAME].ChartType = SeriesChartType.FastLine;
-        this.chart.Series[PROGNOSEDVALUES_TEST_SERIES_NAME].Points.DataBindXY(Content.ProblemData.TestIndizes.ToArray(), Content.PrognosedTestValues.ToArray());
+        if (prognosedValuesCheckbox.Checked) {
+          this.chart.Series[PROGNOSEDVALUES_TEST_SERIES_NAME].Points
+            .DataBindXY(Content.ProblemData.TestIndizes.ToArray(),
+                        Content.PrognosedTestValues.ElementAt(varIndex).ToArray());
+        } else {
+          this.chart.Series[PROGNOSEDVALUES_TEST_SERIES_NAME].Points
+            .DataBindXY(Content.ProblemData.TestIndizes.ToArray(),
+                        Content.GetPrognosedValues(Content.ProblemData.TestIndizes, 1).Select(
+                          v => v.ElementAt(varIndex).First()).ToArray());
+        }
         this.chart.Series[PROGNOSEDVALUES_TEST_SERIES_NAME].Tag = Content;
-
-
-        int[] allIndizes = Enumerable.Range(0, Content.ProblemData.Dataset.Rows).Except(Content.ProblemData.TrainingIndizes).Except(Content.ProblemData.TestIndizes).ToArray();
-        var estimatedValues = Content.PrognosedValues.ToArray();
-        List<double> allEstimatedValues = allIndizes.Select(index => estimatedValues[index]).ToList();
-
-        this.chart.Series.Add(PROGNOSEDVALUES_ALL_SERIES_NAME);
-        this.chart.Series[PROGNOSEDVALUES_ALL_SERIES_NAME].LegendText = PROGNOSEDVALUES_ALL_SERIES_NAME;
-        this.chart.Series[PROGNOSEDVALUES_ALL_SERIES_NAME].ChartType = SeriesChartType.FastLine;
-        this.chart.Series[PROGNOSEDVALUES_ALL_SERIES_NAME].Points.DataBindXY(allIndizes, allEstimatedValues);
-        this.chart.Series[PROGNOSEDVALUES_ALL_SERIES_NAME].Tag = Content;
-        this.chart.DataManipulator.InsertEmptyPoints(1, IntervalType.Number, PROGNOSEDVALUES_ALL_SERIES_NAME);
-        this.chart.Series[PROGNOSEDVALUES_TRAINING_SERIES_NAME].EmptyPointStyle.BorderWidth = 0;
-        this.chart.Series[PROGNOSEDVALUES_TRAINING_SERIES_NAME].EmptyPointStyle.MarkerStyle = MarkerStyle.None;
-        this.ToggleSeriesData(this.chart.Series[PROGNOSEDVALUES_ALL_SERIES_NAME]);
 
         UpdateCursorInterval();
@@ -130,10 +148,18 @@
     protected override void OnContentChanged() {
       base.OnContentChanged();
+      UpdateTargetVariables();
+    }
+
+    private void Content_ProblemDataChanged(object sender, EventArgs e) {
+      UpdateTargetVariables();
+    }
+    private void Content_ModelChanged(object sender, EventArgs e) {
       RedrawChart();
     }
-    private void Content_ProblemDataChanged(object sender, EventArgs e) {
+
+    private void targetVariableComboBox_SelectedIndexChanged(object sender, EventArgs e) {
       RedrawChart();
     }
-    private void Content_ModelChanged(object sender, EventArgs e) {
+    private void prognosedValuesCheckbox_CheckedChanged(object sender, EventArgs e) {
       RedrawChart();
     }
@@ -207,21 +233,18 @@
         }
       } else if (Content != null) {
-        string targetVariableName = Content.ProblemData.TargetVariable;
+        string targetVariable = (string)targetVariableComboBox.SelectedItem;
+        int varIndex = Content.ProblemData.TargetVariables.ToList().IndexOf(targetVariable);
+
 
         IEnumerable<int> indizes = null;
         IEnumerable<double> predictedValues = null;
         switch (series.Name) {
-          case PROGNOSEDVALUES_ALL_SERIES_NAME:
-            indizes = Enumerable.Range(0, Content.ProblemData.Dataset.Rows).Except(Content.ProblemData.TrainingIndizes).Except(Content.ProblemData.TestIndizes).ToArray();
-            var estimatedValues = Content.PrognosedValues.ToArray();
-            predictedValues = indizes.Select(index => estimatedValues[index]).ToList();
-            break;
           case PROGNOSEDVALUES_TRAINING_SERIES_NAME:
             indizes = Content.ProblemData.TrainingIndizes.ToArray();
-            predictedValues = Content.PrognosedTrainingValues.ToArray();
+            predictedValues = Content.PrognosedTrainingValues.ElementAt(varIndex).ToArray();
             break;
           case PROGNOSEDVALUES_TEST_SERIES_NAME:
             indizes = Content.ProblemData.TestIndizes.ToArray();
-            predictedValues = Content.PrognosedTestValues.ToArray();
+            predictedValues = Content.PrognosedTestValues.ElementAt(varIndex).ToArray();
             break;
         }
@@ -255,4 +278,5 @@
       e.LegendItems[3].Cells[1].ForeColor = this.chart.Series[PROGNOSEDVALUES_ALL_SERIES_NAME].Points.Count == 0 ? Color.Gray : Color.Black;
     }
+
   }
 }
Index: /branches/HeuristicLab.TimeSeries/HeuristicLab.Problems.DataAnalysis.Views/3.4/TimeSeriesPrognosis/TimeSeriesPrognosisSolutionLineChartView.resx
===================================================================
--- /branches/HeuristicLab.TimeSeries/HeuristicLab.Problems.DataAnalysis.Views/3.4/TimeSeriesPrognosis/TimeSeriesPrognosisSolutionLineChartView.resx	(revision 7129)
+++ /branches/HeuristicLab.TimeSeries/HeuristicLab.Problems.DataAnalysis.Views/3.4/TimeSeriesPrognosis/TimeSeriesPrognosisSolutionLineChartView.resx	(revision 7129)
@@ -0,0 +1,120 @@
+﻿<?xml version="1.0" encoding="utf-8"?>
+<root>
+  <!-- 
+    Microsoft ResX Schema 
+    
+    Version 2.0
+    
+    The primary goals of this format is to allow a simple XML format 
+    that is mostly human readable. The generation and parsing of the 
+    various data types are done through the TypeConverter classes 
+    associated with the data types.
+    
+    Example:
+    
+    ... ado.net/XML headers & schema ...
+    <resheader name="resmimetype">text/microsoft-resx</resheader>
+    <resheader name="version">2.0</resheader>
+    <resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>
+    <resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>
+    <data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data>
+    <data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data>
+    <data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64">
+        <value>[base64 mime encoded serialized .NET Framework object]</value>
+    </data>
+    <data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
+        <value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>
+        <comment>This is a comment</comment>
+    </data>
+                
+    There are any number of "resheader" rows that contain simple 
+    name/value pairs.
+    
+    Each data row contains a name, and value. The row also contains a 
+    type or mimetype. Type corresponds to a .NET class that support 
+    text/value conversion through the TypeConverter architecture. 
+    Classes that don't support this are serialized and stored with the 
+    mimetype set.
+    
+    The mimetype is used for serialized objects, and tells the 
+    ResXResourceReader how to depersist the object. This is currently not 
+    extensible. For a given mimetype the value must be set accordingly:
+    
+    Note - application/x-microsoft.net.object.binary.base64 is the format 
+    that the ResXResourceWriter will generate, however the reader can 
+    read any of the formats listed below.
+    
+    mimetype: application/x-microsoft.net.object.binary.base64
+    value   : The object must be serialized with 
+            : System.Runtime.Serialization.Formatters.Binary.BinaryFormatter
+            : and then encoded with base64 encoding.
+    
+    mimetype: application/x-microsoft.net.object.soap.base64
+    value   : The object must be serialized with 
+            : System.Runtime.Serialization.Formatters.Soap.SoapFormatter
+            : and then encoded with base64 encoding.
+
+    mimetype: application/x-microsoft.net.object.bytearray.base64
+    value   : The object must be serialized into a byte array 
+            : using a System.ComponentModel.TypeConverter
+            : and then encoded with base64 encoding.
+    -->
+  <xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
+    <xsd:import namespace="http://www.w3.org/XML/1998/namespace" />
+    <xsd:element name="root" msdata:IsDataSet="true">
+      <xsd:complexType>
+        <xsd:choice maxOccurs="unbounded">
+          <xsd:element name="metadata">
+            <xsd:complexType>
+              <xsd:sequence>
+                <xsd:element name="value" type="xsd:string" minOccurs="0" />
+              </xsd:sequence>
+              <xsd:attribute name="name" use="required" type="xsd:string" />
+              <xsd:attribute name="type" type="xsd:string" />
+              <xsd:attribute name="mimetype" type="xsd:string" />
+              <xsd:attribute ref="xml:space" />
+            </xsd:complexType>
+          </xsd:element>
+          <xsd:element name="assembly">
+            <xsd:complexType>
+              <xsd:attribute name="alias" type="xsd:string" />
+              <xsd:attribute name="name" type="xsd:string" />
+            </xsd:complexType>
+          </xsd:element>
+          <xsd:element name="data">
+            <xsd:complexType>
+              <xsd:sequence>
+                <xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
+                <xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
+              </xsd:sequence>
+              <xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1" />
+              <xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
+              <xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
+              <xsd:attribute ref="xml:space" />
+            </xsd:complexType>
+          </xsd:element>
+          <xsd:element name="resheader">
+            <xsd:complexType>
+              <xsd:sequence>
+                <xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
+              </xsd:sequence>
+              <xsd:attribute name="name" type="xsd:string" use="required" />
+            </xsd:complexType>
+          </xsd:element>
+        </xsd:choice>
+      </xsd:complexType>
+    </xsd:element>
+  </xsd:schema>
+  <resheader name="resmimetype">
+    <value>text/microsoft-resx</value>
+  </resheader>
+  <resheader name="version">
+    <value>2.0</value>
+  </resheader>
+  <resheader name="reader">
+    <value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
+  </resheader>
+  <resheader name="writer">
+    <value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
+  </resheader>
+</root>
Index: /branches/HeuristicLab.TimeSeries/HeuristicLab.Tests/HeuristicLab.Problems.DataAnalysis.Symbolic-3.4/SymbolicDataAnalysisExpressionTreeInterpreterTest.cs
===================================================================
--- /branches/HeuristicLab.TimeSeries/HeuristicLab.Tests/HeuristicLab.Problems.DataAnalysis.Symbolic-3.4/SymbolicDataAnalysisExpressionTreeInterpreterTest.cs	(revision 7128)
+++ /branches/HeuristicLab.TimeSeries/HeuristicLab.Tests/HeuristicLab.Problems.DataAnalysis.Symbolic-3.4/SymbolicDataAnalysisExpressionTreeInterpreterTest.cs	(revision 7129)
@@ -24,4 +24,5 @@
 using System.Globalization;
 using System.Linq;
+using HeuristicLab.Encodings.IntegerVectorEncoding;
 using HeuristicLab.Encodings.SymbolicExpressionTreeEncoding;
 using HeuristicLab.Random;
@@ -339,4 +340,32 @@
       Evaluate(interpreter, ds, "(lag -1.0 (* (lagVariable 1.0 a 1) (lagVariable 1.0 b 2)))", 1, ds.GetDoubleValue("A", 1) * ds.GetDoubleValue("B", 2));
       Evaluate(interpreter, ds, "(lag -2.0 3.0)", 1, 3.0);
+
+      // prognosis
+      Evaluate(interpreter, ds, "(lagVariable 1.0 a -1)", new string[] { "A" }, Enumerable.Range(1, 1), 3, new[] { new double[] { 1.0, 1.0, 1.0 } });
+      Evaluate(interpreter, ds, "(lagVariable 2.0 a -1)", new string[] { "A" }, Enumerable.Range(1, 1), 3, new[] { new double[] { 2.0, 4.0, 8.0 } });
+      Evaluate(interpreter, ds, "(lagVariable 1.0 a -2)", new string[] { "A" }, Enumerable.Range(2, 1), 4, new[] { new double[] { 1.0, 2.0, 1.0, 2.0 } });
+
+      // multi-variate
+      Evaluate(interpreter, ds, @"(PROG 
+                                    (MAIN (lagVariable 1.0 a -1) (lagVariable 1.0 b -1)))", new string[] { "A", "B" }, Enumerable.Range(1, 2), 3,
+      new[] { new[] { 1.0, 1.0, 1.0 }, new[] { 1.0, 1.0, 1.0 } },
+      new[] { new[] { 2.0, 2.0, 2.0 }, new[] { 2.0, 2.0, 2.0 } }
+        );
+
+      //1.0, 1.0
+      //2.0, 2.0
+      //1.0, 2.0
+      //1.0, 1.0
+      //2.0, 2.0
+      //1.0, 2.0
+      //1.0, 1.0
+      //2.0, 2.0
+      //1.0, 2.0
+      Evaluate(interpreter, ds, @"(PROG 
+                                     (MAIN (lagVariable 2.0 a -2) (lagVariable 1.0 a -1)))", new string[] { "A", "B" }, Enumerable.Range(2, 3), 4,
+      new[] { new[] { 2.0, 4.0, 4.0, 8.0 }, new[] { 2.0, 2.0, 4.0, 4.0 } },
+      new[] { new[] { 4.0, 2.0, 8.0, 4.0 }, new[] { 1.0, 4.0, 2.0, 8.0 } },
+      new[] { new[] { 2.0, 2.0, 4.0, 4.0 }, new[] { 1.0, 2.0, 2.0, 4.0 } }
+        );
     }
 
@@ -351,4 +380,25 @@
       Assert.AreEqual(expected, actual, 1.0E-12, expr);
     }
+    private void Evaluate(ISymbolicDataAnalysisExpressionTreeInterpreter interpreter, Dataset ds, string expr, string[] targetVariables, IEnumerable<int> rows, int horizon, params IEnumerable<IEnumerable<double>>[] expected) {
+      var importer = new SymbolicExpressionImporter();
+      ISymbolicExpressionTree tree = importer.Import(expr);
+
+      var allPrognosis = interpreter.GetSymbolicExpressionTreeValues(tree, ds, targetVariables, rows, horizon);
+      int i = 0;
+      foreach (var actual in allPrognosis) {
+        var actualEnumerator = actual.GetEnumerator();
+        var expectedEnumerator = expected[i].GetEnumerator();
+        while (actualEnumerator.MoveNext() & expectedEnumerator.MoveNext()) {
+          var aEnumerator = actualEnumerator.Current.GetEnumerator();
+          var eEnumerator = expectedEnumerator.Current.GetEnumerator();
+          while (aEnumerator.MoveNext() & eEnumerator.MoveNext()) {
+            Assert.IsFalse(double.IsNaN(aEnumerator.Current) && !double.IsNaN(eEnumerator.Current));
+            Assert.IsFalse(!double.IsNaN(aEnumerator.Current) && double.IsNaN(eEnumerator.Current));
+            Assert.AreEqual(eEnumerator.Current, aEnumerator.Current, 1.0E-12, expr);
+          }
+        }
+        i++;
+      }
+    }
   }
 }
Index: /branches/HeuristicLab.TimeSeries/HeuristicLab.Tests/HeuristicLab.Problems.DataAnalysis.Symbolic-3.4/SymbolicExpressionImporter.cs
===================================================================
--- /branches/HeuristicLab.TimeSeries/HeuristicLab.Tests/HeuristicLab.Problems.DataAnalysis.Symbolic-3.4/SymbolicExpressionImporter.cs	(revision 7128)
+++ /branches/HeuristicLab.TimeSeries/HeuristicLab.Tests/HeuristicLab.Problems.DataAnalysis.Symbolic-3.4/SymbolicExpressionImporter.cs	(revision 7129)
@@ -77,5 +77,6 @@
       ISymbolicExpressionTreeNode root = programRootSymbol.CreateTreeNode();
       ISymbolicExpressionTreeNode start = startSymbol.CreateTreeNode();
-      ISymbolicExpressionTreeNode mainBranch = ParseSexp(new Queue<Token>(GetTokenStream(str)));
+      var q = new Queue<Token>(GetTokenStream(str));
+      ISymbolicExpressionTreeNode mainBranch = ParseSexp(q);
       if (mainBranch.Symbol is ProgramRootSymbol) {
         // when a root symbol was parsed => use main branch as root
