Index: stable/HeuristicLab.Problems.Instances.DataAnalysis/3.3/HeuristicLab.Problems.Instances.DataAnalysis-3.3.csproj
===================================================================
--- stable/HeuristicLab.Problems.Instances.DataAnalysis/3.3/HeuristicLab.Problems.Instances.DataAnalysis-3.3.csproj	(revision 14116)
+++ stable/HeuristicLab.Problems.Instances.DataAnalysis/3.3/HeuristicLab.Problems.Instances.DataAnalysis-3.3.csproj	(revision 14117)
@@ -105,4 +105,8 @@
   </PropertyGroup>
   <ItemGroup>
+    <Reference Include="ALGLIB-3.7.0, Version=3.7.0.0, Culture=neutral, PublicKeyToken=ba48961d6f65dcec, processorArchitecture=MSIL">
+      <SpecificVersion>False</SpecificVersion>
+      <HintPath>..\..\bin\ALGLIB-3.7.0.dll</HintPath>
+    </Reference>
     <Reference Include="System" />
     <Reference Include="System.Core" />
@@ -147,4 +151,6 @@
     <Compile Include="Regression\FeatureSelection\FeatureSelection.cs" />
     <Compile Include="Regression\FeatureSelection\FeatureSelectionInstanceProvider.cs" />
+    <Compile Include="Regression\VariableNetworks\VariableNetwork.cs" />
+    <Compile Include="Regression\VariableNetworks\VariableNetworkInstanceProvider.cs" />
     <Compile Include="Regression\Keijzer\KeijzerFunctionFourteen.cs" />
     <Compile Include="Regression\Keijzer\KeijzerFunctionEleven.cs" />
@@ -179,4 +185,6 @@
     <Compile Include="Regression\Korns\KornsFunctionTwo.cs" />
     <Compile Include="Regression\Korns\KornsInstanceProvider.cs" />
+    <Compile Include="Regression\Friedman\FriedmanRandomFunction.cs" />
+    <Compile Include="Regression\Friedman\FriedmanRandomFunctionInstanceProvider.cs" />
     <Compile Include="Regression\Nguyen\NguyenFunctionEight.cs" />
     <Compile Include="Regression\Nguyen\NguyenFunctionEleven.cs" />
Index: stable/HeuristicLab.Problems.Instances.DataAnalysis/3.3/Plugin.cs.frame
===================================================================
--- stable/HeuristicLab.Problems.Instances.DataAnalysis/3.3/Plugin.cs.frame	(revision 14116)
+++ stable/HeuristicLab.Problems.Instances.DataAnalysis/3.3/Plugin.cs.frame	(revision 14117)
@@ -25,4 +25,5 @@
   [Plugin("HeuristicLab.Problems.Instances.DataAnalysis", "3.3.13.$WCREV$")]
   [PluginFile("HeuristicLab.Problems.Instances.DataAnalysis-3.3.dll", PluginFileType.Assembly)]
+  [PluginDependency("HeuristicLab.ALGLIB", "3.7")]
   [PluginDependency("HeuristicLab.Common", "3.3")]
   [PluginDependency("HeuristicLab.Collections", "3.3")]
