Index: /branches/MathNetNumerics-Exploration-2789/HeuristicLab.Algorithms.DataAnalysis.Experimental/ForwardSelection.cs
===================================================================
--- /branches/MathNetNumerics-Exploration-2789/HeuristicLab.Algorithms.DataAnalysis.Experimental/ForwardSelection.cs	(revision 14998)
+++ /branches/MathNetNumerics-Exploration-2789/HeuristicLab.Algorithms.DataAnalysis.Experimental/ForwardSelection.cs	(revision 14998)
@@ -0,0 +1,180 @@
+﻿#region License Information
+/* HeuristicLab
+ * Copyright (C) 2002-2016 Heuristic and Evolutionary Algorithms Laboratory (HEAL)
+ *
+ * This file is part of HeuristicLab.
+ *
+ * HeuristicLab is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * HeuristicLab is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with HeuristicLab. If not, see <http://www.gnu.org/licenses/>.
+ */
+#endregion
+
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Threading;
+using HeuristicLab.Analysis;
+using HeuristicLab.Common;
+using HeuristicLab.Core;
+using HeuristicLab.Data;
+using HeuristicLab.Optimization;
+using HeuristicLab.Parameters;
+using HeuristicLab.Persistence.Default.CompositeSerializers.Storable;
+using HeuristicLab.Problems.DataAnalysis;
+
+namespace HeuristicLab.Algorithms.DataAnalysis.Experimental {
+  /// <summary>
+  /// Forward selection meta-algorithm.
+  /// </summary>
+  [Item("Forward Selection", "Meta-algorithm that performs feature selection for a given base algorithm using greedy forward selection.")]
+  [Creatable(CreatableAttribute.Categories.DataAnalysisRegression, Priority = 999)]
+  [StorableClass]
+  public sealed class ForwardsSelectionAlgorithm : FixedDataAnalysisAlgorithm<IRegressionProblem> {
+    public IFixedValueParameter<IntValue> MaximumInputsParameter {
+      get { return (IFixedValueParameter<IntValue>)Parameters["Maximum Inputs"]; }
+    }
+    public int MaximumInputs {
+      get { return MaximumInputsParameter.Value.Value; }
+      set { MaximumInputsParameter.Value.Value = value; }
+    }
+
+    public IValueParameter<FixedDataAnalysisAlgorithm<IRegressionProblem>> AlgorithmParameter {
+      get { return (IValueParameter<FixedDataAnalysisAlgorithm<IRegressionProblem>>)Parameters["Algorithm"]; }
+    }
+
+    public FixedDataAnalysisAlgorithm<IRegressionProblem> Algorithm {
+      get { return AlgorithmParameter.Value; }
+      set { AlgorithmParameter.Value = value; }
+    }
+
+
+    [StorableConstructor]
+    private ForwardsSelectionAlgorithm(bool deserializing) : base(deserializing) { }
+    [StorableHook(HookType.AfterDeserialization)]
+    private void AfterDeserialization() {
+      RegisterEventHandlers();
+    }
+
+    private ForwardsSelectionAlgorithm(ForwardsSelectionAlgorithm original, Cloner cloner)
+      : base(original, cloner) {
+      RegisterEventHandlers();
+    }
+    public override IDeepCloneable Clone(Cloner cloner) {
+      return new ForwardsSelectionAlgorithm(this, cloner);
+    }
+
+    public ForwardsSelectionAlgorithm()
+      : base() {
+      Parameters.Add(new FixedValueParameter<IntValue>("Maximum Inputs", "The maximum number of input variables used in the models.", new IntValue(1)));
+      Parameters.Add(new ValueParameter<FixedDataAnalysisAlgorithm<IRegressionProblem>>("Algorithm", "The base algorithm for modeling", new LinearRegression()));
+
+      Problem = new RegressionProblem();
+      RegisterEventHandlers();
+    }
+
+    private void RegisterEventHandlers() {
+      Problem.ProblemDataChanged += (o, e) => { MaximumInputs = Problem.ProblemData.InputVariables.CheckedItems
+        .Select(t => t.Value)
+        .Where(v => Problem.ProblemData.Dataset.VariableHasType<double>(v.Value))
+        .Count();
+      };
+    }
+    protected override void OnProblemChanged() {
+      base.OnProblemChanged();
+      MaximumInputs = Problem.ProblemData.InputVariables.CheckedItems
+        .Select(t => t.Value)
+        .Where(v => Problem.ProblemData.Dataset.VariableHasType<double>(v.Value))
+        .Count();
+    }
+
+    protected override void Run(CancellationToken cancellationToken) {
+      InitResults();
+      var problemClone = (IRegressionProblem)Problem.Clone();
+      var problemDataClone = (IRegressionProblemData)problemClone.ProblemData;
+      var allowedInputVariables = problemDataClone.InputVariables.CheckedItems.Select(t=>t.Value)
+        .Where(v => problemDataClone.Dataset.VariableHasType<double>(v.Value))
+        .ToList();
+      foreach (var variable in problemDataClone.InputVariables)
+        problemDataClone.InputVariables.SetItemCheckedState(variable, false);
+
+      var alg = Algorithm;
+      alg.Problem = problemClone;
+
+      for (int inputs = 1; inputs <= MaximumInputs; inputs++) {
+        var bestRMSE = double.MaxValue;
+        IRegressionSolution bestSolution = null;
+        StringValue bestInput = null;
+        foreach (var inputVar in allowedInputVariables) {
+          if (cancellationToken.IsCancellationRequested) {
+            cancellationToken.ThrowIfCancellationRequested();
+          }
+
+          problemDataClone.InputVariables.SetItemCheckedState(inputVar, true);
+          var solution = RunAlg(alg);
+          if (solution != null && solution.TrainingRootMeanSquaredError < bestRMSE) {
+            bestRMSE = solution.TrainingRootMeanSquaredError;
+            bestSolution = solution;
+            bestInput = inputVar;
+          }
+          problemDataClone.InputVariables.SetItemCheckedState(inputVar, false);
+        }
+
+        allowedInputVariables.Remove(bestInput);
+        problemDataClone.InputVariables.SetItemCheckedState(bestInput, true);
+
+        bestSolution.Name = inputs.ToString() + " " + bestSolution.Name;
+        Results["Current solution"].Value = bestSolution;
+        ((ItemList<IRegressionSolution>)Results["All Solutions"].Value).Add(bestSolution);
+        ((IntValue)Results["Number of variables"].Value).Value = inputs;
+        ((DataTable)Results["RMSE table"].Value).Rows["RMSE (train)"].Values.Add(bestSolution.TrainingRootMeanSquaredError);
+        ((DataTable)Results["RMSE table"].Value).Rows["RMSE (test)"].Values.Add(bestSolution.TestRootMeanSquaredError);
+
+        if (cancellationToken.IsCancellationRequested) {
+          cancellationToken.ThrowIfCancellationRequested();
+        }
+      }
+    }
+
+    private void InitResults() {
+      Results.Add(new Result("Current solution", typeof(IRegressionSolution)));
+      Results.Add(new Result("All Solutions", new ItemList<IRegressionSolution>()));
+      Results.Add(new Result("Number of variables", new IntValue(0)));
+      var rmseTable = new DataTable("RMSE table");
+      var trainingRmseRow = new DataRow("RMSE (train)");
+      var testRmseRow = new DataRow("RMSE (test)");
+      rmseTable.Rows.Add(trainingRmseRow);
+      rmseTable.Rows.Add(testRmseRow);
+      Results.Add(new Result("RMSE table", rmseTable));
+    }
+
+    private IRegressionSolution RunAlg(FixedDataAnalysisAlgorithm<IRegressionProblem> alg) {
+      using (var wh = new AutoResetEvent(false)) {
+        EventHandler<EventArgs<Exception>> setWhForException = (sender, args) => { wh.Set(); };
+        EventHandler setWh = (sender, args) => { wh.Set(); };
+        try {
+          alg.ExceptionOccurred += setWhForException;
+          alg.Stopped += setWh;
+          alg.Prepare(true);
+          alg.Start();
+
+          wh.WaitOne();
+
+          return alg.Results.Select(r => r.Value).OfType<IRegressionSolution>().FirstOrDefault();
+        } finally {
+          alg.ExceptionOccurred -= setWhForException;
+          alg.Stopped -= setWh;
+        }
+      }
+    }
+  }
+}
Index: /branches/MathNetNumerics-Exploration-2789/HeuristicLab.Algorithms.DataAnalysis.Experimental/HeuristicLab.Algorithms.DataAnalysis.Experimental.csproj
===================================================================
--- /branches/MathNetNumerics-Exploration-2789/HeuristicLab.Algorithms.DataAnalysis.Experimental/HeuristicLab.Algorithms.DataAnalysis.Experimental.csproj	(revision 14997)
+++ /branches/MathNetNumerics-Exploration-2789/HeuristicLab.Algorithms.DataAnalysis.Experimental/HeuristicLab.Algorithms.DataAnalysis.Experimental.csproj	(revision 14998)
@@ -32,7 +32,15 @@
   </PropertyGroup>
   <ItemGroup>
