Index: trunk/sources/HeuristicLab.Algorithms.DataAnalysis/3.4/GaussianProcess/MeanFunctions/MeanConst.cs
===================================================================
--- trunk/sources/HeuristicLab.Algorithms.DataAnalysis/3.4/GaussianProcess/MeanFunctions/MeanConst.cs	(revision 8929)
+++ trunk/sources/HeuristicLab.Algorithms.DataAnalysis/3.4/GaussianProcess/MeanFunctions/MeanConst.cs	(revision 8982)
@@ -21,8 +21,10 @@
 
 using System;
+using System.Collections.Generic;
 using System.Linq;
 using HeuristicLab.Common;
 using HeuristicLab.Core;
 using HeuristicLab.Data;
+using HeuristicLab.Parameters;
 using HeuristicLab.Persistence.Default.CompositeSerializers.Storable;
 
@@ -31,9 +33,7 @@
   [Item(Name = "MeanConst", Description = "Constant mean function for Gaussian processes.")]
   public sealed class MeanConst : ParameterizedNamedItem, IMeanFunction {
-    [Storable]
-    private double c;
-    [Storable]
-    private readonly HyperParameter<DoubleValue> valueParameter;
-    public IValueParameter<DoubleValue> ValueParameter { get { return valueParameter; } }
+    public IValueParameter<DoubleValue> ValueParameter {
+      get { return (IValueParameter<DoubleValue>)Parameters["Value"]; }
+    }
 
     [StorableConstructor]
@@ -41,7 +41,4 @@
     private MeanConst(MeanConst original, Cloner cloner)
       : base(original, cloner) {
-      this.c = original.c;
-      this.valueParameter = cloner.Clone(original.valueParameter);
-      RegisterEvents();
     }
     public MeanConst()
@@ -50,7 +47,5 @@
       this.description = ItemDescription;
 
-      this.valueParameter = new HyperParameter<DoubleValue>("Value", "The constant value for the constant mean function.");
-      Parameters.Add(valueParameter);
-      RegisterEvents();
+      Parameters.Add(new OptionalValueParameter<DoubleValue>("Value", "The constant value for the constant mean function."));
     }
 
@@ -59,31 +54,36 @@
     }
 
