Index: /branches/2893_BNLR/HeuristicLab.Algorithms.DataAnalysis/3.4/HeuristicLab.Algorithms.DataAnalysis-3.4.csproj
===================================================================
--- /branches/2893_BNLR/HeuristicLab.Algorithms.DataAnalysis/3.4/HeuristicLab.Algorithms.DataAnalysis-3.4.csproj	(revision 15747)
+++ /branches/2893_BNLR/HeuristicLab.Algorithms.DataAnalysis/3.4/HeuristicLab.Algorithms.DataAnalysis-3.4.csproj	(revision 15748)
@@ -293,4 +293,6 @@
     <Compile Include="NeuralNetwork\NeuralNetworkRegression.cs" />
     <Compile Include="NeuralNetwork\NeuralNetworkRegressionSolution.cs" />
+    <Compile Include="NonlinearRegression\BayesianNonlinearRegression.cs" />
+    <Compile Include="NonlinearRegression\BayesianNonlinearRegressionModel.cs" />
     <Compile Include="NonlinearRegression\NonlinearRegression.cs" />
     <Compile Include="Plugin.cs" />
@@ -320,5 +322,5 @@
     <Compile Include="TSNE\Distances\IndexedItemDistance.cs" />
     <Compile Include="TSNE\Distances\ManhattanDistance.cs" />
-	<Compile Include="TSNE\Distances\WeightedEuclideanDistance.cs" />
+    <Compile Include="TSNE\Distances\WeightedEuclideanDistance.cs" />
     <Compile Include="TSNE\Distances\IDistance.cs" />
     <Compile Include="TSNE\PriorityQueue.cs" />