Index: stable/HeuristicLab.Problems.Instances.DataAnalysis/3.3/Regression/Friedman/FriedmanRandomFunction.cs
===================================================================
--- stable/HeuristicLab.Problems.Instances.DataAnalysis/3.3/Regression/Friedman/FriedmanRandomFunction.cs	(revision 14117)
+++ stable/HeuristicLab.Problems.Instances.DataAnalysis/3.3/Regression/Friedman/FriedmanRandomFunction.cs	(revision 14117)
@@ -0,0 +1,149 @@
+﻿#region License Information
+/* HeuristicLab
+ * Copyright (C) 2002-2015 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.Random;
+
+namespace HeuristicLab.Problems.Instances.DataAnalysis {
+  public class FriedmanRandomFunction : ArtificialRegressionDataDescriptor {
+    private readonly int nTrainingSamples;
+    private readonly int nTestSamples;
+
+    private readonly int numberOfFeatures;
+    private readonly double noiseRatio;
+    private readonly IRandom random;
+
+    public override string Name { get { return string.Format("FriedmanRandomFunction-{0:0%} ({1} dim)", noiseRatio, numberOfFeatures); } }
+    public override string Description {
+      get {
+        return "The data are generated using the random function generator described in 'Friedman: Greedy Function Approximation: A Gradient Boosting Machine, 1999'.";
+      }
+    }
+
+    public FriedmanRandomFunction(int numberOfFeatures, double noiseRatio,
+      IRandom rand)
+      : this(500, 5000, numberOfFeatures, noiseRatio, rand) { }
+
+    public FriedmanRandomFunction(int nTrainingSamples, int nTestSamples,
+      int numberOfFeatures, double noiseRatio, IRandom rand) {
+      this.nTrainingSamples = nTrainingSamples;
+      this.nTestSamples = nTestSamples;
+      this.noiseRatio = noiseRatio;
+      this.random = rand;
+      this.numberOfFeatures = numberOfFeatures;
+    }
+
+    protected override string TargetVariable { get { return "Y"; } }
+
+    protected override string[] VariableNames {
+      get { return AllowedInputVariables.Concat(new string[] { "Y" }).ToArray(); }
+    }
+
+    protected override string[] AllowedInputVariables {
+      get {
+        return Enumerable.Range(1, numberOfFeatures)
+          .Select(i => string.Format("X{0:000}", i))
+          .ToArray();
+      }
+    }
+
+    protected override int TrainingPartitionStart { get { return 0; } }
+    protected override int TrainingPartitionEnd { get { return nTrainingSamples; } }
+    protected override int TestPartitionStart { get { return nTrainingSamples; } }
+    protected override int TestPartitionEnd { get { return nTrainingSamples + nTestSamples; } }
+
+
+    protected override List<List<double>> GenerateValues() {
+      List<List<double>> data = new List<List<double>>();
+
+      var nrand = new NormalDistributedRandom(random, 0, 1);
+      for (int c = 0; c < numberOfFeatures; c++) {
+        var datai = Enumerable.Range(0, TestPartitionEnd).Select(_ => nrand.NextDouble()).ToList();
+        data.Add(datai);
+      }
+      var y = GenerateRandomFunction(random, data);
+
+      var targetSigma = y.StandardDeviation();
+      var noisePrng = new NormalDistributedRandom(random, 0, targetSigma * Math.Sqrt(noiseRatio / (1.0 - noiseRatio)));
+
+      data.Add(y.Select(t => t + noisePrng.NextDouble()).ToList());
+
+      return data;
+    }
+
+    // as described in Greedy Function Approxination paper
+    private IEnumerable<double> GenerateRandomFunction(IRandom rand, List<List<double>> xs, int nTerms = 20) {
+      int nRows = xs.First().Count;
+
+      var gz = new List<double[]>();
+      for (int i = 0; i < nTerms; i++) {
+
+        // alpha ~ U(-1, 1)
+        double alpha = rand.NextDouble() * 2 - 1;
+        double r = -Math.Log(1.0 - rand.NextDouble()) * 2.0; // r is exponentially distributed with lambda = 2
+        int nl = (int)Math.Floor(1.5 + r); // number of selected vars is likely to be between three and four
+
+
+        var selectedVars = xs.Shuffle(random).Take(nl).ToArray();
+        gz.Add(SampleRandomFunction(random, selectedVars)
+          .Select(f => alpha * f)
+          .ToArray());
+      }
+      // sum up
+      return Enumerable.Range(0, nRows)
+        .Select(r => gz.Sum(gzi => gzi[r]));
+    }
+
+    private IEnumerable<double> SampleRandomFunction(IRandom random, List<double>[] xs) {
+      int nl = xs.Length;
+      // mu is generated from same distribution as x
+      double[] mu = Enumerable.Range(0, nl).Select(_ => random.NextDouble() * 2 - 1).ToArray();
+      double[,] v = new double[nl, nl];
+      var condNum = 4.0 / 0.01; // as given in the paper for max and min eigen values
+
+      // temporarily use different random number generator in alglib
+      var curRand = alglib.math.rndobject;
+      alglib.math.rndobject = new System.Random(random.Next());
+
+      alglib.matgen.spdmatrixrndcond(nl, condNum, ref v);
+      // restore
+      alglib.math.rndobject = curRand;
+
+      int nRows = xs.First().Count;
+      var z = new double[nl];
+      var y = new double[nl];
+      for (int i = 0; i < nRows; i++) {
+        for (int j = 0; j < nl; j++) z[j] = xs[j][i] - mu[j];
+        alglib.ablas.rmatrixmv(nl, nl, v, 0, 0, 0, z, 0, ref y, 0);
+
+        // dot prod
+        var s = 0.0;
+        for (int j = 0; j < nl; j++) s += z[j] * y[j];
+
+        yield return s;
+      }
+    }
+  }
+}
Index: stable/HeuristicLab.Problems.Instances.DataAnalysis/3.3/Regression/Friedman/FriedmanRandomFunctionInstanceProvider.cs
===================================================================
--- stable/HeuristicLab.Problems.Instances.DataAnalysis/3.3/Regression/Friedman/FriedmanRandomFunctionInstanceProvider.cs	(revision 14117)
+++ stable/HeuristicLab.Problems.Instances.DataAnalysis/3.3/Regression/Friedman/FriedmanRandomFunctionInstanceProvider.cs	(revision 14117)
@@ -0,0 +1,62 @@
+﻿#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 HeuristicLab.Problems.DataAnalysis;
+using HeuristicLab.Random;
+
+namespace HeuristicLab.Problems.Instances.DataAnalysis {
+  public class FriedmanRandomFunctionInstanceProvider : ArtificialRegressionInstanceProvider {
+    public override string Name {
+      get { return "Friedman Random Functions"; }
+    }
+    public override string Description {
+      get { return "A set of regression benchmark instances as described by Friedman in the Greedy Function Approximation paper"; }
+    }
+    public override Uri WebLink {
+      get { return new Uri("http://dev.heuristiclab.com"); }
+    }
+    public override string ReferencePublication {
+      get { return "Friedman, Jerome H. 'Greedy function approximation: a gradient boosting machine.' Annals of statistics (2001): 1189-1232."; }
+    }
+
+    public override IEnumerable<IDataDescriptor> GetDataDescriptors() {
+      var numVariables = new int[] { 10, 25, 50, 100 };
+      var noiseRatios = new double[] { 0.01, 0.05, 0.1 };
+      var rand = new System.Random(1234); // use fixed seed for deterministic problem generation
+      return (from size in numVariables
+              from noiseRatio in noiseRatios
+              select new FriedmanRandomFunction(size, noiseRatio, new MersenneTwister((uint)rand.Next())))
+              .Cast<IDataDescriptor>()
+              .ToList();
+    }
+
+    public override IRegressionProblemData LoadData(IDataDescriptor descriptor) {
+      var frfDescriptor = descriptor as FriedmanRandomFunction;
+      if (frfDescriptor == null) throw new ArgumentException("FriedmanRandomFunctionInstanceProvider expects an FriedmanRandomFunction data descriptor.");
+      // base call generates a regression problem data
+      var problemData = base.LoadData(frfDescriptor);
+      return problemData;
+    }
+  }
+}
Index: stable/HeuristicLab.Problems.Instances.DataAnalysis/3.3/Regression/VariableNetworks/VariableNetwork.cs
===================================================================
--- stable/HeuristicLab.Problems.Instances.DataAnalysis/3.3/Regression/VariableNetworks/VariableNetwork.cs	(revision 14117)
+++ stable/HeuristicLab.Problems.Instances.DataAnalysis/3.3/Regression/VariableNetworks/VariableNetwork.cs	(revision 14117)
@@ -0,0 +1,223 @@
+﻿#region License Information
+/* HeuristicLab
+ * Copyright (C) 2002-2015 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.Random;
+
+namespace HeuristicLab.Problems.Instances.DataAnalysis {
+  public class VariableNetwork : ArtificialRegressionDataDescriptor {
+    private int nTrainingSamples;
+    private int nTestSamples;
+
+    private int numberOfFeatures;
+    private double noiseRatio;
+    private IRandom random;
+
+    public override string Name { get { return string.Format("VariableNetwork-{0:0%} ({1} dim)", noiseRatio, numberOfFeatures); } }
+    private string networkDefinition;
+    public string NetworkDefinition { get { return networkDefinition; } }
+    public override string Description {
+      get {
+        return "The data are generated specifically to test methods for variable network analysis.";
+      }
+    }
+
+    public VariableNetwork(int numberOfFeatures, double noiseRatio,
+      IRandom rand)
+      : this(250, 250, numberOfFeatures, noiseRatio, rand) { }
+
+    public VariableNetwork(int nTrainingSamples, int nTestSamples,
+      int numberOfFeatures, double noiseRatio, IRandom rand) {
+      this.nTrainingSamples = nTrainingSamples;
+      this.nTestSamples = nTestSamples;
+      this.noiseRatio = noiseRatio;
+      this.random = rand;
+      this.numberOfFeatures = numberOfFeatures;
+      // default variable names
+      variableNames = Enumerable.Range(1, numberOfFeatures)
+        .Select(i => string.Format("X{0:000}", i))
+        .ToArray();
+    }
+
+    private string[] variableNames;
+    protected override string[] VariableNames {
+      get {
+        return variableNames;
+      }
+    }
+
+    // there is no specific target variable in variable network analysis but we still need to specify one
+    protected override string TargetVariable { get { return VariableNames.Last(); } }
+
+    protected override string[] AllowedInputVariables {
+      get {
+        return VariableNames.Take(numberOfFeatures - 1).ToArray();
+      }
+    }
+
+    protected override int TrainingPartitionStart { get { return 0; } }
+    protected override int TrainingPartitionEnd { get { return nTrainingSamples; } }
+    protected override int TestPartitionStart { get { return nTrainingSamples; } }
+    protected override int TestPartitionEnd { get { return nTrainingSamples + nTestSamples; } }
+
+
+    protected override List<List<double>> GenerateValues() {
+      // variable names are shuffled in the beginning (and sorted at the end)
+      variableNames = variableNames.Shuffle(random).ToArray();
+
+      // a third of all variables are independent vars
+      List<List<double>> lvl0 = new List<List<double>>();
+      int numLvl0 = (int)Math.Ceiling(numberOfFeatures * 0.33);
+
+      List<string> description = new List<string>(); // store information how the variable is actually produced
+      List<string[]> inputVarNames = new List<string[]>(); // store information to produce graphviz file
+
+      var nrand = new NormalDistributedRandom(random, 0, 1);
+      for (int c = 0; c < numLvl0; c++) {
+        var datai = Enumerable.Range(0, TestPartitionEnd).Select(_ => nrand.NextDouble()).ToList();
+        inputVarNames.Add(new string[] { });
+        description.Add("~ N(0, 1)");
+        lvl0.Add(datai);
+      }
+
+      // lvl1 contains variables which are functions of vars in lvl0 (+ noise)
+      List<List<double>> lvl1 = new List<List<double>>();
+      int numLvl1 = (int)Math.Ceiling(numberOfFeatures * 0.33);
+      for (int c = 0; c < numLvl1; c++) {
+        string[] selectedVarNames;
+        var x = GenerateRandomFunction(random, lvl0, out selectedVarNames);
+        var sigma = x.StandardDeviation();
+        var noisePrng = new NormalDistributedRandom(random, 0, sigma * Math.Sqrt(noiseRatio / (1.0 - noiseRatio)));
+        lvl1.Add(x.Select(t => t + noisePrng.NextDouble()).ToList());
+
+        inputVarNames.Add(selectedVarNames);
+        var desc = string.Format("f({0})", string.Join(",", selectedVarNames));
+        description.Add(string.Format(" ~ N({0}, {1:N3})", desc, noisePrng.Sigma));
+      }
+
+      // lvl2 contains variables which are functions of vars in lvl0 and lvl1 (+ noise)
+      List<List<double>> lvl2 = new List<List<double>>();
+      int numLvl2 = (int)Math.Ceiling(numberOfFeatures * 0.2);
+      for (int c = 0; c < numLvl2; c++) {
+        string[] selectedVarNames;
+        var x = GenerateRandomFunction(random, lvl0.Concat(lvl1).ToList(), out selectedVarNames);
+        var sigma = x.StandardDeviation();
+        var noisePrng = new NormalDistributedRandom(random, 0, sigma * Math.Sqrt(noiseRatio / (1.0 - noiseRatio)));
+        lvl2.Add(x.Select(t => t + noisePrng.NextDouble()).ToList());
+
+        inputVarNames.Add(selectedVarNames);
+        var desc = string.Format("f({0})", string.Join(",", selectedVarNames));
+        description.Add(string.Format(" ~ N({0}, {1:N3})", desc, noisePrng.Sigma));
+      }
+
+      // lvl3 contains variables which are functions of vars in lvl0, lvl1 and lvl2 (+ noise)
+      List<List<double>> lvl3 = new List<List<double>>();
+      int numLvl3 = numberOfFeatures - numLvl0 - numLvl1 - numLvl2;
+      for (int c = 0; c < numLvl3; c++) {
+        string[] selectedVarNames;
+        var x = GenerateRandomFunction(random, lvl0.Concat(lvl1).Concat(lvl2).ToList(), out selectedVarNames);
+        var sigma = x.StandardDeviation();
+        var noisePrng = new NormalDistributedRandom(random, 0, sigma * Math.Sqrt(noiseRatio / (1.0 - noiseRatio)));
+        lvl3.Add(x.Select(t => t + noisePrng.NextDouble()).ToList());
+
+        inputVarNames.Add(selectedVarNames);
+        var desc = string.Format("f({0})", string.Join(",", selectedVarNames));
+        description.Add(string.Format(" ~ N({0}, {1:N3})", desc, noisePrng.Sigma));
+      }
+
+      networkDefinition = string.Join(Environment.NewLine, variableNames.Zip(description, (n, d) => n + d));
+      // for graphviz
+      networkDefinition += Environment.NewLine + "digraph G {";
+      foreach (var t in variableNames.Zip(inputVarNames, Tuple.Create).OrderBy(t => t.Item1)) {
+        var name = t.Item1;
+        var selectedVarNames = t.Item2;
+        foreach (var selectedVarName in selectedVarNames) {
+          networkDefinition += Environment.NewLine + selectedVarName + " -> " + name;
+        }
+      }
+      networkDefinition += Environment.NewLine + "}";
+
+      // return a random permutation of all variables
+      var allVars = lvl0.Concat(lvl1).Concat(lvl2).Concat(lvl3).ToList();
+      var orderedVars = allVars.Zip(variableNames, Tuple.Create).OrderBy(t => t.Item2).Select(t => t.Item1).ToList();
+      variableNames = variableNames.OrderBy(n => n).ToArray();
+      return orderedVars;
+    }
+
+    // sample the input variables that are actually used and sample from a Gaussian process
+    private IEnumerable<double> GenerateRandomFunction(IRandom rand, List<List<double>> xs, out string[] selectedVarNames) {
+      double r = -Math.Log(1.0 - rand.NextDouble()) * 2.0; // r is exponentially distributed with lambda = 2
+      int nl = (int)Math.Floor(1.5 + r); // number of selected vars is likely to be between three and four
+      if (nl > xs.Count) nl = xs.Count; // limit max
+
+      var selectedIdx = Enumerable.Range(0, xs.Count).Shuffle(random)
+        .Take(nl).ToArray();
+
+      var selectedVars = selectedIdx.Select(i => xs[i]).ToArray();
+      selectedVarNames = selectedIdx.Select(i => VariableNames[i]).ToArray();
+      return SampleGaussianProcess(random, selectedVars);
+    }
+
+    private IEnumerable<double> SampleGaussianProcess(IRandom random, List<double>[] xs) {
+      int nl = xs.Length;
+      int nRows = xs.First().Count;
+      double[,] K = new double[nRows, nRows];
+
+      // sample length-scales
+      var l = Enumerable.Range(0, nl)
+        .Select(_ => random.NextDouble() * 2 + 0.5)
+        .ToArray();
+      // calculate covariance matrix
+      for (int r = 0; r < nRows; r++) {
+        double[] xi = xs.Select(x => x[r]).ToArray();
+        for (int c = 0; c <= r; c++) {
+          double[] xj = xs.Select(x => x[c]).ToArray();
+          double dSqr = xi.Zip(xj, (xik, xjk) => (xik - xjk))
+            .Select(dk => dk * dk)
+            .Zip(l, (dk, lk) => dk / lk)
+            .Sum();
+          K[r, c] = Math.Exp(-dSqr);
+        }
+      }
+
+      // add a small diagonal matrix for numeric stability
+      for (int i = 0; i < nRows; i++) {
+        K[i, i] += 1.0E-7;
+      }
+
+      // decompose
+      alglib.trfac.spdmatrixcholesky(ref K, nRows, false);
+
+      // sample u iid ~ N(0, 1)
+      var u = Enumerable.Range(0, nRows).Select(_ => NormalDistributedRandom.NextDouble(random, 0, 1)).ToArray();
+
+      // calc y = Lu
+      var y = new double[u.Length];
+      alglib.ablas.rmatrixmv(nRows, nRows, K, 0, 0, 0, u, 0, ref y, 0);
+
+      return y;
+    }
+  }
+}
Index: stable/HeuristicLab.Problems.Instances.DataAnalysis/3.3/Regression/VariableNetworks/VariableNetworkInstanceProvider.cs
===================================================================
--- stable/HeuristicLab.Problems.Instances.DataAnalysis/3.3/Regression/VariableNetworks/VariableNetworkInstanceProvider.cs	(revision 14117)
+++ stable/HeuristicLab.Problems.Instances.DataAnalysis/3.3/Regression/VariableNetworks/VariableNetworkInstanceProvider.cs	(revision 14117)
@@ -0,0 +1,63 @@
+﻿#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 HeuristicLab.Problems.DataAnalysis;
+using HeuristicLab.Random;
+
+namespace HeuristicLab.Problems.Instances.DataAnalysis {
+  public class VariableNetworkInstanceProvider : ArtificialRegressionInstanceProvider {
+    public override string Name {
+      get { return "Variable Network Instances"; }
+    }
+    public override string Description {
+      get { return "A set of regression benchmark instances for variable network analysis"; }
+    }
+    public override Uri WebLink {
+      get { return new Uri("http://dev.heuristiclab.com"); }
+    }
+    public override string ReferencePublication {
+      get { return ""; }
+    }
+
+    public override IEnumerable<IDataDescriptor> GetDataDescriptors() {
+      var numVariables = new int[] { 10, 20, 50, 100 };
+      var noiseRatios = new double[] { 0.01, 0.05, 0.1 };
+      var rand = new System.Random(1234); // use fixed seed for deterministic problem generation
+      return (from size in numVariables
+              from noiseRatio in noiseRatios
+              select new VariableNetwork(size, noiseRatio, new MersenneTwister((uint)rand.Next())))
+              .Cast<IDataDescriptor>()
+              .ToList();
+    }
+
+    public override IRegressionProblemData LoadData(IDataDescriptor descriptor) {
+      var varNetwork = descriptor as VariableNetwork;
+      if (varNetwork == null) throw new ArgumentException("VariableNetworkInstanceProvider expects an VariableNetwork data descriptor.");
+      // base call generates a regression problem data
+      var problemData = base.LoadData(varNetwork);
+      problemData.Description = varNetwork.Description + Environment.NewLine + varNetwork.NetworkDefinition;
+      return problemData;
+    }
+  }
+}
