Index: /trunk/sources/HeuristicLab.GP.Boolean/3.3/BooleanTreeInterpreter.cs
===================================================================
--- /trunk/sources/HeuristicLab.GP.Boolean/3.3/BooleanTreeInterpreter.cs	(revision 2327)
+++ /trunk/sources/HeuristicLab.GP.Boolean/3.3/BooleanTreeInterpreter.cs	(revision 2328)
@@ -27,4 +27,5 @@
 using System.Xml;
 using System.Diagnostics;
+using HeuristicLab.Common;
 using HeuristicLab.Data;
 using HeuristicLab.GP.Interfaces;
@@ -67,5 +68,5 @@
             var varNode = (VariableFunctionTree)t;
             int index = dataset.GetVariableIndex(varNode.VariableName);
-            return !IsAlmost(dataset.GetValue(currentRow, index), 0.0);
+            return !dataset.GetValue(currentRow, index).IsAlmost(0.0);
           }
         case SymbolTable.UNKNOWN:
@@ -74,8 +75,4 @@
       }
     }
-
-    private bool IsAlmost(double x, double y) {
-      return Math.Abs(x - y) < EPSILON;
-    }
   }
 }
Index: /trunk/sources/HeuristicLab.GP.Boolean/3.3/HeuristicLab.GP.Boolean-3.3.csproj
===================================================================
--- /trunk/sources/HeuristicLab.GP.Boolean/3.3/HeuristicLab.GP.Boolean-3.3.csproj	(revision 2327)
+++ /trunk/sources/HeuristicLab.GP.Boolean/3.3/HeuristicLab.GP.Boolean-3.3.csproj	(revision 2328)
@@ -100,4 +100,8 @@
   </ItemGroup>
   <ItemGroup>
+    <ProjectReference Include="..\..\HeuristicLab.Common\3.2\HeuristicLab.Common-3.2.csproj">
+      <Project>{1FC004FC-59AF-4249-B1B6-FF25873A20E4}</Project>
+      <Name>HeuristicLab.Common-3.2</Name>
+    </ProjectReference>
     <ProjectReference Include="..\..\HeuristicLab.Core\3.2\HeuristicLab.Core-3.2.csproj">
       <Project>{F43B59AB-2B8C-4570-BC1E-15592086517C}</Project>
Index: /trunk/sources/HeuristicLab.GP.Boolean/3.3/HeuristicLabGPBooleanPlugin.cs
===================================================================
--- /trunk/sources/HeuristicLab.GP.Boolean/3.3/HeuristicLabGPBooleanPlugin.cs	(revision 2327)
+++ /trunk/sources/HeuristicLab.GP.Boolean/3.3/HeuristicLabGPBooleanPlugin.cs	(revision 2328)
@@ -28,4 +28,5 @@
   [ClassInfo(Name = "HeuristicLab.GP.Boolean-3.3")]
   [PluginFile(Filename = "HeuristicLab.GP.Boolean-3.3.dll", Filetype = PluginFileType.Assembly)]
+  [Dependency(Dependency = "HeuristicLab.Common-3.2")]
   [Dependency(Dependency = "HeuristicLab.Core-3.2")]
   [Dependency(Dependency = "HeuristicLab.Data-3.2")]
Index: /trunk/sources/HeuristicLab.GP.StructureIdentification.Classification/3.3/ClassificationMeanSquaredErrorEvaluator.cs
===================================================================
--- /trunk/sources/HeuristicLab.GP.StructureIdentification.Classification/3.3/ClassificationMeanSquaredErrorEvaluator.cs	(revision 2327)
+++ /trunk/sources/HeuristicLab.GP.StructureIdentification.Classification/3.3/ClassificationMeanSquaredErrorEvaluator.cs	(revision 2328)
@@ -23,4 +23,5 @@
 using HeuristicLab.Core;
 using HeuristicLab.Data;
+using HeuristicLab.Common;
 
 namespace HeuristicLab.GP.StructureIdentification.Classification {
@@ -49,6 +50,6 @@
           // on the lower end and upper end only add linear error if the absolute error is larger than 1
           // the error>1.0 constraint is needed for balance because in the interval ]-1, 1[ the squared error is smaller than the absolute error
-          if ((IsEqual(original, classes[0]) && error < -1.0) ||
-            (IsEqual(original, classes[classes.Length - 1]) && error > 1.0)) {
+          if ((original.IsAlmost(classes[0]) && error < -1.0) ||
+            (original.IsAlmost(classes[classes.Length - 1]) && error > 1.0)) {
             errorsSquaredSum += Math.Abs(error); // only add linear error below the smallest class or above the largest class
           } else {
@@ -71,8 +72,4 @@
       mse.Data = errorsSquaredSum;
     }
-
-    private bool IsEqual(double x, double y) {
-      return Math.Abs(x - y) < EPSILON;
-    }
   }
 }
Index: /trunk/sources/HeuristicLab.GP.StructureIdentification.Classification/3.3/HeuristicLab.GP.StructureIdentification.Classification-3.3.csproj
===================================================================
--- /trunk/sources/HeuristicLab.GP.StructureIdentification.Classification/3.3/HeuristicLab.GP.StructureIdentification.Classification-3.3.csproj	(revision 2327)
+++ /trunk/sources/HeuristicLab.GP.StructureIdentification.Classification/3.3/HeuristicLab.GP.StructureIdentification.Classification-3.3.csproj	(revision 2328)
@@ -94,4 +94,8 @@
   </ItemGroup>
   <ItemGroup>
+    <ProjectReference Include="..\..\HeuristicLab.Common\3.2\HeuristicLab.Common-3.2.csproj">
+      <Project>{1FC004FC-59AF-4249-B1B6-FF25873A20E4}</Project>
+      <Name>HeuristicLab.Common-3.2</Name>
+    </ProjectReference>
     <ProjectReference Include="..\..\HeuristicLab.Core\3.2\HeuristicLab.Core-3.2.csproj">
       <Project>{F43B59AB-2B8C-4570-BC1E-15592086517C}</Project>
Index: /trunk/sources/HeuristicLab.GP.StructureIdentification.Classification/3.3/HeuristicLabGPClassificationPlugin.cs
===================================================================
--- /trunk/sources/HeuristicLab.GP.StructureIdentification.Classification/3.3/HeuristicLabGPClassificationPlugin.cs	(revision 2327)
+++ /trunk/sources/HeuristicLab.GP.StructureIdentification.Classification/3.3/HeuristicLabGPClassificationPlugin.cs	(revision 2328)
@@ -28,4 +28,5 @@
   [ClassInfo(Name = "HeuristicLab.GP.StructureIdentification.Classification-3.3")]
   [PluginFile(Filename = "HeuristicLab.GP.StructureIdentification.Classification-3.3.dll", Filetype = PluginFileType.Assembly)]
+  [Dependency(Dependency = "HeuristicLab.Common-3.2")]
   [Dependency(Dependency = "HeuristicLab.Core-3.2")]
   [Dependency(Dependency = "HeuristicLab.Data-3.2")]
Index: /trunk/sources/HeuristicLab.GP.StructureIdentification.Classification/3.3/MulticlassModeller.cs
===================================================================
--- /trunk/sources/HeuristicLab.GP.StructureIdentification.Classification/3.3/MulticlassModeller.cs	(revision 2327)
+++ /trunk/sources/HeuristicLab.GP.StructureIdentification.Classification/3.3/MulticlassModeller.cs	(revision 2328)
@@ -22,4 +22,5 @@
 using System;
 using System.Collections.Generic;
+using HeuristicLab.Common;
 using HeuristicLab.Core;
 using HeuristicLab.Data;
@@ -83,5 +84,5 @@
             double[] row = new double[dataset.Columns];
             double targetValue = origDataset.GetValue(k, targetVariable);