Index: /branches/2893_BNLR/HeuristicLab.Algorithms.DataAnalysis/3.4/NonlinearRegression/BayesianNonlinearRegression.cs
===================================================================
--- /branches/2893_BNLR/HeuristicLab.Algorithms.DataAnalysis/3.4/NonlinearRegression/BayesianNonlinearRegression.cs	(revision 15748)
+++ /branches/2893_BNLR/HeuristicLab.Algorithms.DataAnalysis/3.4/NonlinearRegression/BayesianNonlinearRegression.cs	(revision 15748)
@@ -0,0 +1,365 @@
+#region License Information
+/* HeuristicLab
+ * Copyright (C) 2002-2018 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;
+using HeuristicLab.Problems.DataAnalysis.Symbolic;
+using HeuristicLab.Problems.DataAnalysis.Symbolic.Regression;
+using HeuristicLab.Encodings.SymbolicExpressionTreeEncoding;
+using HeuristicLab.Random;
+
+namespace HeuristicLab.Algorithms.DataAnalysis {
+  /// <summary>
+  /// Bayesian non-linear regression data analysis algorithm.
+  /// </summary>
+  [Item("Bayesian Nonlinear Regression (BNLR)", "Nonlinear regression algorithm which uses HMC to create samples for the posterior distribution for the model parameters.")]
+  [Creatable(CreatableAttribute.Categories.DataAnalysisRegression, Priority = 120)]
+  [StorableClass]
+  public sealed class BayesianNonlinearRegression : FixedDataAnalysisAlgorithm<IRegressionProblem> {
+    private const string RegressionSolutionResultName = "Regression solution";
+    private const string ModelStructureParameterName = "Model structure";
+    private const string IterationsParameterName = "Iterations";
+    private const string RestartsParameterName = "Restarts";
+    private const string SetSeedRandomlyParameterName = "SetSeedRandomly";
+    private const string SeedParameterName = "Seed";
+    private const string InitParamsRandomlyParameterName = "InitializeParametersRandomly";
+
+    public IFixedValueParameter<StringValue> ModelStructureParameter {
+      get { return (IFixedValueParameter<StringValue>)Parameters[ModelStructureParameterName]; }
+    }
+    public IFixedValueParameter<IntValue> IterationsParameter {
+      get { return (IFixedValueParameter<IntValue>)Parameters[IterationsParameterName]; }
+    }
+
+    public IFixedValueParameter<BoolValue> SetSeedRandomlyParameter {
+      get { return (IFixedValueParameter<BoolValue>)Parameters[SetSeedRandomlyParameterName]; }
+    }
+
+    public IFixedValueParameter<IntValue> SeedParameter {
+      get { return (IFixedValueParameter<IntValue>)Parameters[SeedParameterName]; }
+    }
+
+    public IFixedValueParameter<IntValue> RestartsParameter {
+      get { return (IFixedValueParameter<IntValue>)Parameters[RestartsParameterName]; }
+    }
+
+    public IFixedValueParameter<BoolValue> InitParametersRandomlyParameter {
+      get { return (IFixedValueParameter<BoolValue>)Parameters[InitParamsRandomlyParameterName]; }
+    }
+
+    public IFixedValueParameter<IntValue> LeapFrogStepsParameter {
+      get { return (IFixedValueParameter<IntValue>)Parameters["LeapFrogSteps"]; }
+    }
+    public IFixedValueParameter<DoubleValue> LeapFrogStepSizeParameter {
+      get { return (IFixedValueParameter<DoubleValue>)Parameters["LeapFrogStepSize"]; }
+    }
+    public IFixedValueParameter<DoubleValue> NoiseSigmaParameter {
+      get { return (IFixedValueParameter<DoubleValue>)Parameters["NoiseSigma"]; }
+    }
+
+    public string ModelStructure {
+      get { return ModelStructureParameter.Value.Value; }
+      set { ModelStructureParameter.Value.Value = value; }
+    }
+
+    public int Iterations {
+      get { return IterationsParameter.Value.Value; }
+      set { IterationsParameter.Value.Value = value; }
+    }
+
+    public int Restarts {
+      get { return RestartsParameter.Value.Value; }
+      set { RestartsParameter.Value.Value = value; }
+    }
+
+    public int Seed {
+      get { return SeedParameter.Value.Value; }
+      set { SeedParameter.Value.Value = value; }
+    }
+
+    public bool SetSeedRandomly {
+      get { return SetSeedRandomlyParameter.Value.Value; }
+      set { SetSeedRandomlyParameter.Value.Value = value; }
+    }
+
+    public bool InitializeParametersRandomly {
+      get { return InitParametersRandomlyParameter.Value.Value; }
+      set { InitParametersRandomlyParameter.Value.Value = value; }
+    }
+
+    public int LeapFrogSteps {
+      get { return LeapFrogStepsParameter.Value.Value; }
+      set { LeapFrogStepsParameter.Value.Value = value; }
+    }
+    public double LeapFrogStepSize {
+      get { return LeapFrogStepSizeParameter.Value.Value; }
+      set { LeapFrogStepSizeParameter.Value.Value = value; }
+    }
+    public double NoiseSigma {
+      get { return NoiseSigmaParameter.Value.Value; }
+      set { NoiseSigmaParameter.Value.Value = value; }
+    }
+
+    [StorableConstructor]
+    private BayesianNonlinearRegression(bool deserializing) : base(deserializing) { }
+    private BayesianNonlinearRegression(BayesianNonlinearRegression original, Cloner cloner)
+      : base(original, cloner) {
+    }
+    public BayesianNonlinearRegression()
+      : base() {
+      Problem = new RegressionProblem();
+      Parameters.Add(new FixedValueParameter<StringValue>(ModelStructureParameterName, "The function for which the parameters must be fit (only numeric constants are tuned).", new StringValue("1.0 * x*x + 0.0")));
+      Parameters.Add(new FixedValueParameter<IntValue>(IterationsParameterName, "The maximum number of iterations for constants optimization.", new IntValue(200)));
+      Parameters.Add(new FixedValueParameter<IntValue>(RestartsParameterName, "The number of independent random restarts (>0)", new IntValue(10)));
+      Parameters.Add(new FixedValueParameter<IntValue>(SeedParameterName, "The PRNG seed value.", new IntValue()));
+      Parameters.Add(new FixedValueParameter<BoolValue>(SetSeedRandomlyParameterName, "Switch to determine if the random number seed should be initialized randomly.", new BoolValue(true)));
+      Parameters.Add(new FixedValueParameter<BoolValue>(InitParamsRandomlyParameterName, "Switch to determine if the real-valued model parameters should be initialized randomly in each restart.", new BoolValue(false)));
+
+      Parameters.Add(new FixedValueParameter<IntValue>("LeapFrogSteps", "LeapFrogSteps", new IntValue(10)));
+      Parameters.Add(new FixedValueParameter<DoubleValue>("LeapFrogStepSize", "LeapFrogStepSize", new DoubleValue(0.1)));
+      Parameters.Add(new FixedValueParameter<DoubleValue>("NoiseSigma", "NoiseSigma", new DoubleValue(0.1)));
+
+      SetParameterHiddenState();
+
+      InitParametersRandomlyParameter.Value.ValueChanged += (sender, args) => {
+        SetParameterHiddenState();
+      };
+    }
+
+    private void SetParameterHiddenState() {
+      var hide = !InitializeParametersRandomly;
+      RestartsParameter.Hidden = hide;
+      SeedParameter.Hidden = hide;
+      SetSeedRandomlyParameter.Hidden = hide;
+    }
+
+    [StorableHook(HookType.AfterDeserialization)]
+    private void AfterDeserialization() {
+    }
+
+    public override IDeepCloneable Clone(Cloner cloner) {
+      return new BayesianNonlinearRegression(this, cloner);
+    }
+
+    #region nonlinear regression
+    protected override void Run(CancellationToken cancellationToken) {
+      IRegressionSolution bestSolution = null;
+      if (SetSeedRandomly) Seed = (new System.Random()).Next();
+      var rand = new MersenneTwister((uint)Seed);
+
+      double[][] chain;
+      if (InitializeParametersRandomly) {
+        var qualityTable = new DataTable("RMSE table");
+        qualityTable.VisualProperties.YAxisLogScale = true;
+        var trainRMSERow = new DataRow("RMSE (train)");
+        trainRMSERow.VisualProperties.ChartType = DataRowVisualProperties.DataRowChartType.Points;
+        var testRMSERow = new DataRow("RMSE test");
+        testRMSERow.VisualProperties.ChartType = DataRowVisualProperties.DataRowChartType.Points;
+
+        qualityTable.Rows.Add(trainRMSERow);
+        qualityTable.Rows.Add(testRMSERow);
+        Results.Add(new Result(qualityTable.Name, qualityTable.Name + " for all restarts", qualityTable));
+        bestSolution = CreateRegressionSolution(Problem.ProblemData, ModelStructure, Iterations, rand, LeapFrogSteps, LeapFrogStepSize, NoiseSigma, out chain);
+        trainRMSERow.Values.Add(bestSolution.TrainingRootMeanSquaredError);
+        testRMSERow.Values.Add(bestSolution.TestRootMeanSquaredError);
+        for (int r = 0; r < Restarts; r++) {
+          var solution = CreateRegressionSolution(Problem.ProblemData, ModelStructure, Iterations, rand, LeapFrogSteps, LeapFrogStepSize, NoiseSigma, out chain);
+          trainRMSERow.Values.Add(solution.TrainingRootMeanSquaredError);
+          testRMSERow.Values.Add(solution.TestRootMeanSquaredError);
+          if (solution.TrainingRootMeanSquaredError < bestSolution.TrainingRootMeanSquaredError) {
+            bestSolution = solution;
+          }
+        }
+      } else {
+        bestSolution = CreateRegressionSolution(Problem.ProblemData, ModelStructure, Iterations, rand, LeapFrogSteps, LeapFrogStepSize, NoiseSigma, out chain);
+        var nRows = chain.First().Length;
+        var chainTable = new DataTable("Chain");
+        var rows = new DataRow[nRows];
+        for (int i = 0; i < nRows; i++) {
+          rows[i] = new DataRow(i.ToString());
+        }
+        foreach(var sample in chain) {
+          for(int i=0;i<sample.Length;i++) {
+            rows[i].Values.Add(sample[i]);
+          }
+        }
+        for (int i = 0; i < nRows; i++) {
+          chainTable.Rows.Add(rows[i]);
+        }
+
+        Results.Add(new Result("Chain", chainTable));
+      }
+
+      Results.Add(new Result(RegressionSolutionResultName, "The nonlinear regression solution.", bestSolution));
+      Results.Add(new Result("Root mean square error (train)", "The root of the mean of squared errors of the regression solution on the training set.", new DoubleValue(bestSolution.TrainingRootMeanSquaredError)));
+      Results.Add(new Result("Root mean square error (test)", "The root of the mean of squared errors of the regression solution on the test set.", new DoubleValue(bestSolution.TestRootMeanSquaredError)));
+    }
+
+    /// <summary>
+    /// Detemines the posterior distribution for the model parameters using Hamiltonian Monte Carlo.
+    /// Model is specified as infix expression containing variable names and numbers. 
+    /// Prior distribution for the parameters is N(0,\lambda I)
+    /// </summary>-
+    /// <param name="problemData">Training and test data</param>
+    /// <param name="modelStructure">The function as infix expression</param>
+    /// <param name="maxIterations">Number of samples for HMC</param>
+    public static IRegressionSolution CreateRegressionSolution(
+      IRegressionProblemData problemData, string modelStructure, int maxIterations, IRandom random,
+      int leapFrogSteps, double leapFrogStepSize, double noiseSigma, out double[][] chain
+      ) {
+      var parser = new InfixExpressionParser();
+      var tree = parser.Parse(modelStructure);
+      // parser handles double and string variables equally by creating a VariableTreeNode
+      // post-process to replace VariableTreeNodes by FactorVariableTreeNodes for all string variables
+      var factorSymbol = new FactorVariable();
+      factorSymbol.VariableNames =
+        problemData.AllowedInputVariables.Where(name => problemData.Dataset.VariableHasType<string>(name));
+      factorSymbol.AllVariableNames = factorSymbol.VariableNames;
+      factorSymbol.VariableValues =
+        factorSymbol.VariableNames.Select(name =>
+        new KeyValuePair<string, Dictionary<string, int>>(name,
+        problemData.Dataset.GetReadOnlyStringValues(name).Distinct()
+        .Select((n, i) => Tuple.Create(n, i))
+        .ToDictionary(tup => tup.Item1, tup => tup.Item2)));
+
+      foreach (var parent in tree.IterateNodesPrefix().ToArray()) {
+        for (int i = 0; i < parent.SubtreeCount; i++) {
+          var varChild = parent.GetSubtree(i) as VariableTreeNode;
+          var factorVarChild = parent.GetSubtree(i) as FactorVariableTreeNode;
+          if (varChild != null && factorSymbol.VariableNames.Contains(varChild.VariableName)) {
+            parent.RemoveSubtree(i);
+            var factorTreeNode = (FactorVariableTreeNode)factorSymbol.CreateTreeNode();
+            factorTreeNode.VariableName = varChild.VariableName;
+            factorTreeNode.Weights =
+              factorTreeNode.Symbol.GetVariableValues(factorTreeNode.VariableName).Select(_ => 1.0).ToArray();
+            // weight = 1.0 for each value
+            parent.InsertSubtree(i, factorTreeNode);
+          } else if (factorVarChild != null && factorSymbol.VariableNames.Contains(factorVarChild.VariableName)) {
+            if (factorSymbol.GetVariableValues(factorVarChild.VariableName).Count() != factorVarChild.Weights.Length)
+              throw new ArgumentException(
+                string.Format("Factor variable {0} needs exactly {1} weights",
+                factorVarChild.VariableName,
+                factorSymbol.GetVariableValues(factorVarChild.VariableName).Count()));
+            parent.RemoveSubtree(i);
+            var factorTreeNode = (FactorVariableTreeNode)factorSymbol.CreateTreeNode();
+            factorTreeNode.VariableName = factorVarChild.VariableName;
+            factorTreeNode.Weights = factorVarChild.Weights;
+            parent.InsertSubtree(i, factorTreeNode);
+          }
+        }
+      }
+
+      // TODO: useful?
+      // initialize constants randomly
+      // if (random != null) {
+      //   foreach (var node in tree.IterateNodesPrefix().OfType<ConstantTreeNode>()) {
+      //     double f = Math.Exp(NormalDistributedRandom.NextDouble(random, 0, 1));
+      //     double s = random.NextDouble() < 0.5 ? -1 : 1;
+      //     node.Value = s * node.Value * f;
+      //   }
+      // }
+
+      double[] initialConstants;
+      var negLogLikelihood = CreateNegLogLikelihoodFunction(problemData, tree, noiseSigma, out initialConstants);
+
+
+      // create parameter sample
+      var sampledParameters = HamiltonianMonteCarlo.SampleChain(initialConstants, negLogLikelihood, random, leapFrogStepSize, leapFrogSteps)
+        .Take(maxIterations);
+
+      chain = sampledParameters.ToArray();
+
+      var model = new BayesianNonlinearRegressionModel(tree, chain,
+        new SymbolicDataAnalysisExpressionTreeLinearInterpreter(), problemData.TargetVariable, problemData.AllowedInputVariables);
+      var solution = model.CreateRegressionSolution((IRegressionProblemData)problemData.Clone());
+
+      solution.Model.Name = "Regression Model";
+      solution.Name = "Regression Solution";
+      return solution;
+    }
+
+    private static Func<double[], Tuple<double, double[]>> CreateNegLogLikelihoodFunction(
+      IRegressionProblemData problemData, ISymbolicExpressionTree tree, double noiseSigma, 
+      out double[] initialConstants) {
+      List<TreeToAutoDiffTermConverter.DataForVariable> parameters;
+      TreeToAutoDiffTermConverter.ParametricFunction func;
+      TreeToAutoDiffTermConverter.ParametricFunctionGradient funcGrad;
+      TreeToAutoDiffTermConverter.TryConvertToAutoDiff(tree, false, false, out parameters, out initialConstants, out func, out funcGrad);
+
+      double variance = noiseSigma * noiseSigma;
+
+      IDataset ds = problemData.Dataset;
+      var rows = problemData.TrainingIndices;
+      int N = rows.Count();
+      var xs = new double[N][];
+      int row = 0;
+      foreach (var r in rows) {
+        int col = 0;
+        xs[row] = new double[parameters.Count];
+        foreach (var info in parameters) {
+          if (ds.VariableHasType<double>(info.variableName)) {
+            xs[row][col] = ds.GetDoubleValue(info.variableName, r + info.lag);
+          } else if (ds.VariableHasType<string>(info.variableName)) {
+            xs[row][col] = ds.GetStringValue(info.variableName, r) == info.variableValue ? 1 : 0;
+          } else throw new InvalidProgramException("found a variable of unknown type");
+          col++;
+        }
+        row++;
+      }
+      var ys = ds.GetDoubleValues(problemData.TargetVariable, rows).ToArray();
+
+      return (double[] p) => {
+        var logProbSum = 0.0;
+        var scalingFactor = 1.0 / (2.0 * variance);
+        double[] gSum = new double[p.Length];
+        for (int i = 0; i < N; i++) {
+          var fg = funcGrad(p, xs[i]);
+          // sum up err
+          var err = fg.Item2 - ys[i];
+          logProbSum += scalingFactor * err * err;
+
+//          var llik = (err * err / (2 * sigma * sigma))
+
+          // sum up grad
+          for (int j = 0; j < gSum.Length; j++) gSum[j] += scalingFactor * 2 * err * fg.Item1[j];
+        }
+
+
+        double f = logProbSum /* + N / 2.0 * Math.Log(variance) + N / 2.0 * Math.Log(2 * Math.PI) (constant factors) */;
+        double[] g = gSum /* + N / 2.0 * Math.Log(variance) + N / 2.0 * Math.Log(2 * Math.PI) (constant factors) */;
+        return Tuple.Create(f, g);
+      };
+    }
+
+
+    #endregion
+  }
+}
Index: /branches/2893_BNLR/HeuristicLab.Algorithms.DataAnalysis/3.4/NonlinearRegression/BayesianNonlinearRegressionModel.cs
===================================================================
--- /branches/2893_BNLR/HeuristicLab.Algorithms.DataAnalysis/3.4/NonlinearRegression/BayesianNonlinearRegressionModel.cs	(revision 15748)
+++ /branches/2893_BNLR/HeuristicLab.Algorithms.DataAnalysis/3.4/NonlinearRegression/BayesianNonlinearRegressionModel.cs	(revision 15748)
@@ -0,0 +1,146 @@
+#region License Information
+/* HeuristicLab
+ * Copyright (C) 2002-2018 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 HeuristicLab.Common;
+using HeuristicLab.Core;
+using HeuristicLab.Encodings.SymbolicExpressionTreeEncoding;
+using HeuristicLab.Persistence.Default.CompositeSerializers.Storable;
+using HeuristicLab.Problems.DataAnalysis;
+using HeuristicLab.Problems.DataAnalysis.Symbolic;
+
+namespace HeuristicLab.Algorithms.DataAnalysis {
+  [StorableClass]
+  [Item("BayesianNonlinearRegressionModel", "")]
+  public sealed class BayesianNonlinearRegressionModel : RegressionModel, IConfidenceRegressionModel {
+    private const int SAMPLE_SIZE = 100;
+
+
+    [Storable]
+    public ISymbolicExpressionTree Tree {
+      get; private set;
+    }
+
+    private double[][] parameterEmpiricalDistribution;
+    public IEnumerable<double[]> ParameterEmpiricalDistribution {
+      get { return parameterEmpiricalDistribution; }
+    }
+
+    public ISymbolicDataAnalysisExpressionTreeInterpreter Interpreter {
+      get; private set;
+    }
+
+    public override IEnumerable<string> VariablesUsedForPrediction {
+      get { return allowedInputVariables; }
+    }
+
+    [Storable]
+    private string[] allowedInputVariables;
+
+    [StorableConstructor]
+    private BayesianNonlinearRegressionModel(bool deserializing)
+      : base(deserializing) {
+    }
+    private BayesianNonlinearRegressionModel(BayesianNonlinearRegressionModel original, Cloner cloner)
+      : base(original, cloner) {
+      allowedInputVariables = (string[])original.allowedInputVariables.Clone();
+      this.Tree = cloner.Clone(original.Tree);
+      this.parameterEmpiricalDistribution = original.parameterEmpiricalDistribution;
+      this.Interpreter = cloner.Clone(original.Interpreter);
+    }
+    public BayesianNonlinearRegressionModel(
+      ISymbolicExpressionTree tree,
+      double[][] parameterEmpiricalDistribution,
+      ISymbolicDataAnalysisExpressionTreeInterpreter interpreter,
+      string targetVariable, 
+      IEnumerable<string> allowedInputVariables
+      )
+      : base(targetVariable) {
+      this.name = ItemName;
+      this.description = ItemDescription;
+      this.Tree = tree;
+      this.parameterEmpiricalDistribution = (double[][])parameterEmpiricalDistribution.Clone();
+      this.Interpreter = interpreter;
+      this.allowedInputVariables = allowedInputVariables.ToArray();
+    }
+
+    [StorableHook(HookType.AfterDeserialization)]
+    private void AfterDeserialization() {
+    }
+
+    public override IDeepCloneable Clone(Cloner cloner) {
+      return new BayesianNonlinearRegressionModel(this, cloner);
+    }
+
+
+    public override IEnumerable<double> GetEstimatedValues(IDataset dataset, IEnumerable<int> rows) {
+      var y = Sample(dataset, rows);
+      return y.Select(yi => yi.Average());
+    }
+
+    public IEnumerable<double> GetEstimatedVariances(IDataset dataset, IEnumerable<int> rows) {
+      var y = Sample(dataset, rows);
+      return y.Select(yi => yi.VariancePop());
+    }
+
+    private IList<double>[] Sample(IDataset dataset, IEnumerable<int> rows) {
+      List<double>[] y = rows.Select(_ => new List<double>(SAMPLE_SIZE)).ToArray();
+      var rand = new System.Random(1234); // TODO;
+      for (int s = 0; s < SAMPLE_SIZE; s++) {
+        var paramIdx = rand.Next(parameterEmpiricalDistribution.Length);
+        UpdateConstants(Tree, parameterEmpiricalDistribution[paramIdx]);
+        int predRow = 0;
+        foreach (var pred in Interpreter.GetSymbolicExpressionTreeValues(Tree, dataset, rows)) {
+          y[predRow].Add(pred);
+          predRow++;
+        }
+      }
+      return y;
+    }
+
+    public override IRegressionSolution CreateRegressionSolution(IRegressionProblemData problemData) {
+      return new ConfidenceRegressionSolution(this, new RegressionProblemData(problemData));
+    }
+
+
+    #region taken from ConstantOptEval TODO
+    private static void UpdateConstants(ISymbolicExpressionTree tree, double[] constants) {
+      int i = 0;
+      foreach (var node in tree.Root.IterateNodesPrefix().OfType<SymbolicExpressionTreeTerminalNode>()) {
+        ConstantTreeNode constantTreeNode = node as ConstantTreeNode;
+        VariableTreeNodeBase variableTreeNodeBase = node as VariableTreeNodeBase;
+        FactorVariableTreeNode factorVarTreeNode = node as FactorVariableTreeNode;
+        if (constantTreeNode != null)
+          constantTreeNode.Value = constants[i++];
+        // else if (updateVariableWeights && variableTreeNodeBase != null)
+        //   variableTreeNodeBase.Weight = constants[i++];
+        else if (factorVarTreeNode != null) {
+          for (int j = 0; j < factorVarTreeNode.Weights.Length; j++)
+            factorVarTreeNode.Weights[j] = constants[i++];
+        }
+      }
+    }
+    #endregion
+
+  }
+}
Index: /branches/2893_BNLR/HeuristicLab.Random/3.3/HamiltonianMonteCarlo.cs
===================================================================
--- /branches/2893_BNLR/HeuristicLab.Random/3.3/HamiltonianMonteCarlo.cs	(revision 15748)
+++ /branches/2893_BNLR/HeuristicLab.Random/3.3/HamiltonianMonteCarlo.cs	(revision 15748)
@@ -0,0 +1,174 @@
+﻿#region License Information
+
+/* HeuristicLab
+ * Copyright (C) 2002-2018 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 HeuristicLab.Core;
+
+namespace HeuristicLab.Random {
+  /// <summary>
+  /// See Radford Neal, MCMC using Hamiltonian dynamics, 2011, https://arxiv.org/pdf/1206.1901.pdf
+  /// Algorithm from the paper:
+  /// 
+  /// HMC = function (U, grad_U, epsilon, L, current_q)
+  /// {
+  ///   q = current_q
+  ///   p = rnorm(length(q), 0, 1) # independent standard normal variates
+  ///   current_p = p
+  ///   # Make a half step for momentum at the beginning
+  ///   p = p - epsilon * grad_U(q) / 2
+  ///   # Alternate full steps for position and momentum
+  ///   for (i in 1:L)
+  ///   {
+  ///     # Make a full step for the position
+  ///     q = q + epsilon* p
+  ///     # Make a full step for the momentum, except at end of trajectory
+  ///     if (i!=L) p = p - epsilon * grad_U(q)
+  ///   }
+  ///   # Make a half step for momentum at the end.
+  ///   p = p - epsilon* grad_U(q) / 2
+  ///   # Negate momentum at end of trajectory to make the proposal symmetric
+  ///   p = -p
+  ///   # Evaluate potential and kinetic energies at start and end of trajectory
+  ///     current_U = U(current_q)
+  ///     current_K = sum(current_p^2) / 2
+  ///     proposed_U = U(q)
+  ///     proposed_K = sum(p^2) / 2
+  ///   # Accept or reject the state at end of trajectory, returning either
+  ///   # the position at the end of the trajectory or the initial position
+  ///   if (runif(1) < exp(current_U-proposed_U+current_K-proposed_K)) {
+  ///     return (q) # accept
+  ///   }
+  ///   else {
+  ///     return (current_q) # reject
+  ///   }
+  /// }
+
+  /// </summary>
+  public static class HamiltonianMonteCarlo {
+
+    public static IEnumerable<double[]> SampleChain(double[] startingPosition,
+      Func<double[], Tuple<double, double[]>> potentialEnergyFunction,
+      IRandom uniformRandom, double stepSize, int steps = 10) {
+      var x = (double[])startingPosition.Clone();
+      while(true) {
+        x = Sample(x, potentialEnergyFunction, uniformRandom, stepSize, steps);
+        yield return x;
+      }
+    }
+
+    public static double[] Sample(
+      double[] startingPosition,
+      Func<double[], Tuple<double, double[]>> potentialEnergyFunction, // U
+      IRandom uniformRandom, double stepSize, int steps) {
+      // step 1
+      // new values for the momentum variables are randomly drawn from their Gaussian 
+      // distribution, independently if the current values of the position variables
+
+      // step 2
+      // Metropolis update is performed, using Hamiltonian dynamics to propose a new state.
+      // Starting with the current state Hamiltonian dynamics is simulated for L steps
+      // using the Leapfrog method with a step size of eps. 
+      // L and eps are parameters of the algorithm, which need to be tuned to obtain 
+      // good performance.
+      // The proposed state is accepted as the next state of the Markov chain with
+      // probability [...].
+      // If the proposed state is not accepted the next state is the same as the current state
+      // (and is counted again when estimating the expectation of some function of
+      // state by its average over states of the Markov chain).
+
+
+      int nVars = startingPosition.Length;
+      var u_initial = potentialEnergyFunction(startingPosition).Item1;
+
+      // rename variables to match Neal's algorithm
+      var current_q = startingPosition;
+      var epsilon = stepSize;
+      var L = steps;
+
+      var q = current_q;
+      // p = rnorm(length(q), 0, 1) # independent standard normal variates
+      var p = q
+        .Select(_ => NormalDistributedRandom.NextDouble(uniformRandom, 0, 1))
+        .ToArray();
+      var current_p = p;
+      // Make a half step for momentum at the beginning
+      // p = p - epsilon * grad_U(q) / 2;
+      p = VectorSum(p, ScaleVector(-0.5 * epsilon, potentialEnergyFunction(q).Item2));
+      // Alternate full steps for position and momentum
+
+      for (int i = 1; i <= L; i++) {
+        // Make a full step for the position
+        // q = q + epsilon * p;
+        q = VectorSum(q, ScaleVector(epsilon, p));
+        // Make a full step for the momentum, except at end of trajectory
+        if (i != L)
+          p = VectorSum(p, ScaleVector(-epsilon, potentialEnergyFunction(q).Item2));
+      }
+      // Make a half step for momentum at the end.
+      ///   p = p - epsilon* grad_U(q) / 2
+      p = VectorSum(p, ScaleVector(-0.5 * epsilon, potentialEnergyFunction(q).Item2));
+      // Negate momentum at end of trajectory to make the proposal symmetric
+      ///   p = -p
+      p = ScaleVector(-1.0, p);
+      // Evaluate potential and kinetic energies at start and end of trajectory
+      double current_U = potentialEnergyFunction(current_q).Item1;
+      // sum(current_p ^ 2) / 2
+      double current_K = 0.5 * current_p.Sum(pi => pi * pi);
+      double proposed_U = potentialEnergyFunction(q).Item1;
+      // sum(p^2) / 2
+      double proposed_K = 0.5 * p.Sum(pi => pi * pi);
+      ///   # Accept or reject the state at end of trajectory, returning either
+      ///   # the position at the end of the trajectory or the initial position
+      if (uniformRandom.NextDouble() < Math.Exp(current_U - proposed_U + current_K - proposed_K)) {
+        return q; // accept
+      } else {
+        return current_q; // # reject
+      }
+    }
+
+    #region to be improved or removed
+    private static double VectorProd(double[] x, double[] y) {
+      double s = 0.0;
+      for (int i = 0; i < x.Length; i++)
+        s += x[i] * y[i];
+      return s;
+    }
+
+    private static double[] VectorSum(double[] x, double[] y) {
+      double[] s = new double[x.Length];
+      for (int i = 0; i < x.Length; i++)
+        s[i] += x[i] + y[i];
+      return s;
+    }
+
+    private static double[] ScaleVector(double a, double[] x) {
+      double[] s = new double[x.Length];
+      for (int i = 0; i < x.Length; i++)
+        s[i] = a * x[i];
+      return s;
+    }
+    #endregion
+  }
+}
Index: /branches/2893_BNLR/HeuristicLab.Random/3.3/HeuristicLab.Random-3.3.csproj
===================================================================
--- /branches/2893_BNLR/HeuristicLab.Random/3.3/HeuristicLab.Random-3.3.csproj	(revision 15747)
+++ /branches/2893_BNLR/HeuristicLab.Random/3.3/HeuristicLab.Random-3.3.csproj	(revision 15748)
@@ -119,4 +119,5 @@
     <None Include="Plugin.cs.frame" />
     <Compile Include="GammaDistributedRandom.cs" />
+    <Compile Include="HamiltonianMonteCarlo.cs" />
     <Compile Include="ListExtensions.cs" />
     <Compile Include="UniformDistributedRandom.cs" />