+    <Reference Include="ALGLIB-3.7.0, Version=3.7.0.0, Culture=neutral, PublicKeyToken=ba48961d6f65dcec, processorArchitecture=MSIL">
+      <SpecificVersion>False</SpecificVersion>
+      <HintPath>..\..\..\trunk\sources\bin\ALGLIB-3.7.0.dll</HintPath>
+    </Reference>
     <Reference Include="HeuristicLab.Algorithms.DataAnalysis-3.4">
       <HintPath>..\..\trunk\sources\bin\HeuristicLab.Algorithms.DataAnalysis-3.4.dll</HintPath>
       <Private>False</Private>
+    </Reference>
+    <Reference Include="HeuristicLab.Analysis-3.3, Version=3.3.0.0, Culture=neutral, PublicKeyToken=ba48961d6f65dcec, processorArchitecture=MSIL">
+      <SpecificVersion>False</SpecificVersion>
+      <HintPath>..\..\..\trunk\sources\bin\HeuristicLab.Analysis-3.3.dll</HintPath>
     </Reference>
     <Reference Include="HeuristicLab.Collections-3.3, Version=3.3.0.0, Culture=neutral, PublicKeyToken=ba48961d6f65dcec, processorArchitecture=MSIL">
@@ -51,4 +59,8 @@
     </Reference>
     <Reference Include="HeuristicLab.Encodings.RealVectorEncoding-3.3, Version=3.3.0.0, Culture=neutral, PublicKeyToken=ba48961d6f65dcec" />