-    [StorableHook(HookType.AfterDeserialization)]
-    private void AfterDeserialization() {
-      RegisterEvents();
+    public int GetNumberOfParameters(int numberOfVariables) {
+      return ValueParameter.Value != null ? 0 : 1;
     }
 
-    private void RegisterEvents() {
-      Util.AttachValueChangeHandler<DoubleValue, double>(valueParameter, () => { c = valueParameter.Value.Value; });
+    public void SetParameter(double[] p) {
+      double c;
+      GetParameters(p, out c);
+      ValueParameter.Value = new DoubleValue(c);
     }
 
-    public int GetNumberOfParameters(int numberOfVariables) {
-      return valueParameter.Fixed ? 0 : 1;
+    private void GetParameters(double[] p, out double c) {
+      if (ValueParameter.Value == null) {
+        c = p[0];
+      } else {
+        if (p.Length > 0)
+          throw new ArgumentException(
+            "The length of the parameter vector does not match the number of free parameters for the constant mean function.",
+            "p");
+        c = ValueParameter.Value.Value;
+      }
     }
 
-    public void SetParameter(double[] hyp) {
-      if (!valueParameter.Fixed) {
-        valueParameter.SetValue(new DoubleValue(hyp[0]));
-      } else if (hyp.Length > 0)
-        throw new ArgumentException("The length of the parameter vector does not match the number of free parameters for the constant mean function.", "hyp");
-    }
-
-    public double[] GetMean(double[,] x) {
-      return Enumerable.Repeat(c, x.GetLength(0)).ToArray();
-    }
-
-    public double[] GetGradients(int k, double[,] x) {
-      if (k > 0) throw new ArgumentException();
-      return Enumerable.Repeat(1.0, x.GetLength(0)).ToArray();
+    public ParameterizedMeanFunction GetParameterizedMeanFunction(double[] p, IEnumerable<int> columnIndices) {
+      double c;
+      GetParameters(p, out c);
+      var mf = new ParameterizedMeanFunction();
+      mf.Mean = (x, i) => c;
+      mf.Gradient = (x, i, k) => {
+        if (k > 0) throw new ArgumentException();
+        return 1.0;
+      };
+      return mf;
     }
   }
Index: trunk/sources/HeuristicLab.Algorithms.DataAnalysis/3.4/GaussianProcess/MeanFunctions/MeanLinear.cs
===================================================================
--- trunk/sources/HeuristicLab.Algorithms.DataAnalysis/3.4/GaussianProcess/MeanFunctions/MeanLinear.cs	(revision 8929)
+++ trunk/sources/HeuristicLab.Algorithms.DataAnalysis/3.4/GaussianProcess/MeanFunctions/MeanLinear.cs	(revision 8982)
@@ -21,8 +21,10 @@
 
 using System;
+using System.Collections.Generic;
 using System.Linq;
 using HeuristicLab.Common;
 using HeuristicLab.Core;
 using HeuristicLab.Data;
+using HeuristicLab.Parameters;
 using HeuristicLab.Persistence.Default.CompositeSerializers.Storable;
 
@@ -31,9 +33,7 @@
   [Item(Name = "MeanLinear", Description = "Linear mean function for Gaussian processes.")]
   public sealed class MeanLinear : ParameterizedNamedItem, IMeanFunction {
-    [Storable]
-    private double[] weights;
-    [Storable]
-    private readonly HyperParameter<DoubleArray> weightsParameter;
-    public IValueParameter<DoubleArray> WeightsParameter { get { return weightsParameter; } }
+    public IValueParameter<DoubleArray> WeightsParameter {
+      get { return (IValueParameter<DoubleArray>)Parameters["Weights"]; }
+    }
 
     [StorableConstructor]
@@ -41,16 +41,8 @@
     private MeanLinear(MeanLinear original, Cloner cloner)
       : base(original, cloner) {
-      if (original.weights != null) {
-        this.weights = new double[original.weights.Length];
-        Array.Copy(original.weights, weights, original.weights.Length);
-      }
-      weightsParameter = cloner.Clone(original.weightsParameter);
-      RegisterEvents();
     }
     public MeanLinear()
       : base() {
-      this.weightsParameter = new HyperParameter<DoubleArray>("Weights", "The weights parameter for the linear mean function.");
-      Parameters.Add(weightsParameter);
-      RegisterEvents();
+      Parameters.Add(new OptionalValueParameter<DoubleArray>("Weights", "The weights parameter for the linear mean function."));
     }
 
@@ -59,41 +51,38 @@
     }
 
-    [StorableHook(HookType.AfterDeserialization)]
-    private void AfterDeserialization() {
-      RegisterEvents();
+    public int GetNumberOfParameters(int numberOfVariables) {
+      return WeightsParameter.Value != null ? 0 : numberOfVariables;
     }
 
-    private void RegisterEvents() {
-      Util.AttachArrayChangeHandler<DoubleArray, double>(weightsParameter, () => {
-        weights = weightsParameter.Value.ToArray();
-      });
+    public void SetParameter(double[] p) {
+      double[] weights;
+      GetParameter(p, out weights);
+      WeightsParameter.Value = new DoubleArray(weights);
     }
 
-    public int GetNumberOfParameters(int numberOfVariables) {
-      return weightsParameter.Fixed ? 0 : numberOfVariables;
+    public void GetParameter(double[] p, out double[] weights) {
+      if (WeightsParameter.Value == null) {
+        weights = p;
+      } else {
+        if (p.Length != 0) throw new ArgumentException("The length of the parameter vector does not match the number of free parameters for the linear mean function.", "p");
+        weights = WeightsParameter.Value.ToArray();
+      }
     }
 
-    public void SetParameter(double[] hyp) {
-      if (!weightsParameter.Fixed) {
-        weightsParameter.SetValue(new DoubleArray(hyp));
-      } else if (hyp.Length != 0) throw new ArgumentException("The length of the parameter vector does not match the number of free parameters for the linear mean function.", "hyp");
-    }
-
-    public double[] GetMean(double[,] x) {
-      // sanity check
-      if (weights.Length != x.GetLength(1)) throw new ArgumentException("The number of hyperparameters must match the number of variables for the linear mean function.");
-      int cols = x.GetLength(1);
-      int n = x.GetLength(0);
-      return (from i in Enumerable.Range(0, n)
-              let rowVector = Enumerable.Range(0, cols).Select(j => x[i, j])
-              select Util.ScalarProd(weights, rowVector))
-        .ToArray();
-    }
-
-    public double[] GetGradients(int k, double[,] x) {
-      int cols = x.GetLength(1);
-      int n = x.GetLength(0);
-      if (k > cols) throw new ArgumentException();
-      return (Enumerable.Range(0, n).Select(r => x[r, k])).ToArray();
+    public ParameterizedMeanFunction GetParameterizedMeanFunction(double[] p, IEnumerable<int> columnIndices) {
+      double[] weights;
+      int[] columns = columnIndices.ToArray();
+      GetParameter(p, out weights);
+      var mf = new ParameterizedMeanFunction();
+      mf.Mean = (x, i) => {
+        // sanity check
+        if (weights.Length != columns.Length) throw new ArgumentException("The number of rparameters must match the number of variables for the linear mean function.");
+        return Util.ScalarProd(weights, Util.GetRow(x, i, columns));
+      };
+      mf.Gradient = (x, i, k) => {
+        if (k > columns.Length) throw new ArgumentException();
+        return x[i, columns[k]];
+      };
+      return mf;
     }
   }
Index: trunk/sources/HeuristicLab.Algorithms.DataAnalysis/3.4/GaussianProcess/MeanFunctions/MeanProduct.cs
===================================================================
--- trunk/sources/HeuristicLab.Algorithms.DataAnalysis/3.4/GaussianProcess/MeanFunctions/MeanProduct.cs	(revision 8929)
+++ trunk/sources/HeuristicLab.Algorithms.DataAnalysis/3.4/GaussianProcess/MeanFunctions/MeanProduct.cs	(revision 8982)
@@ -19,4 +19,6 @@
  */
 #endregion
+
+using System.Collections.Generic;
 using System.Linq;
 using HeuristicLab.Common;
@@ -61,43 +63,50 @@
     }
 
-    public void SetParameter(double[] hyp) {
+    public void SetParameter(double[] p) {
       int offset = 0;
       foreach (var t in factors) {
         var numberOfParameters = t.GetNumberOfParameters(numberOfVariables);
-        t.SetParameter(hyp.Skip(offset).Take(numberOfParameters).ToArray());
+        t.SetParameter(p.Skip(offset).Take(numberOfParameters).ToArray());
         offset += numberOfParameters;
       }
     }
 
-    public double[] GetMean(double[,] x) {
-      var res = factors.First().GetMean(x);
-      foreach (var t in factors.Skip(1)) {
-        var a = t.GetMean(x);
-        for (int i = 0; i < res.Length; i++) res[i] *= a[i];
-      }
-      return res;
-    }
 
-    public double[] GetGradients(int k, double[,] x) {
-      double[] res = Enumerable.Repeat(1.0, x.GetLength(0)).ToArray();
-      // find index of factor for the given k
-      int j = 0;
-      while (k >= factors[j].GetNumberOfParameters(numberOfVariables)) {
-        k -= factors[j].GetNumberOfParameters(numberOfVariables);
-        j++;
-      }
-      for (int i = 0; i < factors.Count; i++) {
-        var f = factors[i];
-        if (i == j) {
-          // multiply gradient
-          var g = f.GetGradients(k, x);
-          for (int ii = 0; ii < res.Length; ii++) res[ii] *= g[ii];
-        } else {
-          // multiply mean
-          var m = f.GetMean(x);
-          for (int ii = 0; ii < res.Length; ii++) res[ii] *= m[ii];
+    public ParameterizedMeanFunction GetParameterizedMeanFunction(double[] p, IEnumerable<int> columnIndices) {
+      var factorMf = new List<ParameterizedMeanFunction>();
+      int totalNumberOfParameters = GetNumberOfParameters(numberOfVariables);
+      int[] factorIndexMap = new int[totalNumberOfParameters]; // maps k-th hyperparameter to the correct mean-term
+      int[] hyperParameterIndexMap = new int[totalNumberOfParameters]; // maps k-th hyperparameter to the l-th hyperparameter of the correct mean-term
+      int c = 0;
+      // get the parameterized mean function for each term
+      for (int factorIndex = 0; factorIndex < factors.Count; factorIndex++) {
+        var numberOfParameters = factors[factorIndex].GetNumberOfParameters(numberOfVariables);
+        factorMf.Add(factors[factorIndex].GetParameterizedMeanFunction(p.Take(numberOfParameters).ToArray(), columnIndices));
+        p = p.Skip(numberOfParameters).ToArray();
+
+        for (int hyperParameterIndex = 0; hyperParameterIndex < numberOfParameters; hyperParameterIndex++) {
+          factorIndexMap[c] = factorIndex;
+          hyperParameterIndexMap[c] = hyperParameterIndex;
+          c++;
         }
       }
-      return res;
+
+      var mf = new ParameterizedMeanFunction();
+      mf.Mean = (x, i) => factorMf.Select(t => t.Mean(x, i)).Aggregate((a, b) => a * b);
+      mf.Gradient = (x, i, k) => {
+        double result = 1.0;
+        int hyperParameterFactorIndex = factorIndexMap[k];
+        for (int factorIndex = 0; factorIndex < factors.Count; factorIndex++) {
+          if (factorIndex == hyperParameterFactorIndex) {
+            // multiply gradient
+            result *= factorMf[factorIndex].Gradient(x, i, hyperParameterIndexMap[k]);
+          } else {
+            // multiply mean
+            result *= factorMf[factorIndex].Mean(x, i);
+          }
+        }
+        return result;
+      };
+      return mf;
     }
   }
Index: trunk/sources/HeuristicLab.Algorithms.DataAnalysis/3.4/GaussianProcess/MeanFunctions/MeanSum.cs
===================================================================
--- trunk/sources/HeuristicLab.Algorithms.DataAnalysis/3.4/GaussianProcess/MeanFunctions/MeanSum.cs	(revision 8929)
+++ trunk/sources/HeuristicLab.Algorithms.DataAnalysis/3.4/GaussianProcess/MeanFunctions/MeanSum.cs	(revision 8982)
@@ -19,4 +19,6 @@
  */
 #endregion
+
+using System.Collections.Generic;
 using System.Linq;
 using HeuristicLab.Common;
@@ -57,29 +59,38 @@
     }
 
-    public void SetParameter(double[] hyp) {
+    public void SetParameter(double[] p) {
       int offset = 0;
       foreach (var t in terms) {
         var numberOfParameters = t.GetNumberOfParameters(numberOfVariables);
-        t.SetParameter(hyp.Skip(offset).Take(numberOfParameters).ToArray());
+        t.SetParameter(p.Skip(offset).Take(numberOfParameters).ToArray());
         offset += numberOfParameters;
       }
     }
 
-    public double[] GetMean(double[,] x) {
-      var res = terms.First().GetMean(x);
-      foreach (var t in terms.Skip(1)) {
-        var a = t.GetMean(x);
-        for (int i = 0; i < res.Length; i++) res[i] += a[i];
+    public ParameterizedMeanFunction GetParameterizedMeanFunction(double[] p, IEnumerable<int> columnIndices) {
+      var termMf = new List<ParameterizedMeanFunction>();
+      int totalNumberOfParameters = GetNumberOfParameters(numberOfVariables);
+      int[] termIndexMap = new int[totalNumberOfParameters]; // maps k-th parameter to the correct mean-term
+      int[] hyperParameterIndexMap = new int[totalNumberOfParameters]; // maps k-th parameter to the l-th parameter of the correct mean-term
+      int c = 0;
+      // get the parameterized mean function for each term
+      for (int termIndex = 0; termIndex < terms.Count; termIndex++) {
+        var numberOfParameters = terms[termIndex].GetNumberOfParameters(numberOfVariables);
+        termMf.Add(terms[termIndex].GetParameterizedMeanFunction(p.Take(numberOfParameters).ToArray(), columnIndices));
+        p = p.Skip(numberOfParameters).ToArray();
+
+        for (int hyperParameterIndex = 0; hyperParameterIndex < numberOfParameters; hyperParameterIndex++) {
+          termIndexMap[c] = termIndex;
+          hyperParameterIndexMap[c] = hyperParameterIndex;
+          c++;
+        }
       }
-      return res;
-    }
 
-    public double[] GetGradients(int k, double[,] x) {
-      int i = 0;
-      while (k >= terms[i].GetNumberOfParameters(numberOfVariables)) {
-        k -= terms[i].GetNumberOfParameters(numberOfVariables);
-        i++;
-      }
-      return terms[i].GetGradients(k, x);
+      var mf = new ParameterizedMeanFunction();
+      mf.Mean = (x, i) => termMf.Select(t => t.Mean(x, i)).Sum();
+      mf.Gradient = (x, i, k) => {
+        return termMf[termIndexMap[k]].Gradient(x, i, hyperParameterIndexMap[k]);
+      };
+      return mf;
     }
   }
Index: trunk/sources/HeuristicLab.Algorithms.DataAnalysis/3.4/GaussianProcess/MeanFunctions/MeanZero.cs
===================================================================
--- trunk/sources/HeuristicLab.Algorithms.DataAnalysis/3.4/GaussianProcess/MeanFunctions/MeanZero.cs	(revision 8929)
+++ trunk/sources/HeuristicLab.Algorithms.DataAnalysis/3.4/GaussianProcess/MeanFunctions/MeanZero.cs	(revision 8982)
@@ -20,4 +20,5 @@
 #endregion
 using System;
+using System.Collections.Generic;
 using System.Linq;
 using HeuristicLab.Common;
@@ -45,15 +46,18 @@
     }
 
-    public void SetParameter(double[] hyp) {
-      if (hyp.Length > 0) throw new ArgumentException("No hyper-parameters allowed for zero mean function.", "hyp");
+    public void SetParameter(double[] p) {
+      if (p.Length > 0) throw new ArgumentException("No parameters allowed for zero mean function.", "p");
     }
 
-    public double[] GetMean(double[,] x) {
-      return Enumerable.Repeat(0.0, x.GetLength(0)).ToArray();
-    }
-
-    public double[] GetGradients(int k, double[,] x) {
-      if (k > 0) throw new ArgumentException();
-      return Enumerable.Repeat(0.0, x.GetLength(0)).ToArray();
+    public ParameterizedMeanFunction GetParameterizedMeanFunction(double[] p, IEnumerable<int> columnIndices) {
+      if (p.Length > 0) throw new ArgumentException("No parameters allowed for zero mean function.", "p");
+      var mf = new ParameterizedMeanFunction();
+      mf.Mean = (x, i) => 0.0;
+      mf.Gradient = (x, i, k) => {
+        if (k > 0)
+          throw new ArgumentException();
+        return 0.0;
+      };
+      return mf;
     }
   }