-            if (IsEqual(targetValue, classAValue)) {
+            if (targetValue.IsAlmost(classAValue)) {
               for (int l = 0; l < row.Length; l++) {
                 row[l] = origDataset.GetValue(k, l);
@@ -89,5 +90,5 @@
               row[targetVariable] = 0;
               rows.Add(row);
-            } else if (IsEqual(targetValue, classBValue)) {
+            } else if (targetValue.IsAlmost(classBValue)) {
               for (int l = 0; l < row.Length; l++) {
                 row[l] = origDataset.GetValue(k, l);
@@ -102,5 +103,5 @@
             double[] row = new double[dataset.Columns];
             double targetValue = origDataset.GetValue(k, targetVariable);
-            if (IsEqual(targetValue, classAValue)) {
+            if (targetValue.IsAlmost(classAValue)) {
               for (int l = 0; l < row.Length; l++) {
                 row[l] = origDataset.GetValue(k, l);
@@ -108,5 +109,5 @@
               row[targetVariable] = 0;
               rows.Add(row);
-            } else if (IsEqual(targetValue, classBValue)) {
+            } else if (targetValue.IsAlmost(classBValue)) {
               for (int l = 0; l < row.Length; l++) {
                 row[l] = origDataset.GetValue(k, l);
@@ -141,8 +142,4 @@
       return null;
     }
-
-    private bool IsEqual(double x, double y) {
-      return Math.Abs(x - y) < EPSILON;
-    }
   }
 }
Index: /trunk/sources/HeuristicLab.GP.StructureIdentification.Classification/3.3/MulticlassOneVsOneAnalyzer.cs
===================================================================
--- /trunk/sources/HeuristicLab.GP.StructureIdentification.Classification/3.3/MulticlassOneVsOneAnalyzer.cs	(revision 2327)
+++ /trunk/sources/HeuristicLab.GP.StructureIdentification.Classification/3.3/MulticlassOneVsOneAnalyzer.cs	(revision 2328)
@@ -25,4 +25,5 @@
 using HeuristicLab.DataAnalysis;
 using HeuristicLab.GP.Interfaces;
+using HeuristicLab.Common;
 
 namespace HeuristicLab.GP.StructureIdentification.Classification {
@@ -44,5 +45,4 @@
     private const string TREEEVALUATOR = "TreeEvaluator";
 
-    private const double EPSILON = 1E-6;
     public override string Description {
       get { return @"TASK"; }
@@ -56,6 +56,4 @@
       AddVariableInfo(new VariableInfo(CLASSAVALUE, "The original class value of the class A in the subscope", typeof(DoubleData), VariableKind.In));
       AddVariableInfo(new VariableInfo(CLASSBVALUE, "The original class value of the class B in the subscope", typeof(DoubleData), VariableKind.In));
-      AddVariableInfo(new VariableInfo(TRAININGSAMPLESSTART, "The start of training samples in the original dataset", typeof(IntData), VariableKind.In));
-      AddVariableInfo(new VariableInfo(TRAININGSAMPLESEND, "The end of training samples in the original dataset", typeof(IntData), VariableKind.In));
       AddVariableInfo(new VariableInfo(SAMPLESSTART, "The start of samples in the original dataset", typeof(IntData), VariableKind.In));
       AddVariableInfo(new VariableInfo(SAMPLESEND, "The end of samples in the original dataset", typeof(IntData), VariableKind.In));
@@ -84,5 +82,5 @@
 
         ITreeEvaluator evaluator = GetVariableValue<ITreeEvaluator>(TREEEVALUATOR, bestScope, true);
-        evaluator.PrepareForEvaluation(dataset, targetVariable, trainingSamplesStart, trainingSamplesEnd, gpModel.FunctionTree);
+        evaluator.PrepareForEvaluation(dataset, gpModel.FunctionTree);
         for(int i = 0; i < (samplesEnd - samplesStart); i++) {
           double est = evaluator.Evaluate(i + samplesStart);
@@ -110,5 +108,5 @@
           }
         }
-        if(IsEqual(originalClassValue, estimatedClassValue) && sameVotes == 0) correctlyClassified++;
+        if(originalClassValue.IsAlmost(estimatedClassValue) && sameVotes == 0) correctlyClassified++;
       }
 
@@ -122,10 +120,6 @@
     private void CastVote(int[,] votes, int sample, double votedClass, ItemList<DoubleData> classValues) {
       for(int i = 0; i < classValues.Count; i++) {
-        if(IsEqual(classValues[i].Data, votedClass)) votes[sample, i]++;
+        if(classValues[i].Data.IsAlmost(votedClass)) votes[sample, i]++;
       }
-    }
-
-    private bool IsEqual(double x, double y) {
-      return Math.Abs(x - y) < EPSILON;
     }
   }
Index: /trunk/sources/HeuristicLab.GP.StructureIdentification/3.3/BaseClasses/AlgorithmBase.cs
===================================================================
--- /trunk/sources/HeuristicLab.GP.StructureIdentification/3.3/BaseClasses/AlgorithmBase.cs	(revision 2327)
+++ /trunk/sources/HeuristicLab.GP.StructureIdentification/3.3/BaseClasses/AlgorithmBase.cs	(revision 2328)
@@ -33,4 +33,5 @@
 using HeuristicLab.Random;
 using HeuristicLab.Selection;
+using HeuristicLab.Operators.Programmable;
 
 namespace HeuristicLab.GP.StructureIdentification {
@@ -75,5 +76,5 @@
         if (!engine.Terminated) throw new InvalidOperationException("The algorithm is still running. Wait until the algorithm is terminated to retrieve the result.");
         if (model == null) {
-          IScope bestModelScope = engine.GlobalScope.GetVariableValue<IScope>("BestValidationSolution", false);
+          IScope bestModelScope = engine.GlobalScope.SubScopes[0];
           model = CreateGPModel(bestModelScope);
         }
@@ -140,4 +141,5 @@
 
       IOperator globalInjector = CreateGlobalInjector();
+      IOperator treeEvaluatorInjector = new HL2TreeEvaluatorInjector();
       IOperator initialization = CreateInitialization();
       IOperator funLibInjector = CreateFunctionLibraryInjector();
@@ -163,8 +165,10 @@
       seq.AddSubOperator(problemInjector);
       seq.AddSubOperator(globalInjector);
+      seq.AddSubOperator(treeEvaluatorInjector);
       seq.AddSubOperator(funLibInjector);
       seq.AddSubOperator(initialization);
       seq.AddSubOperator(mainLoop);
       seq.AddSubOperator(cleanUp);
+      seq.AddSubOperator(CreateModelAnalysisOperator());
 
       initialization.AddSubOperator(treeCreator);
@@ -179,4 +183,164 @@
       this.algorithm = seq;
       return algo;
+    }
+
+    protected internal virtual IOperator CreateModelAnalysisOperator() {
+      CombinedOperator op = new CombinedOperator();
+      SequentialProcessor seq = new SequentialProcessor();
+      SolutionExtractor extractor = new SolutionExtractor();
+      extractor.GetVariableInfo("Scope").ActualName = "BestValidationSolution";
+      SequentialSubScopesProcessor seqSubScopeProc = new SequentialSubScopesProcessor();
+      SequentialProcessor solutionProc = new SequentialProcessor();
+
+      seq.AddSubOperator(extractor);
+      seq.AddSubOperator(seqSubScopeProc);
+      seqSubScopeProc.AddSubOperator(solutionProc);
+
+      HL2TreeEvaluatorInjector evaluatorInjector = new HL2TreeEvaluatorInjector();
+      evaluatorInjector.AddVariable(new HeuristicLab.Core.Variable("PunishmentFactor", new DoubleData(1000.0)));
+      evaluatorInjector.GetVariableInfo("TreeEvaluator").ActualName = "ModelAnalysisTreeEvaluator";
+
+      #region MSE
+      MeanSquaredErrorEvaluator trainingMseEvaluator = new MeanSquaredErrorEvaluator();
+      trainingMseEvaluator.Name = "TrainingMseEvaluator";
+      trainingMseEvaluator.GetVariableInfo("TreeEvaluator").ActualName = "ModelAnalysisTreeEvaluator";
+      trainingMseEvaluator.GetVariableInfo("MSE").ActualName = "TrainingMSE";
+      trainingMseEvaluator.GetVariableInfo("SamplesStart").ActualName = "TrainingSamplesStart";
+      trainingMseEvaluator.GetVariableInfo("SamplesEnd").ActualName = "TrainingSamplesEnd";
+      MeanSquaredErrorEvaluator validationMseEvaluator = new MeanSquaredErrorEvaluator();
+      validationMseEvaluator.Name = "ValidationMseEvaluator";
+      validationMseEvaluator.GetVariableInfo("TreeEvaluator").ActualName = "ModelAnalysisTreeEvaluator";
+      validationMseEvaluator.GetVariableInfo("MSE").ActualName = "ValidationMSE";
+      validationMseEvaluator.GetVariableInfo("SamplesStart").ActualName = "ValidationSamplesStart";
+      validationMseEvaluator.GetVariableInfo("SamplesEnd").ActualName = "ValidationSamplesEnd";
+      MeanSquaredErrorEvaluator testMseEvaluator = new MeanSquaredErrorEvaluator();
+      testMseEvaluator.Name = "TestMeanSquaredErrorEvaluator";
+      testMseEvaluator.GetVariableInfo("TreeEvaluator").ActualName = "ModelAnalysisTreeEvaluator";
+      testMseEvaluator.GetVariableInfo("MSE").ActualName = "TestMSE";
+      testMseEvaluator.GetVariableInfo("SamplesStart").ActualName = "TestSamplesStart";
+      testMseEvaluator.GetVariableInfo("SamplesEnd").ActualName = "TestSamplesEnd";
+      #endregion
+      #region MAPE
+      MeanAbsolutePercentageErrorEvaluator trainingMapeEvaluator = new MeanAbsolutePercentageErrorEvaluator();
+      trainingMapeEvaluator.Name = "TrainingMapeEvaluator";
+      trainingMapeEvaluator.GetVariableInfo("TreeEvaluator").ActualName = "ModelAnalysisTreeEvaluator";
+      trainingMapeEvaluator.GetVariableInfo("MAPE").ActualName = "TrainingMAPE";
+      trainingMapeEvaluator.GetVariableInfo("SamplesStart").ActualName = "ActualTrainingSamplesStart";
+      trainingMapeEvaluator.GetVariableInfo("SamplesEnd").ActualName = "ActualTrainingSamplesEnd";
+      MeanAbsolutePercentageErrorEvaluator validationMapeEvaluator = new MeanAbsolutePercentageErrorEvaluator();
+      validationMapeEvaluator.GetVariableInfo("TreeEvaluator").ActualName = "ModelAnalysisTreeEvaluator";
+      validationMapeEvaluator.Name = "ValidationMapeEvaluator";
+      validationMapeEvaluator.GetVariableInfo("MAPE").ActualName = "ValidationMAPE";
+      validationMapeEvaluator.GetVariableInfo("SamplesStart").ActualName = "ValidationSamplesStart";
+      validationMapeEvaluator.GetVariableInfo("SamplesEnd").ActualName = "ValidationSamplesEnd";
+      MeanAbsolutePercentageErrorEvaluator testMapeEvaluator = new MeanAbsolutePercentageErrorEvaluator();
+      testMapeEvaluator.GetVariableInfo("TreeEvaluator").ActualName = "ModelAnalysisTreeEvaluator";
+      testMapeEvaluator.Name = "TestMapeEvaluator";
+      testMapeEvaluator.GetVariableInfo("MAPE").ActualName = "TestMAPE";
+      testMapeEvaluator.GetVariableInfo("SamplesStart").ActualName = "TestSamplesStart";
+      testMapeEvaluator.GetVariableInfo("SamplesEnd").ActualName = "TestSamplesEnd";
+      #endregion
+      #region MAPRE
+      MeanAbsolutePercentageOfRangeErrorEvaluator trainingMapreEvaluator = new MeanAbsolutePercentageOfRangeErrorEvaluator();
+      trainingMapreEvaluator.GetVariableInfo("TreeEvaluator").ActualName = "ModelAnalysisTreeEvaluator";
+      trainingMapreEvaluator.Name = "TrainingMapreEvaluator";
+      trainingMapreEvaluator.GetVariableInfo("MAPRE").ActualName = "TrainingMAPRE";
+      trainingMapreEvaluator.GetVariableInfo("SamplesStart").ActualName = "ActualTrainingSamplesStart";
+      trainingMapreEvaluator.GetVariableInfo("SamplesEnd").ActualName = "ActualTrainingSamplesEnd";
+      MeanAbsolutePercentageOfRangeErrorEvaluator validationMapreEvaluator = new MeanAbsolutePercentageOfRangeErrorEvaluator();
+      validationMapreEvaluator.GetVariableInfo("TreeEvaluator").ActualName = "ModelAnalysisTreeEvaluator";
+      validationMapreEvaluator.Name = "ValidationMapreEvaluator";
+      validationMapreEvaluator.GetVariableInfo("MAPRE").ActualName = "ValidationMAPRE";
+      validationMapreEvaluator.GetVariableInfo("SamplesStart").ActualName = "ValidationSamplesStart";
+      validationMapreEvaluator.GetVariableInfo("SamplesEnd").ActualName = "ValidationSamplesEnd";
+      MeanAbsolutePercentageOfRangeErrorEvaluator testMapreEvaluator = new MeanAbsolutePercentageOfRangeErrorEvaluator();
+      testMapreEvaluator.GetVariableInfo("TreeEvaluator").ActualName = "ModelAnalysisTreeEvaluator";
+      testMapreEvaluator.Name = "TestMapreEvaluator";
+      testMapreEvaluator.GetVariableInfo("MAPRE").ActualName = "TestMAPRE";
+      testMapreEvaluator.GetVariableInfo("SamplesStart").ActualName = "TestSamplesStart";
+      testMapreEvaluator.GetVariableInfo("SamplesEnd").ActualName = "TestSamplesEnd";
+      #endregion MAPRE
+      #region R2
+      CoefficientOfDeterminationEvaluator trainingR2Evaluator = new CoefficientOfDeterminationEvaluator();
+      trainingR2Evaluator.GetVariableInfo("TreeEvaluator").ActualName = "ModelAnalysisTreeEvaluator";
+      trainingR2Evaluator.Name = "TrainingR2Evaluator";
+      trainingR2Evaluator.GetVariableInfo("R2").ActualName = "TrainingR2";
+      trainingR2Evaluator.GetVariableInfo("SamplesStart").ActualName = "ActualTrainingSamplesStart";
+      trainingR2Evaluator.GetVariableInfo("SamplesEnd").ActualName = "ActualTrainingSamplesEnd";
+      CoefficientOfDeterminationEvaluator validationR2Evaluator = new CoefficientOfDeterminationEvaluator();
+      validationR2Evaluator.GetVariableInfo("TreeEvaluator").ActualName = "ModelAnalysisTreeEvaluator";
+      validationR2Evaluator.Name = "ValidationR2Evaluator";
+      validationR2Evaluator.GetVariableInfo("R2").ActualName = "ValidationR2";
+      validationR2Evaluator.GetVariableInfo("SamplesStart").ActualName = "ValidationSamplesStart";
+      validationR2Evaluator.GetVariableInfo("SamplesEnd").ActualName = "ValidationSamplesEnd";
+      CoefficientOfDeterminationEvaluator testR2Evaluator = new CoefficientOfDeterminationEvaluator();
+      testR2Evaluator.GetVariableInfo("TreeEvaluator").ActualName = "ModelAnalysisTreeEvaluator";
+      testR2Evaluator.Name = "TestR2Evaluator";
+      testR2Evaluator.GetVariableInfo("R2").ActualName = "TestR2";
+      testR2Evaluator.GetVariableInfo("SamplesStart").ActualName = "TestSamplesStart";
+      testR2Evaluator.GetVariableInfo("SamplesEnd").ActualName = "TestSamplesEnd";
+      #endregion
+      #region VAF
+      VarianceAccountedForEvaluator trainingVAFEvaluator = new VarianceAccountedForEvaluator();
+      trainingVAFEvaluator.GetVariableInfo("TreeEvaluator").ActualName = "ModelAnalysisTreeEvaluator";
+      trainingVAFEvaluator.Name = "TrainingVAFEvaluator";
+      trainingVAFEvaluator.GetVariableInfo("VAF").ActualName = "TrainingVAF";
+      trainingVAFEvaluator.GetVariableInfo("SamplesStart").ActualName = "ActualTrainingSamplesStart";
+      trainingVAFEvaluator.GetVariableInfo("SamplesEnd").ActualName = "ActualTrainingSamplesEnd";
+      VarianceAccountedForEvaluator validationVAFEvaluator = new VarianceAccountedForEvaluator();
+      validationVAFEvaluator.GetVariableInfo("TreeEvaluator").ActualName = "ModelAnalysisTreeEvaluator";
+      validationVAFEvaluator.Name = "ValidationVAFEvaluator";
+      validationVAFEvaluator.GetVariableInfo("VAF").ActualName = "ValidationVAF";
+      validationVAFEvaluator.GetVariableInfo("SamplesStart").ActualName = "ValidationSamplesStart";
+      validationVAFEvaluator.GetVariableInfo("SamplesEnd").ActualName = "ValidationSamplesEnd";
+      VarianceAccountedForEvaluator testVAFEvaluator = new VarianceAccountedForEvaluator();
+      testVAFEvaluator.GetVariableInfo("TreeEvaluator").ActualName = "ModelAnalysisTreeEvaluator";
+      testVAFEvaluator.Name = "TestVAFEvaluator";
+      testVAFEvaluator.GetVariableInfo("VAF").ActualName = "TestVAF";
+      testVAFEvaluator.GetVariableInfo("SamplesStart").ActualName = "TestSamplesStart";
+      testVAFEvaluator.GetVariableInfo("SamplesEnd").ActualName = "TestSamplesEnd";
+      #endregion
+
+      solutionProc.AddSubOperator(evaluatorInjector);
+      solutionProc.AddSubOperator(trainingMseEvaluator);
+      solutionProc.AddSubOperator(validationMseEvaluator);
+      solutionProc.AddSubOperator(testMseEvaluator);
+      solutionProc.AddSubOperator(trainingMapeEvaluator);
+      solutionProc.AddSubOperator(validationMapeEvaluator);
+      solutionProc.AddSubOperator(testMapeEvaluator);
+      solutionProc.AddSubOperator(trainingMapreEvaluator);
+      solutionProc.AddSubOperator(validationMapreEvaluator);
+      solutionProc.AddSubOperator(testMapreEvaluator);
+      solutionProc.AddSubOperator(trainingR2Evaluator);
+      solutionProc.AddSubOperator(validationR2Evaluator);
+      solutionProc.AddSubOperator(testR2Evaluator);
+      solutionProc.AddSubOperator(trainingVAFEvaluator);
+      solutionProc.AddSubOperator(validationVAFEvaluator);
+      solutionProc.AddSubOperator(testVAFEvaluator);
+
+      #region variable impacts
+      // calculate and set variable impacts
+      VariableNamesExtractor namesExtractor = new VariableNamesExtractor();
+      namesExtractor.GetVariableInfo("VariableNames").ActualName = "InputVariableNames";
+      PredictorBuilder predictorBuilder = new PredictorBuilder();
+      predictorBuilder.GetVariableInfo("TreeEvaluator").ActualName = "ModelAnalysisTreeEvaluator";
+      predictorBuilder.AddVariable(new HeuristicLab.Core.Variable("PunishmentFactor", new DoubleData(1000.0)));
+
+      VariableEvaluationImpactCalculator evaluationImpactCalculator = new VariableEvaluationImpactCalculator();
+      evaluationImpactCalculator.GetVariableInfo("SamplesStart").ActualName = "ActualTrainingSamplesStart";
+      evaluationImpactCalculator.GetVariableInfo("SamplesEnd").ActualName = "ActualTrainingSamplesEnd";
+      VariableQualityImpactCalculator qualityImpactCalculator = new VariableQualityImpactCalculator();
+      qualityImpactCalculator.GetVariableInfo("SamplesStart").ActualName = "ActualTrainingSamplesStart";
+      qualityImpactCalculator.GetVariableInfo("SamplesEnd").ActualName = "ActualTrainingSamplesEnd";
+
+      solutionProc.AddSubOperator(namesExtractor);
+      solutionProc.AddSubOperator(predictorBuilder);
+      solutionProc.AddSubOperator(evaluationImpactCalculator);
+      solutionProc.AddSubOperator(qualityImpactCalculator);
+      #endregion
+
+      op.OperatorGraph.AddOperator(seq);
+      op.OperatorGraph.InitialOperator = seq;
+      return op;
     }
 
@@ -207,5 +371,5 @@
       injector.AddVariable(new HeuristicLab.Core.Variable("Parents", new IntData()));
       injector.AddVariable(new HeuristicLab.Core.Variable("UseEstimatedTargetValue", new BoolData()));
-      injector.AddVariable(new HeuristicLab.Core.Variable("TreeEvaluator", new HL2TreeEvaluator()));
+      injector.AddVariable(new HeuristicLab.Core.Variable("PunishmentFactor", new DoubleData(10.0)));
       return injector;
     }
@@ -312,20 +476,12 @@
     protected internal virtual IOperator CreateBestSolutionProcessor() {
       SequentialProcessor seq = new SequentialProcessor();
-      // calculate and set variable impacts
-      VariableNamesExtractor namesExtractor = new VariableNamesExtractor();
-      namesExtractor.GetVariableInfo("VariableNames").ActualName = "InputVariableNames";
-      PredictorBuilder predictorBuilder = new PredictorBuilder();
-
-      VariableEvaluationImpactCalculator evaluationImpactCalculator = new VariableEvaluationImpactCalculator();
-      evaluationImpactCalculator.GetVariableInfo("SamplesStart").ActualName = "ActualTrainingSamplesStart";
-      evaluationImpactCalculator.GetVariableInfo("SamplesEnd").ActualName = "ActualTrainingSamplesEnd";
-      VariableQualityImpactCalculator qualityImpactCalculator = new VariableQualityImpactCalculator();
-      qualityImpactCalculator.GetVariableInfo("SamplesStart").ActualName = "ActualTrainingSamplesStart";
-      qualityImpactCalculator.GetVariableInfo("SamplesEnd").ActualName = "ActualTrainingSamplesEnd";
-
-      seq.AddSubOperator(namesExtractor);
-      seq.AddSubOperator(predictorBuilder);
-      seq.AddSubOperator(evaluationImpactCalculator);
-      seq.AddSubOperator(qualityImpactCalculator);
+      ProgrammableOperator progOperator = new ProgrammableOperator();
+      progOperator.RemoveVariableInfo("Result");
+      progOperator.AddVariableInfo(new HeuristicLab.Core.VariableInfo("EvaluatedSolutions", "", typeof(IntData), VariableKind.In));
+      progOperator.Code = @"
+int evalSolutions = EvaluatedSolutions.Data;
+scope.AddVariable(new Variable(""EvaluatedSolutions"", new IntData(evalSolutions)));
+";
+      seq.AddSubOperator(progOperator);
       return seq;
     }
@@ -439,6 +595,19 @@
       model.TestSamplesEnd = bestModelScope.GetVariableValue<IntData>("TestSamplesEnd", true).Data;
 
-      model.TrainingMeanSquaredError = bestModelScope.GetVariableValue<DoubleData>("Quality", false).Data;
-      model.ValidationMeanSquaredError = bestModelScope.GetVariableValue<DoubleData>("ValidationQuality", false).Data;
+      model.TrainingMeanSquaredError = bestModelScope.GetVariableValue<DoubleData>("TrainingMSE", false).Data;
+      model.ValidationMeanSquaredError = bestModelScope.GetVariableValue<DoubleData>("ValidationMSE", false).Data;
+      model.TestMeanSquaredError = bestModelScope.GetVariableValue<DoubleData>("TestMSE", false).Data;
+      model.TrainingCoefficientOfDetermination = bestModelScope.GetVariableValue<DoubleData>("TrainingR2", false).Data;
+      model.ValidationCoefficientOfDetermination = bestModelScope.GetVariableValue<DoubleData>("ValidationR2", false).Data;
+      model.TestCoefficientOfDetermination = bestModelScope.GetVariableValue<DoubleData>("TestR2", false).Data;
+      model.TrainingMeanAbsolutePercentageError = bestModelScope.GetVariableValue<DoubleData>("TrainingMAPE", false).Data;
+      model.ValidationMeanAbsolutePercentageError = bestModelScope.GetVariableValue<DoubleData>("ValidationMAPE", false).Data;
+      model.TestMeanAbsolutePercentageError = bestModelScope.GetVariableValue<DoubleData>("TestMAPE", false).Data;
+      model.TrainingMeanAbsolutePercentageOfRangeError = bestModelScope.GetVariableValue<DoubleData>("TrainingMAPRE", false).Data;
+      model.ValidationMeanAbsolutePercentageOfRangeError = bestModelScope.GetVariableValue<DoubleData>("ValidationMAPRE", false).Data;
+      model.TestMeanAbsolutePercentageOfRangeError = bestModelScope.GetVariableValue<DoubleData>("TestMAPRE", false).Data;
+      model.TrainingVarianceAccountedFor = bestModelScope.GetVariableValue<DoubleData>("TrainingVAF", false).Data;
+      model.ValidationVarianceAccountedFor = bestModelScope.GetVariableValue<DoubleData>("ValidationVAF", false).Data;
+      model.TestVarianceAccountedFor = bestModelScope.GetVariableValue<DoubleData>("TestVAF", false).Data;
 
       ItemList evaluationImpacts = bestModelScope.GetVariableValue<ItemList>("VariableEvaluationImpacts", false);
@@ -456,5 +625,5 @@
         model.AddInputVariable(variableName);
       }
-      Engine.GlobalScope.RemoveSubScope(bestModelScope);
+
       return model;
     }
Index: /trunk/sources/HeuristicLab.GP.StructureIdentification/3.3/BaseClasses/TreeEvaluatorBase.cs
===================================================================
--- /trunk/sources/HeuristicLab.GP.StructureIdentification/3.3/BaseClasses/TreeEvaluatorBase.cs	(revision 2327)
+++ /trunk/sources/HeuristicLab.GP.StructureIdentification/3.3/BaseClasses/TreeEvaluatorBase.cs	(revision 2328)
@@ -33,7 +33,4 @@
   public abstract class TreeEvaluatorBase : ItemBase, ITreeEvaluator {
     protected const double EPSILON = 1.0e-7;
-    protected double maxValue = double.MaxValue;
-    protected double minValue = double.MinValue;
-    private double punishmentFactor = 10.0; // we should provide a view for treeevaluators that allows to change this value
 
     protected class Instr {
@@ -50,4 +47,17 @@
     protected int sampleIndex;
 
+    public double UpperEvaluationLimit { get; set; }
+    public double LowerEvaluationLimit { get; set; }
+
+    public TreeEvaluatorBase() // for persistence
+      : this(double.MinValue, double.MaxValue) {
+    }
+
+    public TreeEvaluatorBase(double minEstimatedValue, double maxEstimatedValue)
+      : base() {
+      UpperEvaluationLimit = maxEstimatedValue;
+      LowerEvaluationLimit = minEstimatedValue;
+    }
+
     public void PrepareForEvaluation(Dataset dataset, IFunctionTree functionTree) {
       this.dataset = dataset;
@@ -57,13 +67,4 @@
         codeArr[i++] = TranslateToInstr(tree);
       }
-    }
-
-    public void PrepareForEvaluation(Dataset dataset, int targetVariable, int start, int end, IFunctionTree functionTree) {
-      // calculate upper and lower bounds for the estimated value (mean +/- punishmentFactor * range)
-      double mean = dataset.GetMean(targetVariable, start, end);
-      double range = dataset.GetRange(targetVariable, start, end);
-      maxValue = mean + punishmentFactor * range;
-      minValue = mean - punishmentFactor * range;
-      PrepareForEvaluation(dataset, functionTree);
     }
 
@@ -106,8 +107,6 @@
       this.sampleIndex = sampleIndex;
 
-      double estimated = EvaluateBakedCode();
-      if (double.IsNaN(estimated) || double.IsInfinity(estimated)) estimated = maxValue;
-      else if (estimated < minValue) estimated = minValue;
-      else if (estimated > maxValue) estimated = maxValue;
+      double estimated = Math.Min(Math.Max(EvaluateBakedCode(), LowerEvaluationLimit), UpperEvaluationLimit);
+      if (double.IsNaN(estimated)) estimated = UpperEvaluationLimit;
       return estimated;
     }
@@ -126,7 +125,6 @@
     public override object Clone(IDictionary<Guid, object> clonedObjects) {
       TreeEvaluatorBase clone = (TreeEvaluatorBase)base.Clone(clonedObjects);
-      clone.maxValue = maxValue;
-      clone.minValue = minValue;
-      clone.punishmentFactor = punishmentFactor;
+      clone.UpperEvaluationLimit = UpperEvaluationLimit;
+      clone.LowerEvaluationLimit = LowerEvaluationLimit;
       return clone;
     }
@@ -134,12 +132,8 @@
     public override System.Xml.XmlNode GetXmlNode(string name, System.Xml.XmlDocument document, IDictionary<Guid, IStorable> persistedObjects) {
       XmlNode node = base.GetXmlNode(name, document, persistedObjects);
-      XmlAttribute maxValueAttribute = document.CreateAttribute("MaxPredictionValue");
-      XmlAttribute minValueAttribute = document.CreateAttribute("MinPredictionValue");
-      XmlAttribute punishmentFactorAttribute = document.CreateAttribute("PunishmentFactor");
-      maxValueAttribute.Value = XmlConvert.ToString(maxValue);
-      minValueAttribute.Value = XmlConvert.ToString(minValue);
-      punishmentFactorAttribute.Value = XmlConvert.ToString(punishmentFactor);
-
-      node.Attributes.Append(punishmentFactorAttribute);
+      XmlAttribute maxValueAttribute = document.CreateAttribute("UpperEvaluationLimit");
+      XmlAttribute minValueAttribute = document.CreateAttribute("LowerEvaluationLimit");
+      maxValueAttribute.Value = XmlConvert.ToString(UpperEvaluationLimit);
+      minValueAttribute.Value = XmlConvert.ToString(LowerEvaluationLimit);
       node.Attributes.Append(minValueAttribute);
       node.Attributes.Append(maxValueAttribute);
@@ -149,7 +143,6 @@
     public override void Populate(System.Xml.XmlNode node, IDictionary<Guid, IStorable> restoredObjects) {
       base.Populate(node, restoredObjects);
-      minValue = XmlConvert.ToDouble(node.Attributes["MinPredictionValue"].Value);
-      maxValue = XmlConvert.ToDouble(node.Attributes["MaxPredictionValue"].Value);
-      punishmentFactor = XmlConvert.ToDouble(node.Attributes["PunishmentFactor"].Value);
+      LowerEvaluationLimit = XmlConvert.ToDouble(node.Attributes["LowerEvaluationLimit"].Value);
+      UpperEvaluationLimit = XmlConvert.ToDouble(node.Attributes["UpperEvaluationLimit"].Value);
     }
   }
Index: /trunk/sources/HeuristicLab.GP.StructureIdentification/3.3/Evaluators/GPEvaluatorBase.cs
===================================================================
--- /trunk/sources/HeuristicLab.GP.StructureIdentification/3.3/Evaluators/GPEvaluatorBase.cs	(revision 2327)
+++ /trunk/sources/HeuristicLab.GP.StructureIdentification/3.3/Evaluators/GPEvaluatorBase.cs	(revision 2328)
@@ -34,6 +34,4 @@
       AddVariableInfo(new VariableInfo("TargetVariable", "Index of the column of the dataset that holds the target variable", typeof(IntData), VariableKind.In));
       AddVariableInfo(new VariableInfo("TotalEvaluatedNodes", "Number of evaluated nodes", typeof(DoubleData), VariableKind.In | VariableKind.Out));
-      AddVariableInfo(new VariableInfo("TrainingSamplesStart", "Start index of training samples in dataset", typeof(IntData), VariableKind.In));
-      AddVariableInfo(new VariableInfo("TrainingSamplesEnd", "End index of training samples in dataset", typeof(IntData), VariableKind.In));
       AddVariableInfo(new VariableInfo("SamplesStart", "Start index of samples in dataset to evaluate", typeof(IntData), VariableKind.In));
       AddVariableInfo(new VariableInfo("SamplesEnd", "End index of samples in dataset to evaluate", typeof(IntData), VariableKind.In));
@@ -47,11 +45,9 @@
       IGeneticProgrammingModel gpModel = GetVariableValue<IGeneticProgrammingModel>("FunctionTree", scope, true);
       double totalEvaluatedNodes = scope.GetVariableValue<DoubleData>("TotalEvaluatedNodes", true).Data;
-      int trainingStart = GetVariableValue<IntData>("TrainingSamplesStart", scope, true).Data;
-      int trainingEnd = GetVariableValue<IntData>("TrainingSamplesEnd", scope, true).Data;
       int start = GetVariableValue<IntData>("SamplesStart", scope, true).Data;
       int end = GetVariableValue<IntData>("SamplesEnd", scope, true).Data;
       bool useEstimatedValues = GetVariableValue<BoolData>("UseEstimatedTargetValue", scope, true).Data;
       ITreeEvaluator evaluator = GetVariableValue<ITreeEvaluator>("TreeEvaluator", scope, true);
-      evaluator.PrepareForEvaluation(dataset, targetVariable, trainingStart, trainingEnd, gpModel.FunctionTree);
+      evaluator.PrepareForEvaluation(dataset, gpModel.FunctionTree);
 
       double[] backupValues = null;
Index: /trunk/sources/HeuristicLab.GP.StructureIdentification/3.3/HL2TreeEvaluator.cs
===================================================================
--- /trunk/sources/HeuristicLab.GP.StructureIdentification/3.3/HL2TreeEvaluator.cs	(revision 2327)
+++ /trunk/sources/HeuristicLab.GP.StructureIdentification/3.3/HL2TreeEvaluator.cs	(revision 2328)
@@ -28,4 +28,6 @@
   /// </summary>
   public class HL2TreeEvaluator : TreeEvaluatorBase {
+    public HL2TreeEvaluator() : base() { } // for persistence
+    public HL2TreeEvaluator(double minValue, double maxValue) : base(minValue, maxValue) { }
 
     protected override double EvaluateBakedCode() {
Index: /trunk/sources/HeuristicLab.GP.StructureIdentification/3.3/HL3TreeEvaluator.cs
===================================================================
--- /trunk/sources/HeuristicLab.GP.StructureIdentification/3.3/HL3TreeEvaluator.cs	(revision 2327)
+++ /trunk/sources/HeuristicLab.GP.StructureIdentification/3.3/HL3TreeEvaluator.cs	(revision 2328)
@@ -30,4 +30,7 @@
   /// </summary>
   public class HL3TreeEvaluator : TreeEvaluatorBase {
+    public HL3TreeEvaluator() : base() { } // for persistence
+    public HL3TreeEvaluator(double minValue, double maxValue) : base(minValue, maxValue) { }
+
     protected override double EvaluateBakedCode() {
       Instr currInstr = codeArr[PC++];
Index: /trunk/sources/HeuristicLab.GP.StructureIdentification/3.3/HeuristicLab.GP.StructureIdentification-3.3.csproj
===================================================================
--- /trunk/sources/HeuristicLab.GP.StructureIdentification/3.3/HeuristicLab.GP.StructureIdentification-3.3.csproj	(revision 2327)
+++ /trunk/sources/HeuristicLab.GP.StructureIdentification/3.3/HeuristicLab.GP.StructureIdentification-3.3.csproj	(revision 2328)
@@ -85,8 +85,16 @@
     <Compile Include="BaseClasses\FunctionTreeBase.cs" />
     <Compile Include="BaseClasses\TreeEvaluatorBase.cs" />
+    <Compile Include="HL3TreeEvaluatorInjector.cs" />
+    <Compile Include="HL2TreeEvaluatorInjector.cs" />
     <Compile Include="PredictorBuilder.cs" />
     <Compile Include="Predictor.cs" />
     <Compile Include="Evaluators\SimpleGPEvaluatorBase.cs" />
     <Compile Include="HL3TreeEvaluator.cs" />
+    <Compile Include="PredictorView.cs">
+      <SubType>UserControl</SubType>
+    </Compile>
+    <Compile Include="PredictorView.Designer.cs">
+      <DependentUpon>PredictorView.cs</DependentUpon>
+    </Compile>
     <Compile Include="Symbols\Addition.cs" />
     <Compile Include="Symbols\And.cs" />
@@ -222,4 +230,7 @@
       <DependentUpon>OffSpringSelectionGpEditor.cs</DependentUpon>
     </EmbeddedResource>
+    <EmbeddedResource Include="PredictorView.resx">
+      <DependentUpon>PredictorView.cs</DependentUpon>
+    </EmbeddedResource>
     <EmbeddedResource Include="StandardGpEditor.resx">
       <DependentUpon>StandardGpEditor.cs</DependentUpon>
Index: /trunk/sources/HeuristicLab.GP.StructureIdentification/3.3/ITreeEvaluator.cs
===================================================================
--- /trunk/sources/HeuristicLab.GP.StructureIdentification/3.3/ITreeEvaluator.cs	(revision 2327)
+++ /trunk/sources/HeuristicLab.GP.StructureIdentification/3.3/ITreeEvaluator.cs	(revision 2328)
@@ -26,5 +26,6 @@
 namespace HeuristicLab.GP.StructureIdentification {
   public interface ITreeEvaluator : IItem {
-    void PrepareForEvaluation(Dataset dataset, int targetVariable, int start, int end, IFunctionTree functionTree);
+    double LowerEvaluationLimit { get; set; }
+    double UpperEvaluationLimit { get; set; }
     void PrepareForEvaluation(Dataset dataset, IFunctionTree functionTree);
     double Evaluate(int sampleIndex);
Index: /trunk/sources/HeuristicLab.GP.StructureIdentification/3.3/Predictor.cs
===================================================================
--- /trunk/sources/HeuristicLab.GP.StructureIdentification/3.3/Predictor.cs	(revision 2327)
+++ /trunk/sources/HeuristicLab.GP.StructureIdentification/3.3/Predictor.cs	(revision 2328)
@@ -31,14 +31,6 @@
 
 namespace HeuristicLab.GP.StructureIdentification {
-  public class Predictor : ItemBase, IPredictor {
+  public class Predictor : PredictorBase {
     private ITreeEvaluator treeEvaluator;
-    
-
-    public Predictor() : base() { } // for persistence
-    public Predictor(ITreeEvaluator evaluator, IGeneticProgrammingModel tree)
-      : base() {
-      this.treeEvaluator = evaluator;
-      this.functionTree = tree;
-    }
 
     private IGeneticProgrammingModel functionTree;
@@ -46,6 +38,15 @@
       get { return functionTree; }
     }
+    public Predictor() : base() { } // for persistence
+    public Predictor(ITreeEvaluator evaluator, IGeneticProgrammingModel tree, double lowerPredictionLimit, double upperPredictionLimit)
+      : base(lowerPredictionLimit, upperPredictionLimit) {
+      this.treeEvaluator = evaluator;
+      this.functionTree = tree;
+    }
 
-    public double[] Predict(Dataset input, int start, int end) {
+    public override double[] Predict(Dataset input, int start, int end) {
+      treeEvaluator.UpperEvaluationLimit = UpperPredictionLimit;
+      treeEvaluator.LowerEvaluationLimit = LowerPredictionLimit;
+
       if (start < 0 || end <= start) throw new ArgumentException("start must be larger than zero and strictly smaller than end");
       if (end > input.Rows) throw new ArgumentOutOfRangeException("number of rows in input is smaller then end");
@@ -59,5 +60,5 @@
 
     public override IView CreateView() {
-      return functionTree.CreateView();
+      return new PredictorView(this);
     }
 
Index: /trunk/sources/HeuristicLab.GP.StructureIdentification/3.3/PredictorBuilder.cs
===================================================================
--- /trunk/sources/HeuristicLab.GP.StructureIdentification/3.3/PredictorBuilder.cs	(revision 2327)
+++ /trunk/sources/HeuristicLab.GP.StructureIdentification/3.3/PredictorBuilder.cs	(revision 2328)
@@ -28,4 +28,5 @@
 using HeuristicLab.GP.Interfaces;
 using HeuristicLab.Modeling;
+using HeuristicLab.DataAnalysis;
 
 namespace HeuristicLab.GP.StructureIdentification {
@@ -35,4 +36,9 @@
       AddVariableInfo(new VariableInfo("FunctionTree", "The function tree", typeof(IGeneticProgrammingModel), VariableKind.In));
       AddVariableInfo(new VariableInfo("TreeEvaluator", "The tree evaluator used to evaluate the model", typeof(ITreeEvaluator), VariableKind.In));
+      AddVariableInfo(new VariableInfo("PunishmentFactor", "The punishment factor limits the estimated values to a certain range", typeof(DoubleData), VariableKind.In));
+      AddVariableInfo(new VariableInfo("Dataset", "The dataset", typeof(Dataset), VariableKind.In));
+      AddVariableInfo(new VariableInfo("TrainingSamplesStart", "Start index of training set", typeof(DoubleData), VariableKind.In));
+      AddVariableInfo(new VariableInfo("TrainingSamplesEnd", "End index of training set", typeof(DoubleData), VariableKind.In));
+      AddVariableInfo(new VariableInfo("TargetVariable", "Index of the target variable", typeof(IntData), VariableKind.In));
       AddVariableInfo(new VariableInfo("Predictor", "The predictor combines the function tree and the evaluator and can be used to generate estimated values", typeof(IPredictor), VariableKind.New));
     }
@@ -44,6 +50,15 @@
     public override IOperation Apply(IScope scope) {
       IGeneticProgrammingModel model = GetVariableValue<IGeneticProgrammingModel>("FunctionTree", scope, true);
-      ITreeEvaluator evaluator = GetVariableValue<ITreeEvaluator>("TreeEvaluator", scope, true);
-      scope.AddVariable(new HeuristicLab.Core.Variable(scope.TranslateName("Predictor"), new Predictor(evaluator, model)));
+      ITreeEvaluator evaluator = (ITreeEvaluator)GetVariableValue<ITreeEvaluator>("TreeEvaluator", scope, true).Clone();
+      double punishmentFactor = GetVariableValue<DoubleData>("PunishmentFactor", scope, true).Data;
+      Dataset dataset = GetVariableValue<Dataset>("Dataset", scope, true);
+      int start = GetVariableValue<IntData>("TrainingSamplesStart", scope, true).Data;
+      int end = GetVariableValue<IntData>("TrainingSamplesEnd", scope, true).Data;
+      int targetVariable = GetVariableValue<IntData>("TargetVariable", scope, true).Data;
+      double mean = dataset.GetMean(targetVariable, start, end);
+      double range = dataset.GetRange(targetVariable, start, end);
+      double minEstimatedValue = mean - punishmentFactor * range;
+      double maxEstimatedValue = mean + punishmentFactor * range;
+      scope.AddVariable(new HeuristicLab.Core.Variable(scope.TranslateName("Predictor"), new Predictor(evaluator, model, minEstimatedValue, maxEstimatedValue)));
       return null;
     }
Index: /trunk/sources/HeuristicLab.GP.StructureIdentification/3.3/StandardGP.cs
===================================================================
--- /trunk/sources/HeuristicLab.GP.StructureIdentification/3.3/StandardGP.cs	(revision 2327)
+++ /trunk/sources/HeuristicLab.GP.StructureIdentification/3.3/StandardGP.cs	(revision 2328)
@@ -115,5 +115,5 @@
 
     protected internal override IOperator CreateProblemInjector() {
-      SequentialProcessor seq = new SequentialProcessor();      
+      SequentialProcessor seq = new SequentialProcessor();
       var probInject = new ProblemInjector();
       probInject.GetVariableInfo("MaxNumberOfTrainingSamples").Local = true;
@@ -201,107 +201,4 @@
       manipulator.OperatorGraph.InitialOperator = multibranch;
       return manipulator;
-    }
-
-    protected internal override IOperator CreateBestSolutionProcessor() {      
-      SequentialProcessor bestSolutionProcessor = new SequentialProcessor();
-      bestSolutionProcessor.AddSubOperator(base.CreateBestSolutionProcessor());
-
-      #region MSE
-      MeanSquaredErrorEvaluator testMseEvaluator = new MeanSquaredErrorEvaluator();
-      testMseEvaluator.Name = "TestMeanSquaredErrorEvaluator";
-      testMseEvaluator.GetVariableInfo("MSE").ActualName = "TestQuality";
-      testMseEvaluator.GetVariableInfo("SamplesStart").ActualName = "TestSamplesStart";
-      testMseEvaluator.GetVariableInfo("SamplesEnd").ActualName = "TestSamplesEnd";
-      #endregion
-      #region MAPE
-      MeanAbsolutePercentageErrorEvaluator trainingMapeEvaluator = new MeanAbsolutePercentageErrorEvaluator();
-      trainingMapeEvaluator.Name = "TrainingMapeEvaluator";
-      trainingMapeEvaluator.GetVariableInfo("MAPE").ActualName = "TrainingMAPE";
-      trainingMapeEvaluator.GetVariableInfo("SamplesStart").ActualName = "ActualTrainingSamplesStart";
-      trainingMapeEvaluator.GetVariableInfo("SamplesEnd").ActualName = "ActualTrainingSamplesEnd";
-      MeanAbsolutePercentageErrorEvaluator validationMapeEvaluator = new MeanAbsolutePercentageErrorEvaluator();
-      validationMapeEvaluator.Name = "ValidationMapeEvaluator";
-      validationMapeEvaluator.GetVariableInfo("MAPE").ActualName = "ValidationMAPE";
-      validationMapeEvaluator.GetVariableInfo("SamplesStart").ActualName = "ValidationSamplesStart";
-      validationMapeEvaluator.GetVariableInfo("SamplesEnd").ActualName = "ValidationSamplesEnd";
-      MeanAbsolutePercentageErrorEvaluator testMapeEvaluator = new MeanAbsolutePercentageErrorEvaluator();
-      testMapeEvaluator.Name = "TestMapeEvaluator";
-      testMapeEvaluator.GetVariableInfo("MAPE").ActualName = "TestMAPE";
-      testMapeEvaluator.GetVariableInfo("SamplesStart").ActualName = "TestSamplesStart";
-      testMapeEvaluator.GetVariableInfo("SamplesEnd").ActualName = "TestSamplesEnd";
-      #endregion
-      #region MAPRE
-      MeanAbsolutePercentageOfRangeErrorEvaluator trainingMapreEvaluator = new MeanAbsolutePercentageOfRangeErrorEvaluator();
-      trainingMapreEvaluator.Name = "TrainingMapreEvaluator";
-      trainingMapreEvaluator.GetVariableInfo("MAPRE").ActualName = "TrainingMAPRE";
-      trainingMapreEvaluator.GetVariableInfo("SamplesStart").ActualName = "ActualTrainingSamplesStart";
-      trainingMapreEvaluator.GetVariableInfo("SamplesEnd").ActualName = "ActualTrainingSamplesEnd";
-      MeanAbsolutePercentageOfRangeErrorEvaluator validationMapreEvaluator = new MeanAbsolutePercentageOfRangeErrorEvaluator();
-      validationMapreEvaluator.Name = "ValidationMapreEvaluator";
-      validationMapreEvaluator.GetVariableInfo("MAPRE").ActualName = "ValidationMAPRE";
-      validationMapreEvaluator.GetVariableInfo("SamplesStart").ActualName = "ValidationSamplesStart";
-      validationMapreEvaluator.GetVariableInfo("SamplesEnd").ActualName = "ValidationSamplesEnd";
-      MeanAbsolutePercentageOfRangeErrorEvaluator testMapreEvaluator = new MeanAbsolutePercentageOfRangeErrorEvaluator();
-      testMapreEvaluator.Name = "TestMapreEvaluator";
-      testMapreEvaluator.GetVariableInfo("MAPRE").ActualName = "TestMAPRE";
-      testMapreEvaluator.GetVariableInfo("SamplesStart").ActualName = "TestSamplesStart";
-      testMapreEvaluator.GetVariableInfo("SamplesEnd").ActualName = "TestSamplesEnd";
-      #endregion MAPRE
-      #region R2
-      CoefficientOfDeterminationEvaluator trainingR2Evaluator = new CoefficientOfDeterminationEvaluator();
-      trainingR2Evaluator.Name = "TrainingR2Evaluator";
-      trainingR2Evaluator.GetVariableInfo("R2").ActualName = "TrainingR2";
-      trainingR2Evaluator.GetVariableInfo("SamplesStart").ActualName = "ActualTrainingSamplesStart";
-      trainingR2Evaluator.GetVariableInfo("SamplesEnd").ActualName = "ActualTrainingSamplesEnd";
-      CoefficientOfDeterminationEvaluator validationR2Evaluator = new CoefficientOfDeterminationEvaluator();
-      validationR2Evaluator.Name = "ValidationR2Evaluator";
-      validationR2Evaluator.GetVariableInfo("R2").ActualName = "ValidationR2";
-      validationR2Evaluator.GetVariableInfo("SamplesStart").ActualName = "ValidationSamplesStart";
-      validationR2Evaluator.GetVariableInfo("SamplesEnd").ActualName = "ValidationSamplesEnd";
-      CoefficientOfDeterminationEvaluator testR2Evaluator = new CoefficientOfDeterminationEvaluator();
-      testR2Evaluator.Name = "TestR2Evaluator";
-      testR2Evaluator.GetVariableInfo("R2").ActualName = "TestR2";
-      testR2Evaluator.GetVariableInfo("SamplesStart").ActualName = "TestSamplesStart";
-      testR2Evaluator.GetVariableInfo("SamplesEnd").ActualName = "TestSamplesEnd";
-      #endregion
-      #region VAF
-      VarianceAccountedForEvaluator trainingVAFEvaluator = new VarianceAccountedForEvaluator();
-      trainingVAFEvaluator.Name = "TrainingVAFEvaluator";
-      trainingVAFEvaluator.GetVariableInfo("VAF").ActualName = "TrainingVAF";
-      trainingVAFEvaluator.GetVariableInfo("SamplesStart").ActualName = "ActualTrainingSamplesStart";
-      trainingVAFEvaluator.GetVariableInfo("SamplesEnd").ActualName = "ActualTrainingSamplesEnd";
-      VarianceAccountedForEvaluator validationVAFEvaluator = new VarianceAccountedForEvaluator();
-      validationVAFEvaluator.Name = "ValidationVAFEvaluator";
-      validationVAFEvaluator.GetVariableInfo("VAF").ActualName = "ValidationVAF";
-      validationVAFEvaluator.GetVariableInfo("SamplesStart").ActualName = "ValidationSamplesStart";
-      validationVAFEvaluator.GetVariableInfo("SamplesEnd").ActualName = "ValidationSamplesEnd";
-      VarianceAccountedForEvaluator testVAFEvaluator = new VarianceAccountedForEvaluator();
-      testVAFEvaluator.Name = "TestVAFEvaluator";
-      testVAFEvaluator.GetVariableInfo("VAF").ActualName = "TestVAF";
-      testVAFEvaluator.GetVariableInfo("SamplesStart").ActualName = "TestSamplesStart";
-      testVAFEvaluator.GetVariableInfo("SamplesEnd").ActualName = "TestSamplesEnd";
-      #endregion
-      ProgrammableOperator progOperator = new ProgrammableOperator();
-      progOperator.RemoveVariableInfo("Result");
-      progOperator.AddVariableInfo(new HeuristicLab.Core.VariableInfo("EvaluatedSolutions", "", typeof(IntData), VariableKind.In));
-      progOperator.Code = @"
-int evalSolutions = EvaluatedSolutions.Data;
-scope.AddVariable(new Variable(""EvaluatedSolutions"", new IntData(evalSolutions)));
-";
-      bestSolutionProcessor.AddSubOperator(testMseEvaluator);
-      bestSolutionProcessor.AddSubOperator(trainingMapeEvaluator);
-      bestSolutionProcessor.AddSubOperator(validationMapeEvaluator);
-      bestSolutionProcessor.AddSubOperator(testMapeEvaluator);
-      bestSolutionProcessor.AddSubOperator(trainingMapreEvaluator);
-      bestSolutionProcessor.AddSubOperator(validationMapreEvaluator);
-      bestSolutionProcessor.AddSubOperator(testMapreEvaluator);
-      bestSolutionProcessor.AddSubOperator(trainingR2Evaluator);
-      bestSolutionProcessor.AddSubOperator(validationR2Evaluator);
-      bestSolutionProcessor.AddSubOperator(testR2Evaluator);
-      bestSolutionProcessor.AddSubOperator(trainingVAFEvaluator);
-      bestSolutionProcessor.AddSubOperator(validationVAFEvaluator);
-      bestSolutionProcessor.AddSubOperator(testVAFEvaluator);
-      bestSolutionProcessor.AddSubOperator(progOperator);
-      return bestSolutionProcessor;
     }
 
@@ -338,23 +235,4 @@
     }
 
-    protected internal override IAnalyzerModel CreateGPModel(IScope bestModelScope) {
-      IAnalyzerModel model = base.CreateGPModel(bestModelScope);
-      model.TestMeanSquaredError = bestModelScope.GetVariableValue<DoubleData>("TestQuality", false).Data;
-      model.TrainingCoefficientOfDetermination = bestModelScope.GetVariableValue<DoubleData>("TrainingR2", false).Data;
-      model.ValidationCoefficientOfDetermination = bestModelScope.GetVariableValue<DoubleData>("ValidationR2", false).Data;
-      model.TestCoefficientOfDetermination = bestModelScope.GetVariableValue<DoubleData>("TestR2", false).Data;
-      model.TrainingMeanAbsolutePercentageError = bestModelScope.GetVariableValue<DoubleData>("TrainingMAPE", false).Data;
-      model.ValidationMeanAbsolutePercentageError = bestModelScope.GetVariableValue<DoubleData>("ValidationMAPE", false).Data;
-      model.TestMeanAbsolutePercentageError = bestModelScope.GetVariableValue<DoubleData>("TestMAPE", false).Data;
-      model.TrainingMeanAbsolutePercentageOfRangeError = bestModelScope.GetVariableValue<DoubleData>("TrainingMAPRE", false).Data;
-      model.ValidationMeanAbsolutePercentageOfRangeError = bestModelScope.GetVariableValue<DoubleData>("ValidationMAPRE", false).Data;
-      model.TestMeanAbsolutePercentageOfRangeError = bestModelScope.GetVariableValue<DoubleData>("TestMAPRE", false).Data;
-      model.TrainingVarianceAccountedFor = bestModelScope.GetVariableValue<DoubleData>("TrainingVAF", false).Data;
-      model.ValidationVarianceAccountedFor = bestModelScope.GetVariableValue<DoubleData>("ValidationVAF", false).Data;
-      model.TestVarianceAccountedFor = bestModelScope.GetVariableValue<DoubleData>("TestVAF", false).Data;
-
-      return model;
-    }
-
     public virtual IEditor CreateEditor() {
       return new StandardGpEditor(this);
Index: /trunk/sources/HeuristicLab.GP/3.3/FunctionTreeView.Designer.cs
===================================================================
--- /trunk/sources/HeuristicLab.GP/3.3/FunctionTreeView.Designer.cs	(revision 2327)
+++ /trunk/sources/HeuristicLab.GP/3.3/FunctionTreeView.Designer.cs	(revision 2328)
@@ -52,5 +52,4 @@
       // funTreeView
       // 
-      this.funTreeView.Dock = System.Windows.Forms.DockStyle.Fill;
       this.funTreeView.HideSelection = false;
       this.funTreeView.Location = new System.Drawing.Point(0, 0);
@@ -73,6 +72,6 @@
     #endregion
 
-    private System.Windows.Forms.ContextMenu treeNodeContextMenu;
-    private System.Windows.Forms.TreeView funTreeView;
+    protected System.Windows.Forms.ContextMenu treeNodeContextMenu;
+    protected System.Windows.Forms.TreeView funTreeView;
   }
 }
Index: /trunk/sources/HeuristicLab.GP/3.3/GeneticProgrammingModel.cs
===================================================================
--- /trunk/sources/HeuristicLab.GP/3.3/GeneticProgrammingModel.cs	(revision 2327)
+++ /trunk/sources/HeuristicLab.GP/3.3/GeneticProgrammingModel.cs	(revision 2328)
@@ -97,5 +97,5 @@
 
     public override IView CreateView() {
-      return new FunctionTreeView(this.FunctionTree);
+      return new GeneticProgrammingModelView(this);
     }
   }
Index: /trunk/sources/HeuristicLab.GP/3.3/HeuristicLab.GP-3.3.csproj
===================================================================
--- /trunk/sources/HeuristicLab.GP/3.3/HeuristicLab.GP-3.3.csproj	(revision 2327)
+++ /trunk/sources/HeuristicLab.GP/3.3/HeuristicLab.GP-3.3.csproj	(revision 2328)
@@ -89,4 +89,10 @@
     <Compile Include="BaseClasses\Terminal.cs" />
     <Compile Include="BaseClasses\UnaryFunction.cs" />
+    <Compile Include="GeneticProgrammingModelView.cs">
+      <SubType>UserControl</SubType>
+    </Compile>
+    <Compile Include="GeneticProgrammingModelView.Designer.cs">
+      <DependentUpon>GeneticProgrammingModelView.cs</DependentUpon>
+    </Compile>
     <Compile Include="FunctionLibrary.cs" />
     <Compile Include="FunctionLibraryEditor.cs">
@@ -127,4 +133,7 @@
   </ItemGroup>
   <ItemGroup>
+    <EmbeddedResource Include="GeneticProgrammingModelView.resx">
+      <DependentUpon>GeneticProgrammingModelView.cs</DependentUpon>
+    </EmbeddedResource>
     <EmbeddedResource Include="FunctionLibraryEditor.resx">
       <DependentUpon>FunctionLibraryEditor.cs</DependentUpon>
Index: /trunk/sources/HeuristicLab.LinearRegression/3.2/LinearRegression.cs
===================================================================
--- /trunk/sources/HeuristicLab.LinearRegression/3.2/LinearRegression.cs	(revision 2327)
+++ /trunk/sources/HeuristicLab.LinearRegression/3.2/LinearRegression.cs	(revision 2328)
@@ -97,4 +97,6 @@
       problemInjector.AddVariable(new HeuristicLab.Core.Variable("MaxNumberOfTrainingSamples", new IntData(5000)));
 
+      HL2TreeEvaluatorInjector treeEvaluatorInjector = new HL2TreeEvaluatorInjector();
+
       IOperator shuffler = new DatasetShuffler();
       shuffler.GetVariableInfo("ShuffleStart").ActualName = "TrainingSamplesStart";
@@ -108,4 +110,5 @@
       seq.AddSubOperator(problemInjector);
       seq.AddSubOperator(globalInjector);
+      seq.AddSubOperator(treeEvaluatorInjector);
       seq.AddSubOperator(shuffler);
       seq.AddSubOperator(lrOperator);
@@ -120,7 +123,6 @@
     private IOperator CreateGlobalInjector() {
       VariableInjector injector = new VariableInjector();
-      injector.AddVariable(new HeuristicLab.Core.Variable("PunishmentFactor", new DoubleData(10)));
+      injector.AddVariable(new HeuristicLab.Core.Variable("PunishmentFactor", new DoubleData(1000)));
       injector.AddVariable(new HeuristicLab.Core.Variable("TotalEvaluatedNodes", new DoubleData(0)));
-      injector.AddVariable(new HeuristicLab.Core.Variable("TreeEvaluator", new HL2TreeEvaluator()));
       injector.AddVariable(new HeuristicLab.Core.Variable("UseEstimatedTargetValue", new BoolData(false)));
 
@@ -272,5 +274,4 @@
     }
 
-
     protected internal virtual IAnalyzerModel CreateLRModel(IScope bestModelScope) {
       IAnalyzerModel model = new AnalyzerModel();
Index: unk/sources/HeuristicLab.Logging/3.2/BestSolutionStorer.cs
===================================================================
--- /trunk/sources/HeuristicLab.Logging/3.2/BestSolutionStorer.cs	(revision 2327)
+++ 	(revision )
@@ -1,131 +1,0 @@
-#region License Information
-/* HeuristicLab
- * Copyright (C) 2002-2008 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.Text;
-using HeuristicLab.Core;
-using HeuristicLab.Data;
-using HeuristicLab.Operators;
-
-namespace HeuristicLab.Logging {
-  /// <summary>
-  /// Keeps a variable in the global scope that contains the scope representing the best solution.
-  /// </summary>
-  public class BestSolutionStorer : OperatorBase {
-    /// <inheritdoc select="summary"/>
-    public override string Description {
-      get { return @"Keeps a variable in the global scope that contains the scope representing the best of run solution."; }
-    }
-
-    /// <summary>
-    /// Initializes a new instance of <see cref="BestSolutionStorer"/> with three variable infos
-    /// (<c>Quality</c>, <c>Maximization</c> and <c>BestSolution</c>).
-    /// </summary>
-    public BestSolutionStorer()
-      : base() {
-      AddVariableInfo(new VariableInfo("Quality", "Quality value of a solution", typeof(DoubleData), VariableKind.In));
-      AddVariableInfo(new VariableInfo("Maximization", "Maximization problem", typeof(BoolData), VariableKind.In));
-      AddVariableInfo(new VariableInfo("BestSolution", "The best solution of the run", typeof(IScope), VariableKind.New | VariableKind.In | VariableKind.Out));
-    }
-
-    /// <summary>
-    /// Keeps a variable in the global scope that contains the scope representing the best solution.
-    /// </summary>
-    /// <param name="scope">The scope whose populations to check for the best solution.</param>
-    /// <returns><c>null</c>.</returns>
-    public override IOperation Apply(IScope scope) {
-      if(scope.GetVariable(Guid.ToString() + "-Active") == null) {
-        double[] qualities = new double[scope.SubScopes.Count];
-        bool maximization = scope.GetVariableValue<BoolData>("Maximization", true).Data;
-        for(int i = 0; i < scope.SubScopes.Count; i++)
-          qualities[i] = scope.SubScopes[i].GetVariableValue<DoubleData>("Quality", false).Data;
-
-        double smallest = qualities[0]; int smallestIndex = 0;
-        double biggest = qualities[0]; int biggestIndex = 0;
-        for(int i = 1; i < qualities.Length; i++) {
-          if(qualities[i] < smallest) {
-            smallest = qualities[i];
-            smallestIndex = i;
-          }
-          if(qualities[i] > biggest) {
-            biggest = qualities[i];
-            biggestIndex = i;
-          }
-        }
-        IVariableInfo qualityInfo = GetVariableInfo("Quality");
-        IVariable bestSolutionVariable = scope.GetVariable(scope.TranslateName("BestSolution"));
-        if(bestSolutionVariable != null) {
-
-          double bestQuality = ((IScope)bestSolutionVariable.Value).GetVariableValue<DoubleData>(qualityInfo.ActualName, false).Data;
-
-          // do nothing if the best solution of the current scope is not better than the best solution of the whole run so far.
-          if((maximization && biggest <= bestQuality) ||
-            (!maximization && smallest >= bestQuality)) return null;
-        }
-
-        IScope bestSolutionClone;
-        if(maximization) {
-          bestSolutionClone = (IScope)scope.SubScopes[biggestIndex].Clone();
-        } else {
-          bestSolutionClone = (IScope)scope.SubScopes[smallestIndex].Clone();
-        }
-
-        if(SubOperators.Count > 0) {
-          scope.AddSubScope(bestSolutionClone);
-          scope.AddVariable(new Variable(Guid.ToString() + "-Active", new BoolData(true)));
-
-          CompositeOperation compOp = new CompositeOperation();
-          AtomicOperation operation = new AtomicOperation(SubOperators[0], bestSolutionClone);
-          AtomicOperation continuation = new AtomicOperation(this, scope);
-
-          compOp.AddOperation(operation);
-          compOp.AddOperation(continuation);
-          return compOp;
-        } else {
-          StoreBestSolution(bestSolutionClone, scope);
-          return null;
-        }
-      } else {  // operator already executed
-        scope.RemoveVariable(Guid.ToString() + "-Active");
-        IScope bestSolutionClone = scope.SubScopes[scope.SubScopes.Count - 1];
-        scope.RemoveSubScope(bestSolutionClone);
-
-        StoreBestSolution(bestSolutionClone, scope);
-        return null;
-      }
-    }
-
-    private void StoreBestSolution(IScope bestSolution, IScope scope) {
-      SetValue(GetVariableInfo("BestSolution"), bestSolution, scope);
-    }
-
-    private void SetValue(IVariableInfo info, IScope data, IScope scope) {
-      IVariable var = scope.GetVariable(info.ActualName);
-      if(var == null) {
-        var = new Variable(scope.TranslateName(info.FormalName), data);
-        scope.AddVariable(var);
-      } else {
-        var.Value = data;
-      }
-    }
-  }
-}
Index: /trunk/sources/HeuristicLab.Logging/3.2/HeuristicLab.Logging-3.2.csproj
===================================================================
--- /trunk/sources/HeuristicLab.Logging/3.2/HeuristicLab.Logging-3.2.csproj	(revision 2327)
+++ /trunk/sources/HeuristicLab.Logging/3.2/HeuristicLab.Logging-3.2.csproj	(revision 2328)
@@ -80,5 +80,4 @@
   <ItemGroup>
     <Compile Include="BestAverageWorstQualityCalculator.cs" />
-    <Compile Include="BestSolutionStorer.cs" />
     <Compile Include="PointXYChartView.cs">
       <SubType>UserControl</SubType>
Index: /trunk/sources/HeuristicLab.Modeling/3.2/BestSolutionStorer.cs
===================================================================
--- /trunk/sources/HeuristicLab.Modeling/3.2/BestSolutionStorer.cs	(revision 2328)
+++ /trunk/sources/HeuristicLab.Modeling/3.2/BestSolutionStorer.cs	(revision 2328)
@@ -0,0 +1,130 @@
+#region License Information
+/* HeuristicLab
+ * Copyright (C) 2002-2008 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.Text;
+using HeuristicLab.Core;
+using HeuristicLab.Data;
+
+namespace HeuristicLab.Modeling {
+  /// <summary>
+  /// Keeps a variable in the global scope that contains the scope representing the best solution.
+  /// </summary>
+  public class BestSolutionStorer : OperatorBase {
+    /// <inheritdoc select="summary"/>
+    public override string Description {
+      get { return @"Keeps a variable in the global scope that contains the scope representing the best of run solution."; }
+    }
+
+    /// <summary>
+    /// Initializes a new instance of <see cref="BestSolutionStorer"/> with three variable infos
+    /// (<c>Quality</c>, <c>Maximization</c> and <c>BestSolution</c>).
+    /// </summary>
+    public BestSolutionStorer()
+      : base() {
+      AddVariableInfo(new VariableInfo("Quality", "Quality value of a solution", typeof(DoubleData), VariableKind.In));
+      AddVariableInfo(new VariableInfo("Maximization", "Maximization problem", typeof(BoolData), VariableKind.In));
+      AddVariableInfo(new VariableInfo("BestSolution", "The best solution of the run", typeof(IScope), VariableKind.New | VariableKind.In | VariableKind.Out));
+    }
+
+    /// <summary>
+    /// Keeps a variable in the global scope that contains the scope representing the best solution.
+    /// </summary>
+    /// <param name="scope">The scope whose populations to check for the best solution.</param>
+    /// <returns><c>null</c>.</returns>
+    public override IOperation Apply(IScope scope) {
+      if(scope.GetVariable(Guid.ToString() + "-Active") == null) {
+        double[] qualities = new double[scope.SubScopes.Count];
+        bool maximization = scope.GetVariableValue<BoolData>("Maximization", true).Data;
+        for(int i = 0; i < scope.SubScopes.Count; i++)
+          qualities[i] = scope.SubScopes[i].GetVariableValue<DoubleData>("Quality", false).Data;
+
+        double smallest = qualities[0]; int smallestIndex = 0;
+        double biggest = qualities[0]; int biggestIndex = 0;
+        for(int i = 1; i < qualities.Length; i++) {
+          if(qualities[i] < smallest) {
+            smallest = qualities[i];
+            smallestIndex = i;
+          }
+          if(qualities[i] > biggest) {
+            biggest = qualities[i];
+            biggestIndex = i;
+          }
+        }
+        IVariableInfo qualityInfo = GetVariableInfo("Quality");
+        IVariable bestSolutionVariable = scope.GetVariable(scope.TranslateName("BestSolution"));
+        if(bestSolutionVariable != null) {
+
+          double bestQuality = ((IScope)bestSolutionVariable.Value).GetVariableValue<DoubleData>(qualityInfo.ActualName, false).Data;
+
+          // do nothing if the best solution of the current scope is not better than the best solution of the whole run so far.
+          if((maximization && biggest <= bestQuality) ||
+            (!maximization && smallest >= bestQuality)) return null;
+        }
+
+        IScope bestSolutionClone;
+        if(maximization) {
+          bestSolutionClone = (IScope)scope.SubScopes[biggestIndex].Clone();
+        } else {
+          bestSolutionClone = (IScope)scope.SubScopes[smallestIndex].Clone();
+        }
+
+        if(SubOperators.Count > 0) {
+          scope.AddSubScope(bestSolutionClone);
+          scope.AddVariable(new Variable(Guid.ToString() + "-Active", new BoolData(true)));
+
+          CompositeOperation compOp = new CompositeOperation();
+          AtomicOperation operation = new AtomicOperation(SubOperators[0], bestSolutionClone);
+          AtomicOperation continuation = new AtomicOperation(this, scope);
+
+          compOp.AddOperation(operation);
+          compOp.AddOperation(continuation);
+          return compOp;
+        } else {
+          StoreBestSolution(bestSolutionClone, scope);
+          return null;
+        }
+      } else {  // operator already executed
+        scope.RemoveVariable(Guid.ToString() + "-Active");
+        IScope bestSolutionClone = scope.SubScopes[scope.SubScopes.Count - 1];
+        scope.RemoveSubScope(bestSolutionClone);
+
+        StoreBestSolution(bestSolutionClone, scope);
+        return null;
+      }
+    }
+
+    private void StoreBestSolution(IScope bestSolution, IScope scope) {
+      SetValue(GetVariableInfo("BestSolution"), bestSolution, scope);
+    }
+
+    private void SetValue(IVariableInfo info, IScope data, IScope scope) {
+      IVariable var = scope.GetVariable(info.ActualName);
+      if(var == null) {
+        var = new Variable(scope.TranslateName(info.FormalName), data);
+        scope.AddVariable(var);
+      } else {
+        var.Value = data;
+      }
+    }
+  }
+}
Index: /trunk/sources/HeuristicLab.Modeling/3.2/HeuristicLab.Modeling-3.2.csproj
===================================================================
--- /trunk/sources/HeuristicLab.Modeling/3.2/HeuristicLab.Modeling-3.2.csproj	(revision 2327)
+++ /trunk/sources/HeuristicLab.Modeling/3.2/HeuristicLab.Modeling-3.2.csproj	(revision 2328)
@@ -83,5 +83,8 @@
   <ItemGroup>
     <Compile Include="AnalyzerModel.cs" />
+    <Compile Include="BestSolutionStorer.cs" />
     <Compile Include="ClassificationProblemInjector.cs" />
+    <Compile Include="SolutionExtractor.cs" />
+    <Compile Include="PredictorBase.cs" />
     <Compile Include="IAnalyzerModel.cs" />
     <Compile Include="MatrixCreator.cs" />
Index: /trunk/sources/HeuristicLab.Modeling/3.2/IPredictor.cs
===================================================================
--- /trunk/sources/HeuristicLab.Modeling/3.2/IPredictor.cs	(revision 2327)
+++ /trunk/sources/HeuristicLab.Modeling/3.2/IPredictor.cs	(revision 2328)
@@ -28,4 +28,6 @@
 namespace HeuristicLab.Modeling {
   public interface IPredictor : IItem {
+    double UpperPredictionLimit { get; set; }
+    double LowerPredictionLimit { get; set; }
     double[] Predict(Dataset dataset, int start, int end);
   } 
Index: /trunk/sources/HeuristicLab.Modeling/3.2/PredictorBase.cs
===================================================================
--- /trunk/sources/HeuristicLab.Modeling/3.2/PredictorBase.cs	(revision 2328)
+++ /trunk/sources/HeuristicLab.Modeling/3.2/PredictorBase.cs	(revision 2328)
@@ -0,0 +1,65 @@
+#region License Information
+/* HeuristicLab
+ * Copyright (C) 2002-2008 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.Text;
+using HeuristicLab.Core;
+using HeuristicLab.DataAnalysis;
+using System.Xml;
+
+namespace HeuristicLab.Modeling {
+  public abstract class PredictorBase : ItemBase, IPredictor {
+    public double UpperPredictionLimit { get; set; }
+    public double LowerPredictionLimit { get; set; }
+    public abstract double[] Predict(Dataset dataset, int start, int end);
+
+    public PredictorBase() : this(double.MinValue, double.MaxValue) { } // for persistence
+    public PredictorBase(double lowerPredictionLimit, double upperPredictionLimit)
+      : base() {
+      this.UpperPredictionLimit = upperPredictionLimit;
+      this.LowerPredictionLimit = lowerPredictionLimit;
+    }
+
+    public override object Clone(IDictionary<Guid, object> clonedObjects) {
+      PredictorBase clone = (PredictorBase)base.Clone(clonedObjects);
+      clone.UpperPredictionLimit = UpperPredictionLimit;
+      clone.LowerPredictionLimit = LowerPredictionLimit;
+      return clone;
+    }
+
+    public override System.Xml.XmlNode GetXmlNode(string name, System.Xml.XmlDocument document, IDictionary<Guid, IStorable> persistedObjects) {
+      XmlNode node = base.GetXmlNode(name, document, persistedObjects);
+      XmlAttribute minValue = document.CreateAttribute("LowerPredictionLimit");
+      minValue.Value = XmlConvert.ToString(LowerPredictionLimit);
+      XmlAttribute maxValue = document.CreateAttribute("UpperPredictionLimit");
+      maxValue.Value = XmlConvert.ToString(UpperPredictionLimit);
+      node.Attributes.Append(minValue); node.Attributes.Append(maxValue);
+      return node;
+    }
+
+    public override void Populate(System.Xml.XmlNode node, IDictionary<Guid, IStorable> restoredObjects) {
+      base.Populate(node, restoredObjects);
+      LowerPredictionLimit = XmlConvert.ToDouble(node.Attributes["LowerPredictionLimit"].Value);
+      UpperPredictionLimit = XmlConvert.ToDouble(node.Attributes["UpperPredictionLimit"].Value);
+    }
+  } 
+}
Index: /trunk/sources/HeuristicLab.SupportVectorMachines/3.2/HeuristicLab.SupportVectorMachines-3.2.csproj
===================================================================
--- /trunk/sources/HeuristicLab.SupportVectorMachines/3.2/HeuristicLab.SupportVectorMachines-3.2.csproj	(revision 2327)
+++ /trunk/sources/HeuristicLab.SupportVectorMachines/3.2/HeuristicLab.SupportVectorMachines-3.2.csproj	(revision 2328)
@@ -83,4 +83,10 @@
   </ItemGroup>
   <ItemGroup>
+    <Compile Include="PredictorView.cs">
+      <SubType>UserControl</SubType>
+    </Compile>
+    <Compile Include="PredictorView.Designer.cs">
+      <DependentUpon>PredictorView.cs</DependentUpon>
+    </Compile>
     <Compile Include="Predictor.cs" />
     <Compile Include="PredictorBuilder.cs" />
@@ -154,4 +160,7 @@
   </ItemGroup>
   <ItemGroup>
+    <EmbeddedResource Include="PredictorView.resx">
+      <DependentUpon>PredictorView.cs</DependentUpon>
+    </EmbeddedResource>
     <EmbeddedResource Include="SVMModelView.resx">
       <DependentUpon>SVMModelView.cs</DependentUpon>
Index: /trunk/sources/HeuristicLab.SupportVectorMachines/3.2/Predictor.cs
===================================================================
--- /trunk/sources/HeuristicLab.SupportVectorMachines/3.2/Predictor.cs	(revision 2327)
+++ /trunk/sources/HeuristicLab.SupportVectorMachines/3.2/Predictor.cs	(revision 2328)
@@ -32,6 +32,10 @@
 
 namespace HeuristicLab.SupportVectorMachines {
-  public class Predictor : ItemBase, IPredictor {
+  public class Predictor : PredictorBase {
     private SVMModel svmModel;
+    public SVMModel Model {
+      get { return svmModel; }
+    }
+
     private Dictionary<string, int> variableNames = new Dictionary<string, int>();
     private string targetVariable;
@@ -46,5 +50,5 @@
     }
 
-    public double[] Predict(Dataset input, int start, int end) {
+    public override double[] Predict(Dataset input, int start, int end) {
       if (start < 0 || end <= start) throw new ArgumentException("start must be larger than zero and strictly smaller than end");
       if (end > input.Rows) throw new ArgumentOutOfRangeException("number of rows in input is smaller then end");
@@ -64,5 +68,5 @@
       double[] result = new double[rows];
       for (int row = 0; row < rows; row++) {
-        result[row] = SVM.Prediction.Predict(model, scaledProblem.X[row]);
+        result[row] = Math.Max(Math.Min(SVM.Prediction.Predict(model, scaledProblem.X[row]), UpperPredictionLimit), LowerPredictionLimit);
       }
       return result;
@@ -70,5 +74,5 @@
 
     public override IView CreateView() {
-      return svmModel.CreateView();
+      return new PredictorView(this);
     }
 
Index: /trunk/sources/HeuristicLab.SupportVectorMachines/3.2/PredictorBuilder.cs
===================================================================
--- /trunk/sources/HeuristicLab.SupportVectorMachines/3.2/PredictorBuilder.cs	(revision 2327)
+++ /trunk/sources/HeuristicLab.SupportVectorMachines/3.2/PredictorBuilder.cs	(revision 2328)
@@ -37,4 +37,7 @@
       AddVariableInfo(new VariableInfo("TargetVariable", "The target variable", typeof(StringData), VariableKind.In));
       AddVariableInfo(new VariableInfo("InputVariables", "The input variable names", typeof(StringData), VariableKind.In));
+      AddVariableInfo(new VariableInfo("TrainingSamplesStart", "Start index of the training set", typeof(IntData), VariableKind.In));
+      AddVariableInfo(new VariableInfo("TrainingSamplesEnd", "End index of the training set", typeof(IntData), VariableKind.In));
+      AddVariableInfo(new VariableInfo("PunishmentFactor", "The punishment factor limits the range of predicted values", typeof(DoubleData), VariableKind.In));
       AddVariableInfo(new VariableInfo("Predictor", "The predictor can be used to generate estimated values", typeof(IPredictor), VariableKind.New));
     }
@@ -48,4 +51,8 @@
       SVMModel model = GetVariableValue<SVMModel>("SVMModel", scope, true);
       int targetVariable = GetVariableValue<IntData>("TargetVariable", scope, true).Data;
+      int start = GetVariableValue<IntData>("TrainingSamplesStart", scope, true).Data;
+      int end = GetVariableValue<IntData>("TrainingSamplesEnd", scope, true).Data;
+      double punishmentFactor = GetVariableValue<DoubleData>("PunishmentFactor", scope, true).Data;
+
       string targetVariableName = ds.GetVariableName(targetVariable);
       ItemList inputVariables = GetVariableValue<ItemList>("InputVariables", scope, true);
@@ -53,5 +60,11 @@
       for (int i = 0; i < ds.Columns; i++) variableNames[ds.GetVariableName(i)] = i;
 
-      scope.AddVariable(new HeuristicLab.Core.Variable(scope.TranslateName("Predictor"), new Predictor(model, targetVariableName, variableNames)));
+      double mean = ds.GetMean(targetVariable, start, end);
+      double range = ds.GetRange(targetVariable, start, end);
+
+      Predictor predictor = new Predictor(model, targetVariableName, variableNames);
+      predictor.LowerPredictionLimit = mean - punishmentFactor * range;
+      predictor.UpperPredictionLimit = mean + punishmentFactor * range;
+      scope.AddVariable(new HeuristicLab.Core.Variable(scope.TranslateName("Predictor"), predictor));
       return null;
     }
Index: /trunk/sources/HeuristicLab.SupportVectorMachines/3.2/SVMModelView.cs
===================================================================
--- /trunk/sources/HeuristicLab.SupportVectorMachines/3.2/SVMModelView.cs	(revision 2327)
+++ /trunk/sources/HeuristicLab.SupportVectorMachines/3.2/SVMModelView.cs	(revision 2328)
@@ -33,20 +33,17 @@
   public partial class SVMModelView : ViewBase {
     private SVMModel model;
-    
+    public SVMModelView() : base() {
+      InitializeComponent();
+    }    
     public SVMModelView(SVMModel model) : base() {
       InitializeComponent();
       this.model = model;
-      model.Changed += (sender, args) => UpdateControls();
+      model.Changed += (sender, args) => Refresh();
 
-      UpdateControls();
-    }
-
-    protected override void UpdateControls() {
-      base.UpdateControls();
-      numberOfSupportVectors.Text = model.Model.SupportVectorCount.ToString();
-      rho.Text = model.Model.Rho[0].ToString();
-      svmType.Text = model.Model.Parameter.SvmType.ToString();
-      kernelType.Text = model.Model.Parameter.KernelType.ToString();
-      gamma.Text = model.Model.Parameter.Gamma.ToString();
+      numberOfSupportVectors.DataBindings.Add(new Binding("Text", model.Model, "SupportVectorCount"));
+      rho.DataBindings.Add(new Binding("Text", model.Model, "Rho"));
+      svmType.DataBindings.Add(new Binding("Text", model.Model.Parameter, "SvmType"));
+      kernelType.DataBindings.Add(new Binding("Text", model.Model.Parameter, "KernelType"));
+      gamma.DataBindings.Add(new Binding("Text", model.Model.Parameter, "Gamma"));
     }
   }
Index: /trunk/sources/HeuristicLab.SupportVectorMachines/3.2/SupportVectorRegression.cs
===================================================================
--- /trunk/sources/HeuristicLab.SupportVectorMachines/3.2/SupportVectorRegression.cs	(revision 2327)
+++ /trunk/sources/HeuristicLab.SupportVectorMachines/3.2/SupportVectorRegression.cs	(revision 2328)
@@ -394,4 +394,5 @@
       injector.AddVariable(new HeuristicLab.Core.Variable("KernelType", new StringData("RBF")));
       injector.AddVariable(new HeuristicLab.Core.Variable("Type", new StringData("NU_SVR")));
+      injector.AddVariable(new HeuristicLab.Core.Variable("PunishmentFactor", new DoubleData(1000.0)));
 
       return injector;
