Index: stable/HeuristicLab.Algorithms.DataAnalysis/3.4/GBM/GradientBoostingRegressionAlgorithm.cs
===================================================================
--- trunk/sources/HeuristicLab.Algorithms.DataAnalysis/3.4/GBM/GradientBoostingRegressionAlgorithm.cs	(revision 13646)
+++ stable/HeuristicLab.Algorithms.DataAnalysis/3.4/GBM/GradientBoostingRegressionAlgorithm.cs	(revision 13977)
@@ -37,4 +37,5 @@
 using HeuristicLab.Problems.DataAnalysis.Symbolic.Regression;
 using HeuristicLab.Random;
+using HeuristicLab.Selection;
 
 namespace HeuristicLab.Algorithms.DataAnalysis.MctsSymbolicRegression {
@@ -63,4 +64,5 @@
     private const string SetSeedRandomlyParameterName = "SetSeedRandomly";
     private const string CreateSolutionParameterName = "CreateSolution";
+    private const string StoreRunsParameterName = "StoreRuns";
     private const string RegressionAlgorithmSolutionResultParameterName = "RegressionAlgorithmResult";
 
@@ -105,4 +107,7 @@
       get { return (IFixedValueParameter<BoolValue>)Parameters[CreateSolutionParameterName]; }
     }
+    public IFixedValueParameter<BoolValue> StoreRunsParameter {
+      get { return (IFixedValueParameter<BoolValue>)Parameters[StoreRunsParameterName]; }
+    }
 
     #endregion
@@ -145,4 +150,9 @@
     }
 
+    public bool StoreRuns {
+      get { return StoreRunsParameter.Value.Value; }
+      set { StoreRunsParameter.Value.Value = value; }
+    }
+
     public IAlgorithm RegressionAlgorithm {
       get { return RegressionAlgorithmParameter.Value; }
@@ -172,8 +182,10 @@
       Problem = new RegressionProblem(); // default problem
       var mctsSymbReg = new MctsSymbolicRegressionAlgorithm();
-      // var sgp = CreateSGP();
+      mctsSymbReg.Iterations = 10000;
+      mctsSymbReg.StoreAlgorithmInEachRun = false;
+      var sgp = CreateOSGP();
       var regressionAlgs = new ItemSet<IAlgorithm>(new IAlgorithm[] {
-        new LinearRegression(), new RandomForestRegression(), new NearestNeighbourRegression(),
-        // sgp, 
+        new RandomForestRegression(),
+        sgp,
         mctsSymbReg
       });
@@ -203,4 +215,7 @@
         "Flag that indicates if a solution should be produced at the end of the run", new BoolValue(true)));
       Parameters[CreateSolutionParameterName].Hidden = true;
+      Parameters.Add(new FixedValueParameter<BoolValue>(StoreRunsParameterName,
+        "Flag that indicates if the results of the individual runs should be stored for detailed analysis", new BoolValue(false)));
+      Parameters[StoreRunsParameterName].Hidden = true;
     }
 
@@ -215,20 +230,22 @@
 
       var table = new DataTable("Qualities");
-      table.Rows.Add(new DataRow("Loss (train)"));
-      table.Rows.Add(new DataRow("Loss (test)"));
+      table.Rows.Add(new DataRow("R² (train)"));
+      table.Rows.Add(new DataRow("R² (test)"));
       Results.Add(new Result("Qualities", table));
       var curLoss = new DoubleValue();
       var curTestLoss = new DoubleValue();
-      Results.Add(new Result("Loss (train)", curLoss));
-      Results.Add(new Result("Loss (test)", curTestLoss));
+      Results.Add(new Result("R² (train)", curLoss));
+      Results.Add(new Result("R² (test)", curTestLoss));
       var runCollection = new RunCollection();
-      Results.Add(new Result("Runs", runCollection));
+      if (StoreRuns)
+        Results.Add(new Result("Runs", runCollection));
 
       // init
       var problemData = Problem.ProblemData;
