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 15351)
+++ /branches/MathNetNumerics-Exploration-2789/HeuristicLab.Algorithms.DataAnalysis.Experimental/HeuristicLab.Algorithms.DataAnalysis.Experimental.csproj	(revision 15352)
@@ -131,4 +131,6 @@
   <ItemGroup>
     <Compile Include="ForwardSelection.cs" />
+    <Compile Include="RBF.cs" />
+    <Compile Include="Splines.cs" />
     <Compile Include="LinearRegressionCombinations.cs" />
     <Compile Include="NonlinearRegression.cs" />
Index: /branches/MathNetNumerics-Exploration-2789/HeuristicLab.Algorithms.DataAnalysis.Experimental/RBF.cs
===================================================================
--- /branches/MathNetNumerics-Exploration-2789/HeuristicLab.Algorithms.DataAnalysis.Experimental/RBF.cs	(revision 15352)
+++ /branches/MathNetNumerics-Exploration-2789/HeuristicLab.Algorithms.DataAnalysis.Experimental/RBF.cs	(revision 15352)
@@ -0,0 +1,185 @@
+﻿#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 {
+  [Item("RBF (alglib)", "")]
+  [Creatable(CreatableAttribute.Categories.DataAnalysisRegression, Priority = 102)]
+  [StorableClass]
+  public sealed class RBF : FixedDataAnalysisAlgorithm<IRegressionProblem> {
+    [StorableConstructor]
+    private RBF(bool deserializing) : base(deserializing) { }
+    [StorableHook(HookType.AfterDeserialization)]
+    private void AfterDeserialization() {
+    }
+
+    private RBF(RBF original, Cloner cloner)
+      : base(original, cloner) {
+    }
+    public override IDeepCloneable Clone(Cloner cloner) {
+      return new RBF(this, cloner);
+    }
+
+    public RBF()
+      : base() {
+      Problem = new RegressionProblem();
+      Parameters.Add(new ValueParameter<DoubleValue>("RBase", new DoubleValue(1.0)));
+      Parameters.Add(new ValueParameter<IntValue>("NLayers", new IntValue(3)));
+      Parameters.Add(new ValueParameter<DoubleValue>("LambdaNS", new DoubleValue(1.0)));
+    }
+
+
+    protected override void Run(CancellationToken cancellationToken) {
+      var scaling = CreateScaling(Problem.ProblemData.Dataset, Problem.ProblemData.TrainingIndices.ToArray(), Problem.ProblemData.AllowedInputVariables.ToArray());
+
+      double[,] inputMatrix = ExtractData(Problem.ProblemData.Dataset, Problem.ProblemData.TrainingIndices, Problem.ProblemData.AllowedInputVariables.ToArray(), scaling);
+
+      double[,] target = ExtractData(Problem.ProblemData.Dataset, Problem.ProblemData.TrainingIndices, new string[] { Problem.ProblemData.TargetVariable });
+      inputMatrix = inputMatrix.HorzCat(target);
+
+      if (inputMatrix.Cast<double>().Any(x => double.IsNaN(x) || double.IsInfinity(x)))
+        throw new NotSupportedException("Splines does not support NaN or infinity values in the input dataset.");
+
+
+      var inputVars = Problem.ProblemData.AllowedInputVariables.ToArray();
+      if (inputVars.Length > 3) throw new NotSupportedException();
+
+      alglib.rbfmodel model;
+      alglib.rbfreport rep;
+
+      alglib.rbfcreate(inputVars.Length, 1, out model);
+
+      alglib.rbfsetzeroterm(model);
+      var rbase = ((DoubleValue)Parameters["RBase"].ActualValue).Value;
+      var nlayers = ((IntValue)Parameters["NLayers"].ActualValue).Value;
+      var lambdans = ((DoubleValue)Parameters["LambdaNS"].ActualValue).Value;
+      alglib.rbfsetalgohierarchical(model, rbase, nlayers, lambdans);
+      alglib.rbfsetpoints(model, inputMatrix);
+      alglib.rbfbuildmodel(model, out rep);
+
+      Results.Add(new Result("TerminationType", new DoubleValue(rep.terminationtype)));
+      Results.Add(new Result("RMSE", new DoubleValue(rep.rmserror)));
+
+      Results.Add(new Result("Solution", new RegressionSolution(new RBFModel(model, Problem.ProblemData.TargetVariable, inputVars, scaling),
+        (IRegressionProblemData)Problem.ProblemData.Clone())));
+    }
+
+
+    private static ITransformation<double>[] CreateScaling(IDataset dataset, int[] rows, IReadOnlyCollection<string> allowedInputVariables) {
+      var trans = new ITransformation<double>[allowedInputVariables.Count];
+      int i = 0;
+      foreach (var variable in allowedInputVariables) {
+        var lin = new LinearTransformation(allowedInputVariables);
+        var max = dataset.GetDoubleValues(variable, rows).Max();
+        var min = dataset.GetDoubleValues(variable, rows).Min();
+        lin.Multiplier = 1.0 / (max - min);
+        lin.Addend = -min / (max - min);
+        trans[i] = lin;
+        i++;
+      }
+      return trans;
+    }
+
+    private static double[,] ExtractData(IDataset dataset, IEnumerable<int> rows, IReadOnlyCollection<string> allowedInputVariables, ITransformation<double>[] scaling = null) {
+      double[][] variables;
+      if (scaling != null) {
+        variables =
+          allowedInputVariables.Select((var, i) => scaling[i].Apply(dataset.GetDoubleValues(var, rows)).ToArray())
+            .ToArray();
+      } else {
+        variables =
+        allowedInputVariables.Select(var => dataset.GetDoubleValues(var, rows).ToArray()).ToArray();
+      }
+      int n = variables.First().Length;
+      var res = new double[n, variables.Length];
+      for (int r = 0; r < n; r++)
+        for (int c = 0; c < variables.Length; c++) {
+          res[r, c] = variables[c][r];
+        }
+      return res;
+    }
+  }
+
+}
+
+
+// UNFINISHED
+public class RBFModel : NamedItem, IRegressionModel {
+  private alglib.rbfmodel model;
+
+  public string TargetVariable { get; set; }
+
+  public IEnumerable<string> VariablesUsedForPrediction { get; private set; }
+  private ITransformation<double>[] scaling;
+
+  public event EventHandler TargetVariableChanged;
+
+  public RBFModel(RBFModel orig, Cloner cloner) : base(orig, cloner) {
+    this.TargetVariable = orig.TargetVariable;
+    this.VariablesUsedForPrediction = orig.VariablesUsedForPrediction.ToArray();
+    this.model = (alglib.rbfmodel)orig.model.make_copy();
+    this.scaling = orig.scaling.Select(s => cloner.Clone(s)).ToArray();
+  }
+  public RBFModel(alglib.rbfmodel model, string targetVar, string[] inputs, IEnumerable<ITransformation<double>> scaling) : base("RBFModel", "RBFModel") {
+    this.model = model;
+    this.TargetVariable = targetVar;
+    this.VariablesUsedForPrediction = inputs;
+    this.scaling = scaling.ToArray();
+  }
+
+  public override IDeepCloneable Clone(Cloner cloner) {
+    return new RBFModel(this, cloner);
+  }
+
+  public IRegressionSolution CreateRegressionSolution(IRegressionProblemData problemData) {
+    return new RegressionSolution(this, (IRegressionProblemData)problemData.Clone());
+  }
+
+  public IEnumerable<double> GetEstimatedValues(IDataset dataset, IEnumerable<int> rows) {
+    double[] x = new double[VariablesUsedForPrediction.Count()];
+    double[] y;
+    foreach (var r in rows) {
+      int c = 0;
+      foreach (var v in VariablesUsedForPrediction) {
+        x[c] = scaling[c].Apply(dataset.GetDoubleValue(v, r).ToEnumerable()).First(); // OUCH!
+        c++;
+      }
+      alglib.rbfcalc(model, x, out y);
+      yield return y[0];
+    }
+  }
+}
Index: /branches/MathNetNumerics-Exploration-2789/HeuristicLab.Algorithms.DataAnalysis.Experimental/Splines.cs
===================================================================
--- /branches/MathNetNumerics-Exploration-2789/HeuristicLab.Algorithms.DataAnalysis.Experimental/Splines.cs	(revision 15352)
+++ /branches/MathNetNumerics-Exploration-2789/HeuristicLab.Algorithms.DataAnalysis.Experimental/Splines.cs	(revision 15352)
@@ -0,0 +1,140 @@
+﻿#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 {
+  [Item("Splines", "")]
+  [Creatable(CreatableAttribute.Categories.DataAnalysisRegression, Priority = 102)]
+  [StorableClass]
+  public sealed class Splines : FixedDataAnalysisAlgorithm<IRegressionProblem> {
+    [StorableConstructor]
+    private Splines(bool deserializing) : base(deserializing) { }
+    [StorableHook(HookType.AfterDeserialization)]
+    private void AfterDeserialization() {
+    }
+
+    private Splines(Splines original, Cloner cloner)
+      : base(original, cloner) {
+    }
+    public override IDeepCloneable Clone(Cloner cloner) {
+      return new Splines(this, cloner);
+    }
+
+    public Splines()
+      : base() {
+      var validTypes = new ItemSet<StringValue>(
+        new[] {
+        "Monotone", "Akima", "Catmull-Rom", "Cubic", "Linear"
+      }.Select(s => new StringValue(s)));
+
+      Parameters.Add(new ConstrainedValueParameter<StringValue>("Type", "The type of spline (as supported by alglib)", validTypes, validTypes.First()));
+      Problem = new RegressionProblem();
+    }
+
+
+    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("Splines does not support NaN or infinity values in the input dataset.");
+
+      var inputVars = Problem.ProblemData.AllowedInputVariables.ToArray();
+      if (inputVars.Length > 3) throw new ArgumentException();
+
+      var y = Problem.ProblemData.TargetVariableTrainingValues.ToArray();
+      if (inputVars.Length == 1) {
+
+        var x = Problem.ProblemData.Dataset.GetDoubleValues(inputVars.First(), Problem.ProblemData.TrainingIndices).ToArray();
+        alglib.spline1dinterpolant c;
+        var type = ((StringValue)Parameters["Type"].ActualValue).Value;
+        switch (type) {
+          case "Monotone":
+            alglib.spline1dbuildmonotone(x, y, out c); break;
+          case "Akima":
+            alglib.spline1dbuildakima(x, y, out c); break;
+          case "Catmull-Rom":
+            alglib.spline1dbuildcatmullrom(x, y, out c); break;
+          case "Cubic":
+            alglib.spline1dbuildcubic(x, y, out c); break;
+          case "Linear":
+            alglib.spline1dbuildlinear(x, y, out c); break;
+
+          default: throw new NotSupportedException();
+        }
+
+        Results.Add(new Result("Solution", new RegressionSolution(new Spline1dModel(c, Problem.ProblemData.TargetVariable, inputVars),
+          (IRegressionProblemData)Problem.ProblemData.Clone())));
+      }
+    }
+  }
+
+
+  // UNFINISHED
+  public class Spline1dModel : NamedItem, IRegressionModel {
+    private alglib.spline1dinterpolant interpolant;
+
+    public string TargetVariable { get; set; }
+
+    public IEnumerable<string> VariablesUsedForPrediction { get; private set; }
+
+    public event EventHandler TargetVariableChanged;
+
+    public Spline1dModel(Spline1dModel orig, Cloner cloner) : base(orig, cloner) {
+      this.TargetVariable = orig.TargetVariable;
+      this.VariablesUsedForPrediction = orig.VariablesUsedForPrediction.ToArray();
+      this.interpolant = (alglib.spline1dinterpolant)orig.interpolant.make_copy();
+    }
+    public Spline1dModel(alglib.spline1dinterpolant interpolant, string targetVar, string[] inputs) : base("SplineModel", "SplineModel") {
+      this.interpolant = interpolant;
+      this.TargetVariable = targetVar;
+      this.VariablesUsedForPrediction = inputs;
+    }
+
+    public override IDeepCloneable Clone(Cloner cloner) {
+      return new Spline1dModel(this, cloner);
+    }
+
+    public IRegressionSolution CreateRegressionSolution(IRegressionProblemData problemData) {
+      return new RegressionSolution(this, (IRegressionProblemData)problemData.Clone());
+    }
+
+    public IEnumerable<double> GetEstimatedValues(IDataset dataset, IEnumerable<int> rows) {
+      foreach (var x in dataset.GetDoubleValues(VariablesUsedForPrediction.First(), rows)) {
+        yield return alglib.spline1dcalc(interpolant, x);
+      }
+    }
+  }
+}
Index: /branches/MathNetNumerics-Exploration-2789/HeuristicLab.Algorithms.DataAnalysis.Experimental/SymbolicRegressionConstantOptimizationEvaluator.cs
===================================================================
--- /branches/MathNetNumerics-Exploration-2789/HeuristicLab.Algorithms.DataAnalysis.Experimental/SymbolicRegressionConstantOptimizationEvaluator.cs	(revision 15351)
+++ /branches/MathNetNumerics-Exploration-2789/HeuristicLab.Algorithms.DataAnalysis.Experimental/SymbolicRegressionConstantOptimizationEvaluator.cs	(revision 15352)
@@ -223,6 +223,11 @@
       var target = problemData.TargetVariable;
 