+    <Reference Include="HeuristicLab.Encodings.SymbolicExpressionTreeEncoding-3.4, Version=3.4.0.0, Culture=neutral, PublicKeyToken=ba48961d6f65dcec, processorArchitecture=MSIL">
+      <SpecificVersion>False</SpecificVersion>
+      <HintPath>..\..\..\trunk\sources\bin\HeuristicLab.Encodings.SymbolicExpressionTreeEncoding-3.4.dll</HintPath>
+    </Reference>
     <Reference Include="HeuristicLab.Operators-3.3, Version=3.3.0.0, Culture=neutral, PublicKeyToken=ba48961d6f65dcec, processorArchitecture=MSIL">
       <SpecificVersion>False</SpecificVersion>
@@ -76,4 +88,13 @@
       <Private>False</Private>
     </Reference>
+    <Reference Include="HeuristicLab.Problems.DataAnalysis.Symbolic-3.4, Version=3.4.0.0, Culture=neutral, PublicKeyToken=ba48961d6f65dcec, processorArchitecture=MSIL">
+      <SpecificVersion>False</SpecificVersion>
+      <HintPath>..\..\..\trunk\sources\bin\HeuristicLab.Problems.DataAnalysis.Symbolic-3.4.dll</HintPath>
+    </Reference>
+    <Reference Include="HeuristicLab.Problems.DataAnalysis.Symbolic.Regression-3.4, Version=3.4.0.0, Culture=neutral, PublicKeyToken=ba48961d6f65dcec, processorArchitecture=MSIL">
+      <SpecificVersion>False</SpecificVersion>
+      <HintPath>..\..\..\trunk\sources\bin\HeuristicLab.Problems.DataAnalysis.Symbolic.Regression-3.4.dll</HintPath>
+    </Reference>
+    <Reference Include="HeuristicLab.Problems.Instances-3.3, Version=3.3.0.0, Culture=neutral, PublicKeyToken=ba48961d6f65dcec" />
     <Reference Include="MathNet.Numerics, Version=3.19.0.0, Culture=neutral, PublicKeyToken=cd8b63ad3d691a37, processorArchitecture=MSIL">
       <SpecificVersion>False</SpecificVersion>