-      var targetVarName = Problem.ProblemData.TargetVariable;
+      var targetVarName = problemData.TargetVariable;
+      var activeVariables = problemData.AllowedInputVariables.Concat(new string[] { problemData.TargetVariable });
       var modifiableDataset = new ModifiableDataset(
-        problemData.Dataset.VariableNames,
-        problemData.Dataset.VariableNames.Select(v => problemData.Dataset.GetDoubleValues(v).ToList()));
+        activeVariables,
+        activeVariables.Select(v => problemData.Dataset.GetDoubleValues(v).ToList()));
 
       var trainingRows = problemData.TrainingIndices;
@@ -269,6 +286,7 @@
           IRegressionModel model;
           IRun run;
+
           // try to find a model. The algorithm might fail to produce a model. In this case we just retry until the iterations are exhausted
-          if (TryExecute(alg, RegressionAlgorithmResult, out model, out run)) {
+          if (TryExecute(alg, rand.Next(), RegressionAlgorithmResult, out model, out run)) {
             int row = 0;
             // update predictions for training and test
@@ -299,7 +317,8 @@
           }
 
-          runCollection.Add(run);
-          table.Rows["Loss (train)"].Values.Add(curLoss.Value);
-          table.Rows["Loss (test)"].Values.Add(curTestLoss.Value);
+          if (StoreRuns)
+            runCollection.Add(run);
+          table.Rows["R² (train)"].Values.Add(curLoss.Value);
+          table.Rows["R² (test)"].Values.Add(curTestLoss.Value);
           iterations.Value = i + 1;
         }
@@ -312,7 +331,10 @@
           }
           // just produce an ensemble solution for now (TODO: correct scaling or linear regression for ensemble model weights)
-          Results.Add(new Result("EnsembleSolution", new RegressionEnsembleSolution(models, (IRegressionProblemData)problemData.Clone())));
+
+          var ensembleSolution = CreateEnsembleSolution(models, (IRegressionProblemData)problemData.Clone());
+          Results.Add(new Result("EnsembleSolution", ensembleSolution));
         }
-      } finally {
+      }
+      finally {
         // reset everything
         alg.Prepare(true);
@@ -320,5 +342,63 @@
     }
 
