Index: branches/symbreg-factors-2650/HeuristicLab.Problems.Instances.DataAnalysis/3.3/Regression/VariableNetworks/VariableNetwork.cs
===================================================================
--- branches/symbreg-factors-2650/HeuristicLab.Problems.Instances.DataAnalysis/3.3/Regression/VariableNetworks/VariableNetwork.cs	(revision 14232)
+++ branches/symbreg-factors-2650/HeuristicLab.Problems.Instances.DataAnalysis/3.3/Regression/VariableNetworks/VariableNetwork.cs	(revision 14277)
@@ -22,4 +22,5 @@
 using System;
 using System.Collections.Generic;
+using System.Globalization;
 using System.Linq;
 using HeuristicLab.Common;
@@ -60,4 +61,6 @@
         .Select(i => string.Format("X{0:000}", i))
         .ToArray();
+
+      variableRelevances = new Dictionary<string, IEnumerable<KeyValuePair<string, double>>>();
     }
 
@@ -83,4 +86,8 @@
     protected override int TestPartitionEnd { get { return nTrainingSamples + nTestSamples; } }
 
+    private Dictionary<string, IEnumerable<KeyValuePair<string, double>>> variableRelevances;
+    public IEnumerable<KeyValuePair<string, double>> GetVariableRelevance(string targetVar) {
+      return variableRelevances[targetVar];
+    }
 
     protected override List<List<double>> GenerateValues() {
@@ -94,71 +101,52 @@
       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
+      List<double[]> relevances = new List<double[]>(); // stores variable relevance information (same order as given in inputVarNames)
 
       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);
+        relevances.Add(new double[] { });
+        description.Add(" ~ N(0, 1)");
+        lvl0.Add(Enumerable.Range(0, TestPartitionEnd).Select(_ => nrand.NextDouble()).ToList());
       }
 
       // 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));
-      }
+      List<List<double>> lvl1 = CreateVariables(lvl0, numLvl1, inputVarNames, description, relevances);
 
       // 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));
-      }
+      List<List<double>> lvl2 = CreateVariables(lvl0.Concat(lvl1).ToList(), numLvl2, inputVarNames, description, relevances);
 
       // 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));
+      List<List<double>> lvl3 = CreateVariables(lvl0.Concat(lvl1).Concat(lvl2).ToList(), numLvl3, inputVarNames, description, relevances);
+
+      this.variableRelevances.Clear();
+      for (int i = 0; i < variableNames.Length; i++) {
+        var targetVarName = variableNames[i];
+        var targetRelevantInputs =
+          inputVarNames[i].Zip(relevances[i], (inputVar, rel) => new KeyValuePair<string, double>(inputVar, rel))
+            .ToArray();
+        variableRelevances.Add(targetVarName, targetRelevantInputs);
+      }
+
+      networkDefinition = string.Join(Environment.NewLine, variableNames.Zip(description, (n, d) => n + d).OrderBy(x => x));
       // 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;
+      for (int i = 0; i < variableNames.Length; i++) {
+        var name = variableNames[i];
+        var selectedVarNames = inputVarNames[i];
+        var selectedRelevances = relevances[i];
+        for (int j = 0; j < selectedVarNames.Length; j++) {
+          var selectedVarName = selectedVarNames[j];
+          var selectedRelevance = selectedRelevances[j];
+          networkDefinition += Environment.NewLine + selectedVarName + " -> " + name +
+            string.Format(CultureInfo.InvariantCulture, " [label={0:N3}]", selectedRelevance);
         }
       }
       networkDefinition += Environment.NewLine + "}";
 
-      // return a random permutation of all variables
+      // return a random permutation of all variables (to mix lvl0, lvl1, ... 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();
@@ -167,6 +155,29 @@
     }
 
+    private List<List<double>> CreateVariables(List<List<double>> allowedInputs, int numVars, List<string[]> inputVarNames, List<string> description, List<double[]> relevances) {
+      var res = new List<List<double>>();
+      for (int c = 0; c < numVars; c++) {
+        string[] selectedVarNames;
+        double[] relevance;
+        var x = GenerateRandomFunction(random, allowedInputs, out selectedVarNames, out relevance);
+        var sigma = x.StandardDeviation();
+        var noisePrng = new NormalDistributedRandom(random, 0, sigma * Math.Sqrt(noiseRatio / (1.0 - noiseRatio)));
+        res.Add(x.Select(t => t + noisePrng.NextDouble()).ToList());
+        Array.Sort(selectedVarNames, relevance);
+        inputVarNames.Add(selectedVarNames);
+        relevances.Add(relevance);
+        var desc = string.Format("f({0})", string.Join(",", selectedVarNames));
+        // for the relevance information order variables by decreasing relevance
+        var relevanceStr = string.Join(", ",
+          selectedVarNames.Zip(relevance, Tuple.Create)
+          .OrderByDescending(t => t.Item2)
+          .Select(t => string.Format(CultureInfo.InvariantCulture, "{0}: {1:N3}", t.Item1, t.Item2)));
+        description.Add(string.Format(" ~ N({0}, {1:N3}) [Relevances: {2}]", desc, noisePrng.Sigma, relevanceStr));
+      }
+      return res;
+    }
+
     // 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) {
+    private IEnumerable<double> GenerateRandomFunction(IRandom rand, List<List<double>> xs, out string[] selectedVarNames, out double[] relevance) {
       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
@@ -178,8 +189,8 @@
       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) {
+      return SampleGaussianProcess(random, selectedVars, out relevance);
+    }
+
+    private IEnumerable<double> SampleGaussianProcess(IRandom random, List<double>[] xs, out double[] relevance) {
       int nl = xs.Length;
       int nRows = xs.First().Count;
@@ -218,4 +229,13 @@
       alglib.ablas.rmatrixmv(nRows, nRows, K, 0, 0, 0, u, 0, ref y, 0);
 
+      // calculate variable relevance
+      // as per Rasmussen and Williams "Gaussian Processes for Machine Learning" page 106:
+      // ,,For the squared exponential covariance function [...] the l1, ..., lD hyperparameters
+      // play the role of characteristic length scales [...]. Such a covariance function implements 
+      // automatic relevance determination (ARD) [Neal, 1996], since the inverse of the length-scale 
+      // determines how relevant an input is: if the length-scale has a very large value, the covariance 
+      // will become almost independent of that input, effectively removing it from inference.''
+      relevance = l.Select(li => 1.0 / li).ToArray();
+
       return y;
     }
Index: branches/symbreg-factors-2650/HeuristicLab.Problems.Instances.DataAnalysis/3.3/Regression/VariableNetworks/VariableNetworkInstanceProvider.cs
===================================================================
--- branches/symbreg-factors-2650/HeuristicLab.Problems.Instances.DataAnalysis/3.3/Regression/VariableNetworks/VariableNetworkInstanceProvider.cs	(revision 14232)
+++ branches/symbreg-factors-2650/HeuristicLab.Problems.Instances.DataAnalysis/3.3/Regression/VariableNetworks/VariableNetworkInstanceProvider.cs	(revision 14277)
@@ -49,5 +49,5 @@
     public override IEnumerable<IDataDescriptor> GetDataDescriptors() {
       var numVariables = new int[] { 10, 20, 50, 100 };
-      var noiseRatios = new double[] { 0.01, 0.05, 0.1 };
+      var noiseRatios = new double[] { 0, 0.01, 0.05, 0.1 };
       var rand = new MersenneTwister((uint)Seed); // use fixed seed for deterministic problem generation
       return (from size in numVariables