@@ -98,4 +119,6 @@
     <Compile Include="GaussianProcessModelMKL.cs" />
     <Compile Include="GaussianProcessRegressionModelCreatorMKL.cs" />
+    <Compile Include="ForwardSelection.cs" />
+    <Compile Include="LinearRegressionCombinations.cs" />
     <Compile Include="Plugin.cs" />
     <Compile Include="Properties\AssemblyInfo.cs" />
Index: /branches/MathNetNumerics-Exploration-2789/HeuristicLab.Algorithms.DataAnalysis.Experimental/LinearRegressionCombinations.cs
===================================================================
--- /branches/MathNetNumerics-Exploration-2789/HeuristicLab.Algorithms.DataAnalysis.Experimental/LinearRegressionCombinations.cs	(revision 14998)
+++ /branches/MathNetNumerics-Exploration-2789/HeuristicLab.Algorithms.DataAnalysis.Experimental/LinearRegressionCombinations.cs	(revision 14998)
@@ -0,0 +1,253 @@
+﻿#region License Information
+/* HeuristicLab
+ * Copyright (C) 2002-2016 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.Concurrent;
+using System.Collections.Generic;
+using System.Linq;
+using System.Threading;
+using System.Threading.Tasks;
+using HeuristicLab.Common;
+using HeuristicLab.Core;
+using HeuristicLab.Data;
+using HeuristicLab.Encodings.SymbolicExpressionTreeEncoding;
+using HeuristicLab.Optimization;
+using HeuristicLab.Parameters;
+using HeuristicLab.Persistence.Default.CompositeSerializers.Storable;
+using HeuristicLab.Problems.DataAnalysis;
+using HeuristicLab.Problems.DataAnalysis.Symbolic;
+using HeuristicLab.Problems.DataAnalysis.Symbolic.Regression;
+
+namespace HeuristicLab.Algorithms.DataAnalysis.Experimental {
+  /// <summary>
+  /// Linear regression data analysis algorithm.
+  /// </summary>
+  [Item("Linear Regression Combinations (LR)", "Calculates all possible LR solutions.")]
+  [Creatable(CreatableAttribute.Categories.DataAnalysisRegression, Priority = 102)]
+  [StorableClass]
+  public sealed class LinearRegressionCombinations : FixedDataAnalysisAlgorithm<IRegressionProblem> {
+    public IFixedValueParameter<IntValue> MaximumInputsParameter {
+      get { return (IFixedValueParameter<IntValue>)Parameters["Maximum Inputs"]; }
+    }
+    public int MaximumInputs {
+      get { return MaximumInputsParameter.Value.Value; }
+      set { MaximumInputsParameter.Value.Value = value; }
+    }
+
+    public IFixedValueParameter<BoolValue> CreateSolutionParameter {
+      get { return (IFixedValueParameter<BoolValue>)Parameters["Create Solution"]; }
+    }
+    public bool CreateSolution {
+      get { return CreateSolutionParameter.Value.Value; }
+      set { CreateSolutionParameter.Value.Value = value; }
+    }
+
+    public IFixedValueParameter<IntValue> MaximumSolutionsParameter {
+      get { return (IFixedValueParameter<IntValue>)Parameters["Maximum Solutions stored"]; }
+    }
+    public int MaximumSolutions {
+      get { return MaximumSolutionsParameter.Value.Value; }
+      set { MaximumSolutionsParameter.Value.Value = value; }
+    }
+
+    private IntValue CalculatedModelsResults {
+      get {
+        if (!Results.ContainsKey("Calculated Models")) Results.Add(new Result("Calculated Models", "The number of calculated linear models ", new IntValue(0)));
+        return (IntValue)Results["Calculated Models"].Value;
+      }
+    }
+    public int CalculatedModels {
+      get { return CalculatedModelsResults.Value; }
+      set { CalculatedModelsResults.Value = value; }
+    }
+
+    private IntValue TotalModelsResult {
+      get {
+        if (!Results.ContainsKey("Total Models")) Results.Add(new Result("Total Models", "The total number of linear models to calculate", new IntValue(0)));
+        return (IntValue)Results["Total Models"].Value;
+      }
+    }
+    public int TotalModels {
+      get { return TotalModelsResult.Value; }
+      set { TotalModelsResult.Value = value; }
+    }
+
+    private IntValue CalculatedInputResults {
+      get {
+        if (!Results.ContainsKey("Calculated Inputs")) Results.Add(new Result("Calculated Inputs", "The maximum of already calculated input combinations.", new IntValue(0)));
+        return (IntValue)Results["Calculated Inputs"].Value;
+      }
+    }
+    public int CalculatedInputs {
+      get { return CalculatedInputResults.Value; }
+      set { CalculatedInputResults.Value = value; }
+    }
+
+    [StorableConstructor]
+    private LinearRegressionCombinations(bool deserializing) : base(deserializing) { }
+    [StorableHook(HookType.AfterDeserialization)]
+    private void AfterDeserialization() {
+      RegisterEventHandlers();
+    }
+
+    private LinearRegressionCombinations(LinearRegressionCombinations original, Cloner cloner)
+      : base(original, cloner) {
+      RegisterEventHandlers();
+    }
+    public override IDeepCloneable Clone(Cloner cloner) {
+      return new LinearRegressionCombinations(this, cloner);
+    }
+
+    public LinearRegressionCombinations()
+      : base() {
+      Parameters.Add(new FixedValueParameter<IntValue>("Maximum Inputs", "The maximum number of input variables used in the linear models.", new IntValue(1)));
+      Parameters.Add(new FixedValueParameter<IntValue>("Maximum Solutions stored", "The maximum number of solutions that are stored per number of inputs.", new IntValue(1000)));
+      Parameters.Add(new FixedValueParameter<BoolValue>("Create Solution", "Flag that indicates if a solution should be produced at the end of the run", new BoolValue(false)));
+
+      Problem = new RegressionProblem();
+      RegisterEventHandlers();
+    }
+
+    private void RegisterEventHandlers() {
+      Problem.ProblemDataChanged += (o, e) => { MaximumInputs = Problem.ProblemData.InputVariables.CheckedItems.Count(); };
+    }
+    protected override void OnProblemChanged() {
+      base.OnProblemChanged();
+      MaximumInputs = Problem.ProblemData.InputVariables.CheckedItems.Count();
+    }
+
+
+    private static long CalculateCombinations(int maximumInputs, int totalVariables) {
+      long combinations = 0;
+
+      for (int i = 1; i <= maximumInputs; i++)
+        combinations += Common.EnumerableExtensions.BinomialCoefficient(totalVariables, i);
+      return combinations;
+    }
+
+    protected override void Run(CancellationToken cancellationToken) {
+      double[,] inputMatrix = Problem.ProblemData.Dataset.ToArray(Problem.ProblemData.AllowedInputVariables.Concat(new string[] { Problem.ProblemData.TargetVariable }), Problem.ProblemData.TrainingIndices);
+      if (inputMatrix.Cast<double>().Any(x => double.IsNaN(x) || double.IsInfinity(x)))
+        throw new NotSupportedException("Linear regression does not support NaN or infinity values in the input dataset.");
+
+      var templateProblemData = (IRegressionProblemData)Problem.ProblemData.Clone();
+      foreach (var variable in templateProblemData.InputVariables)
+        templateProblemData.InputVariables.SetItemCheckedState(variable, false);
+
+      var inputVariableNames = Problem.ProblemData.InputVariables.CheckedItems.Select(i => i.Value.Value).ToList();
+      var createSolution = CreateSolution;
+      var maximumInputs = MaximumInputs;
+      var maximumSolutions = MaximumSolutions;
+
+      var storedRuns = new List<IRun>[maximumInputs];
+      var runs = new ConcurrentBag<IRun>();
+
+      TotalModels = (int)CalculateCombinations(MaximumInputs, inputVariableNames.Count);
+      CalculatedModels = 0;
+      CalculatedInputs = 0;
+
+      for (int inputs = 1; inputs <= MaximumInputs; inputs++) {
+        Parallel.ForEach(inputVariableNames.Combinations(inputs).ToList(), inputCombination => {
+          var problemData = new RegressionProblemData(templateProblemData.Dataset, inputCombination, templateProblemData.TargetVariable);
+          problemData.TrainingPartition.Start = templateProblemData.TrainingPartition.Start;
+          problemData.TrainingPartition.End = templateProblemData.TrainingPartition.End;
+          problemData.TestPartition.Start = templateProblemData.TestPartition.Start;
+          problemData.TestPartition.End = templateProblemData.TestPartition.End;
+
+          double trainRmsError, testRmsError;
+          var solution = CreateLinearRegressionSolution(problemData, createSolution, out trainRmsError, out testRmsError);
+
+          var run = new Run();
+          run.Name = string.Format("Run - Inputs {0}/{1}", inputCombination.Count(), MaximumInputs);
+          if (solution != null) run.Results.Add("Solution", solution);
+          run.Results.Add("RMSE train", new DoubleValue(trainRmsError));
+          run.Results.Add("RMSE test", new DoubleValue(testRmsError));
+          run.Results.Add("Inputs", new IntValue(inputCombination.Count()));
+          run.Results.Add("Input names", new StringValue(string.Join(" ", inputCombination)));
+          runs.Add(run);
+        });
+
+        CalculatedModels += runs.Count;
+        CalculatedInputs = inputs;
+        storedRuns[inputs - 1] = runs.OrderBy(r => ((DoubleValue)r.Results["RMSE test"]).Value).Take(maximumSolutions).ToList();
+        runs = new ConcurrentBag<IRun>();
+
+        if (cancellationToken.IsCancellationRequested) {
+          Results.Add(new Result("Runs", new RunCollection(storedRuns.SelectMany(r => r))));
+          cancellationToken.ThrowIfCancellationRequested();
+        }
+      }
+
+
+      Results.Add(new Result("Runs", new RunCollection(storedRuns.SelectMany(r => r))));
+    }
+
+
+    public static ISymbolicRegressionSolution CreateLinearRegressionSolution(IRegressionProblemData problemData, bool buildSolution, out double trainRmsError, out double testRmsError) {
+      var dataset = problemData.Dataset;
+      string targetVariable = problemData.TargetVariable;
+      IEnumerable<string> allowedInputVariables = problemData.AllowedInputVariables;
+
+      double[,] inputMatrix = dataset.ToArray(allowedInputVariables.Concat(new string[] { targetVariable }), problemData.TrainingIndices);
+      double[,] testMatrix = dataset.ToArray(allowedInputVariables.Concat(new string[] { targetVariable }), problemData.TestIndices);
+
+      alglib.linearmodel lm = new alglib.linearmodel();
+      alglib.lrreport ar = new alglib.lrreport();
+      int nRows = inputMatrix.GetLength(0);
+      int nFeatures = inputMatrix.GetLength(1) - 1;
+      double[] coefficients = new double[nFeatures + 1]; // last coefficient is for the constant
+
+      int retVal = 1;
+      alglib.lrbuild(inputMatrix, nRows, nFeatures, out retVal, out lm, out ar);
+      if (retVal != 1) throw new ArgumentException("Error in calculation of linear regression solution");
+      trainRmsError = ar.rmserror;
+
+      alglib.lrunpack(lm, out coefficients, out nFeatures);
+      testRmsError = alglib.lrrmserror(lm, testMatrix, testMatrix.GetLength(0));
+
+      if (!buildSolution) return null;
+
+      ISymbolicExpressionTree tree = new SymbolicExpressionTree(new ProgramRootSymbol().CreateTreeNode());
+      ISymbolicExpressionTreeNode startNode = new StartSymbol().CreateTreeNode();
+      tree.Root.AddSubtree(startNode);
+      ISymbolicExpressionTreeNode addition = new Addition().CreateTreeNode();
+      startNode.AddSubtree(addition);
+
+      int col = 0;
+      foreach (string column in allowedInputVariables) {
+        VariableTreeNode vNode = (VariableTreeNode)new HeuristicLab.Problems.DataAnalysis.Symbolic.Variable().CreateTreeNode();
+        vNode.VariableName = column;
+        vNode.Weight = coefficients[col];
+        addition.AddSubtree(vNode);
+        col++;
+      }
+
+      ConstantTreeNode cNode = (ConstantTreeNode)new Constant().CreateTreeNode();
+      cNode.Value = coefficients[coefficients.Length - 1];
+      addition.AddSubtree(cNode);
+
+      SymbolicRegressionSolution solution = new SymbolicRegressionSolution(new SymbolicRegressionModel(problemData.TargetVariable, tree, new SymbolicDataAnalysisExpressionTreeInterpreter()), problemData);
+      solution.Model.Name = "Linear Regression Model";
+      solution.Name = "Linear Regression Solution";
+      return solution;
+    }
+  }
+}
Index: /branches/MathNetNumerics-Exploration-2789/HeuristicLab.Algorithms.DataAnalysis.Experimental/Plugin.cs.frame
===================================================================
--- /branches/MathNetNumerics-Exploration-2789/HeuristicLab.Algorithms.DataAnalysis.Experimental/Plugin.cs.frame	(revision 14997)
+++ /branches/MathNetNumerics-Exploration-2789/HeuristicLab.Algorithms.DataAnalysis.Experimental/Plugin.cs.frame	(revision 14998)
@@ -25,5 +25,22 @@
   [Plugin("HeuristicLab.Algorithms.DataAnalysis.Experimental", "", "3.4.0.$WCREV$")]
   [PluginFile("HeuristicLab.Algorithms.DataAnalysis.Experimental.dll", PluginFileType.Assembly)]
+  [PluginDependency("HeuristicLab.ALGLIB", "3.7")]
+  [PluginDependency("HeuristicLab.Algorithms.DataAnalysis", "3.4")]
+  [PluginDependency("HeuristicLab.Collections", "3.3")]
+  [PluginDependency("HeuristicLab.Common", "3.3")]
+  [PluginDependency("HeuristicLab.Core", "3.3")]
+  [PluginDependency("HeuristicLab.Data", "3.3")]
+  [PluginDependency("HeuristicLab.Encodings.RealVectorEncoding", "3.3")]
+  [PluginDependency("HeuristicLab.Encodings.SymbolicExpressionTreeEncoding", "3.4")]
   [PluginDependency("HeuristicLab.ExtLibs.MathNetNumerics", "3.19")]
+  [PluginDependency("HeuristicLab.Operators", "3.3")]
+  [PluginDependency("HeuristicLab.Optimization", "3.3")]
+  [PluginDependency("HeuristicLab.Parameters", "3.3")]
+  [PluginDependency("HeuristicLab.Persistence", "3.3")]
+  [PluginDependency("HeuristicLab.Problems.DataAnalysis", "3.4")]
+  [PluginDependency("HeuristicLab.Problems.DataAnalysis.Symbolic", "3.4")]
+  [PluginDependency("HeuristicLab.Problems.DataAnalysis.Symbolic.Regression", "3.4")]
+  [PluginDependency("HeuristicLab.Problems.Instances", "3.3")]
+
   public class Plugin : PluginBase {
   }