-    // this is probably slow as hell
+    private static IRegressionEnsembleSolution CreateEnsembleSolution(List<IRegressionModel> models,
+      IRegressionProblemData problemData) {
+      var rows = problemData.TrainingPartition.Size;
+      var features = models.Count;
+      double[,] inputMatrix = new double[rows, features + 1];
+      //add model estimates
+      for (int m = 0; m < models.Count; m++) {
+        var model = models[m];
+        var estimates = model.GetEstimatedValues(problemData.Dataset, problemData.TrainingIndices);
+        int estimatesCounter = 0;
+        foreach (var estimate in estimates) {
+          inputMatrix[estimatesCounter, m] = estimate;
+          estimatesCounter++;
+        }
+      }
+
+      //add target
+      var targets = problemData.Dataset.GetDoubleValues(problemData.TargetVariable, problemData.TrainingIndices);
+      int targetCounter = 0;
+      foreach (var target in targets) {
+        inputMatrix[targetCounter, models.Count] = target;
+        targetCounter++;
+      }
+
+      alglib.linearmodel lm = new alglib.linearmodel();
+      alglib.lrreport ar = new alglib.lrreport();
+      double[] coefficients;
+      int retVal = 1;
+      alglib.lrbuildz(inputMatrix, rows, features, out retVal, out lm, out ar);
+      if (retVal != 1) throw new ArgumentException("Error in calculation of linear regression solution");
+
+      alglib.lrunpack(lm, out coefficients, out features);
+
+      var ensembleModel = new RegressionEnsembleModel(models, coefficients.Take(models.Count)) { AverageModelEstimates = false };
+      var ensembleSolution = ensembleModel.CreateRegressionSolution(problemData);
+      return ensembleSolution;
+    }
+
+
+    private IAlgorithm CreateOSGP() {
+      // configure strict osgp
+      var alg = new OffspringSelectionGeneticAlgorithm.OffspringSelectionGeneticAlgorithm();
+      var prob = new SymbolicRegressionSingleObjectiveProblem();
+      prob.MaximumSymbolicExpressionTreeDepth.Value = 7;
+      prob.MaximumSymbolicExpressionTreeLength.Value = 15;
+      alg.Problem = prob;
+      alg.SuccessRatio.Value = 1.0;
+      alg.ComparisonFactorLowerBound.Value = 1.0;
+      alg.ComparisonFactorUpperBound.Value = 1.0;
+      alg.MutationProbability.Value = 0.15;
+      alg.PopulationSize.Value = 200;
+      alg.MaximumSelectionPressure.Value = 100;
+      alg.MaximumEvaluatedSolutions.Value = 20000;
+      alg.SelectorParameter.Value = alg.SelectorParameter.ValidValues.OfType<GenderSpecificSelector>().First();
+      alg.MutatorParameter.Value = alg.MutatorParameter.ValidValues.OfType<MultiSymbolicExpressionTreeManipulator>().First();
+      alg.StoreAlgorithmInEachRun = false;
+      return alg;
+    }
+
     private void SampleTrainingData(MersenneTwister rand, ModifiableDataset ds, int rRows,
       IDataset sourceDs, double[] curTarget, string targetVarName, IEnumerable<int> trainingIndices) {
@@ -374,22 +454,16 @@
         prob.ProblemDataParameter.Value = problemData;
         return true;
-      } else if (alg.Problem != null) {
-        // a problem is set and it is not compatible
-        return false;
-      } else {
-        try {
-          // we try to use a symbolic regression problem (works for simple regression algs and GP)
-          alg.Problem = new SymbolicRegressionSingleObjectiveProblem();
-        } catch (Exception) {
-          return false;
-        }
-        return true;
-      }
-    }
-
-    private static bool TryExecute(IAlgorithm alg, string regressionAlgorithmResultName, out IRegressionModel model, out IRun run) {
+      } else return false;
+    }
+
+    private static bool TryExecute(IAlgorithm alg, int seed, string regressionAlgorithmResultName, out IRegressionModel model, out IRun run) {
       model = null;
+      SetSeed(alg, seed);
       using (var wh = new AutoResetEvent(false)) {
-        EventHandler<EventArgs<Exception>> handler = (sender, args) => wh.Set();
+        Exception ex = null;
+        EventHandler<EventArgs<Exception>> handler = (sender, args) => {
+          ex = args.Value;
+          wh.Set();
+        };
         EventHandler handler2 = (sender, args) => wh.Set();
         alg.ExceptionOccurred += handler;
@@ -400,5 +474,7 @@
           wh.WaitOne();
 
+          if (ex != null) throw new AggregateException(ex);
           run = alg.Runs.Last();
+          alg.Runs.Clear();
           var sols = alg.Results.Select(r => r.Value).OfType<IRegressionSolution>();
           if (!sols.Any()) return false;
@@ -419,5 +495,6 @@
             model = sol.Model;
           }
-        } finally {
+        }
+        finally {
           alg.ExceptionOccurred -= handler;
           alg.Stopped -= handler2;
@@ -426,4 +503,17 @@
       return model != null;
     }
+
+    private static void SetSeed(IAlgorithm alg, int seed) {
+      // no common interface for algs that use a PRNG -> use naming convention to set seed
+      var paramItem = alg as IParameterizedItem;
+
+      if (paramItem.Parameters.ContainsKey("SetSeedRandomly")) {
+        ((BoolValue)paramItem.Parameters["SetSeedRandomly"].ActualValue).Value = false;
+        ((IntValue)paramItem.Parameters["Seed"].ActualValue).Value = seed;
+      } else {
+        throw new ArgumentException("Base learner does not have a seed parameter (algorithm {0})", alg.Name);
+      }
+
+    }
   }
 }