-      // only count constraints
-      var constraintRows = Enumerable.Range(0, problemData.Dataset.Rows).Where(rIdx => !string.IsNullOrEmpty(ds.GetStringValue("f(x) constraint-type", rIdx)));
+      // determine rows with constraints by checking of any constraint column contains a value
+      var constraintColNames = parameterEntries
+                .Select(e => e.variableName)
+                .Select(name => string.Format("df/d({0})", name))
+                .ToArray();
+      var constraintRows = Enumerable.Range(0, problemData.Dataset.Rows)
+                .Where(rIdx => constraintColNames.Any(name => !double.IsNaN(ds.GetDoubleValue(name, rIdx))));
 
       double[,] constraintX = new double[constraintRows.Count(), parameters.Count]; // inputs for constraint values
@@ -271,9 +276,4 @@
       int updateFreq = 10;
       try {
-        // alglib.lsfitcreatefg(x, y, c, n, m, k, false, out state);
-        // alglib.lsfitsetcond(state, 0.0, maxIterations);
-        // //alglib.lsfitsetgradientcheck(state, 0.001);
-        // alglib.lsfitfit(state, function_cx_1_func, function_cx_1_grad, null, null);
-        // alglib.lsfitresults(state, out retVal, out c, out rep);
         alglib.minnlccreate(c, out state);
         alglib.minnlcsetalgoaul(state, rho, outeriters);
