Index: /branches/HeuristicLab.GoalSeekingProblem/HeuristicLab.GoalSeekingProblem/3.4/Analyzers/BestSolutionAnalyzer.cs
===================================================================
--- /branches/HeuristicLab.GoalSeekingProblem/HeuristicLab.GoalSeekingProblem/3.4/Analyzers/BestSolutionAnalyzer.cs	(revision 14323)
+++ /branches/HeuristicLab.GoalSeekingProblem/HeuristicLab.GoalSeekingProblem/3.4/Analyzers/BestSolutionAnalyzer.cs	(revision 14324)
@@ -32,5 +32,5 @@
 using HeuristicLab.Problems.DataAnalysis;
 
-namespace HeuristicLab.ProcessParameterOptimization {
+namespace HeuristicLab.GoalSeeking {
   [StorableClass]
   [Item("BestSolutionAnalyzer", "An analyzer which identifies the best solution from the SingleObjectiveProcessParameterOptimizationProblem")]
Index: /branches/HeuristicLab.GoalSeekingProblem/HeuristicLab.GoalSeekingProblem/3.4/GoalSeekingProblem.csproj
===================================================================
--- /branches/HeuristicLab.GoalSeekingProblem/HeuristicLab.GoalSeekingProblem/3.4/GoalSeekingProblem.csproj	(revision 14323)
+++ /branches/HeuristicLab.GoalSeekingProblem/HeuristicLab.GoalSeekingProblem/3.4/GoalSeekingProblem.csproj	(revision 14324)
@@ -9,6 +9,6 @@
     <OutputType>Library</OutputType>
     <AppDesignerFolder>Properties</AppDesignerFolder>
-    <RootNamespace>HeuristicLab.ProcessParameterOptimization</RootNamespace>
-    <AssemblyName>HeuristicLab.ProcessParameterOptimization-3.3</AssemblyName>
+    <RootNamespace>HeuristicLab.GoalSeekingProblem</RootNamespace>
+    <AssemblyName>HeuristicLab.GoalSeekingProblem-3.4</AssemblyName>
     <TargetFrameworkVersion>v4.5</TargetFrameworkVersion>
     <FileAlignment>512</FileAlignment>
Index: /branches/HeuristicLab.GoalSeekingProblem/HeuristicLab.GoalSeekingProblem/3.4/IGoalSeekingProblem.cs
===================================================================
--- /branches/HeuristicLab.GoalSeekingProblem/HeuristicLab.GoalSeekingProblem/3.4/IGoalSeekingProblem.cs	(revision 14323)
+++ /branches/HeuristicLab.GoalSeekingProblem/HeuristicLab.GoalSeekingProblem/3.4/IGoalSeekingProblem.cs	(revision 14324)
@@ -27,12 +27,10 @@
 using HeuristicLab.Problems.DataAnalysis;
 
-namespace HeuristicLab.ProcessParameterOptimization {
+namespace HeuristicLab.GoalSeeking {
   public interface IGoalSeekingProblem : IProblem {
     IRegressionProblemData ProblemData { get; set; }
-    double GetVariableValue(string variableName);
-    void SetVariableValue(string variableName, double variableValue);
 
     //rounding ? 
-    double[] GetEstimatedGoalValues(IEnumerable<double> parameters, bool round = false);
+    IEnumerable<double> GetEstimatedGoalValues(IEnumerable<double> parameterValues, bool round = false);
     int Row { get; set; }
 
@@ -44,7 +42,4 @@
 
     #region targets
-    IEnumerable<string> ActiveTargets { get; }
-    IEnumerable<string> Targets { get; }
-    ICheckedItemList<StringValue> TargetList { get; }
     double GetTargetGoal(string target);
     void SetTargetGoal(string target, double goal);
@@ -64,5 +59,4 @@
 
     #region parameters
-    IEnumerable<string> ActiveParameters { get; }
     ICheckedItemList<StringValue> ControllableParameters { get; }
     DoubleMatrix ControllableParameterBounds { get; }
Index: /branches/HeuristicLab.GoalSeekingProblem/HeuristicLab.GoalSeekingProblem/3.4/MultiObjectiveGoalSeekingProblem.cs
===================================================================
--- /branches/HeuristicLab.GoalSeekingProblem/HeuristicLab.GoalSeekingProblem/3.4/MultiObjectiveGoalSeekingProblem.cs	(revision 14323)
+++ /branches/HeuristicLab.GoalSeekingProblem/HeuristicLab.GoalSeekingProblem/3.4/MultiObjectiveGoalSeekingProblem.cs	(revision 14324)
@@ -34,6 +34,6 @@
 using HeuristicLab.Problems.DataAnalysis;
 
-namespace HeuristicLab.ProcessParameterOptimization {
-  [Item("Process parameter optimization problem (multi-objective)", "Represents a single objective optimization problem which uses configurable regression models to evaluate targets from a given dataset.")]
+namespace HeuristicLab.GoalSeeking {
+  [Item("Goal seeking problem (multi-objective)", "Represents a single objective optimization problem which uses configurable regression models to evaluate targets from a given dataset.")]
   [Creatable("Problems")]
   [StorableClass]
@@ -56,7 +56,4 @@
     public IValueParameter<IRegressionProblemData> ProblemDataParameter {
       get { return (IValueParameter<IRegressionProblemData>)Parameters[ProblemDataParameterName]; }
-    }
-    public IValueParameter<IDataset> ModifiableDatasetParameter {
-      get { return (IValueParameter<IDataset>)Parameters[ModifiableDatasetParameterName]; }
     }
     public IValueParameter<CheckedItemList<StringValue>> ControllableParametersParameter {
@@ -129,28 +126,23 @@
 
     #region targets
-    public IEnumerable<string> ActiveTargets {
-      get { return TargetList.CheckedItems.Select(x => x.Value.Value); }
-    }
-
-    public IEnumerable<string> Targets {
-      get { return TargetList.Select(x => x.Value); }
-    }
-
     public ICheckedItemList<StringValue> TargetList {
       get { return TargetsParameter.Value; }
       set { TargetsParameter.Value = (CheckedItemList<StringValue>)value; }
     }
+    // convenience method
+    private IEnumerable<string> ActiveTargets {
+      get { return TargetList.CheckedItems.Select(x => x.Value.Value); }
+    }
     #endregion
 
     #region parameters
-    public IEnumerable<string> ActiveParameters {
-      get { return ControllableParameters.CheckedItems.Select(x => x.Value.Value); }
-    }
-
     public ICheckedItemList<StringValue> ControllableParameters {
       get { return ControllableParametersParameter.Value; }
       set { ControllableParametersParameter.Value = (CheckedItemList<StringValue>)value; }
     }
-
+    // convenience method 
+    private IEnumerable<string> ActiveParameters {
+      get { return ControllableParameters.CheckedItems.Select(x => x.Value.Value); }
+    }
     public DoubleMatrix ControllableParameterBounds {
       get { return ControllableParameterBoundsParameter.Value; }
@@ -162,41 +154,14 @@
     #region IProcessParameterOptimizationProblem methods
     #region models
-    public double GetVariableValue(string variableName) {
-      return dataset.GetDoubleValue(variableName, 0);
-    }
-
-    public void SetVariableValue(string variableName, double variableValue) {
-      dataset.SetVariableValue(variableValue, variableName, 0); // will throw if the variable is not present in the dataset
-    }
-
-    public double[] GetEstimatedGoalValues(IEnumerable<double> parameters, bool round = false) {
+    public IEnumerable<double> GetEstimatedGoalValues(IEnumerable<double> parameterValues, bool round = false) {
       var ds = (ModifiableDataset)dataset.Clone();
-      var estimatedValues = new double[ActiveTargets.Count()];
-      var e1 = parameters.GetEnumerator();
-      var e2 = ActiveParameters.GetEnumerator();
-      while (e1.MoveNext() && e2.MoveNext())
-        ds.SetVariableValue(e1.Current, e2.Current, 0);
+      foreach (var parameter in ActiveParameters.Zip(parameterValues, (p, v) => new { Name = p, Value = v })) {
+        ds.SetVariableValue(parameter.Value, parameter.Name, 0);
+      }
       var rows = new[] { 0 }; // actually just one row
-      int i = 0;
-      var models = ModelCollection.ToList();
-      foreach (var target in TargetList.CheckedItems) {
-        var average = 0d;
-        var count = 0;
-        var targetName = target.Value.Value;
-        foreach (var model in models) {
-          if (targetName != model.TargetVariable)
-            continue;
-          average += model.GetEstimatedValues(ds, rows).Single();
-          count++;
-        }
-        var estimatedValue = average / count;
-        if (round) {
-          var accuracy = GetTargetStepSize(targetName);
-          estimatedValues[i] = RoundToNearestStepMultiple(estimatedValue, accuracy);
-        } else {
-          estimatedValues[i] = estimatedValue;
-        }
-        ++i;
-      }
+
+      var estimatedValues =
+        round ? ActiveTargets.Select(t => RoundToNearestStepMultiple(GetModels(t).Average(m => m.GetEstimatedValues(ds, rows).Single()), GetTargetStepSize(t)))
+              : ActiveTargets.Select(t => GetModels(t).Average(m => m.GetEstimatedValues(ds, rows).Single()));
       return estimatedValues;
     }
@@ -245,5 +210,5 @@
 
     public double GetTargetGoal(string target) {
-      if (!Targets.Contains(target))
+      if (!IsValidTarget(target))
         throw new ArgumentException(string.Format("The target variable name \"{0}\" does not exist in the dataset.", target));
       int i = TargetGoals.RowNames.TakeWhile(x => x != target).Count();
@@ -252,5 +217,5 @@
 
     public void SetTargetGoal(string target, double goal) {
-      if (!Targets.Contains(target))
+      if (!IsValidTarget(target))
         throw new ArgumentException(string.Format("The target variable name \"{0}\" does not exist in the dataset.", target));
       int i = TargetGoals.RowNames.TakeWhile(x => x != target).Count();
@@ -260,5 +225,5 @@
 
     public double GetTargetWeight(string target) {
-      if (!Targets.Contains(target))
+      if (!IsValidTarget(target))
         throw new ArgumentException(string.Format("The target variable name \"{0}\" does not exist in the dataset.", target));
       int i = TargetGoals.RowNames.TakeWhile(x => x != target).Count();
@@ -267,5 +232,5 @@
 
     public void SetTargetWeight(string target, double weight) {
-      if (!Targets.Contains(target))
+      if (!IsValidTarget(target))
         throw new ArgumentException(string.Format("The target variable name \"{0}\" does not exist in the dataset.", target));
       int i = TargetGoals.RowNames.TakeWhile(x => x != target).Count();
@@ -275,5 +240,5 @@
 
     public double GetTargetVariance(string target) {
-      if (!Targets.Contains(target))
+      if (!IsValidTarget(target))
         throw new ArgumentException(string.Format("The target variable name \"{0}\" does not exist in the dataset.", target));
       int i = TargetGoals.RowNames.TakeWhile(x => x != target).Count();
@@ -282,5 +247,5 @@
 
     public void SetTargetVariance(string target, double variance) {
-      if (!Targets.Contains(target))
+      if (!IsValidTarget(target))
         throw new ArgumentException(string.Format("The target variable name \"{0}\" does not exist in the dataset.", target));
       int i = TargetGoals.RowNames.TakeWhile(x => x != target).Count();
@@ -290,5 +255,5 @@
 
     public double GetTargetStepSize(string target) {
-      if (!Targets.Contains(target))
+      if (!IsValidTarget(target))
         throw new ArgumentException(string.Format("The target variable name \"{0}\" does not exist in the dataset.", target));
       int i = TargetGoals.RowNames.TakeWhile(x => x != target).Count();
@@ -297,5 +262,5 @@
 
     public void SetTargetStepSize(string target, double stepSize) {
-      if (!Targets.Contains(target))
+      if (!IsValidTarget(target))
         throw new ArgumentException(string.Format("The target variable name \"{0}\" does not exist in the dataset.", target));
       int i = TargetGoals.RowNames.TakeWhile(x => x != target).Count();
@@ -313,51 +278,4 @@
 
     #region process parameters
-    public void SetParameterBounds(string parameterName, double min, double max, double step) {
-      int i = ControllableParameterBounds.RowNames.TakeWhile(x => x != parameterName).Count();
-      if (i < ControllableParameterBounds.Rows) {
-        ControllableParameterBounds[i, 0] = min;
-        ControllableParameterBounds[i, 1] = max;
-        ControllableParameterBounds[i, 2] = step;
-        UpdateEncoding();
-        OnParametersChanged(this, EventArgs.Empty);
-      } else {
-        throw new ArgumentException(string.Format("SetParameterBounds: Invalid parameter name {0}", parameterName));
-      }
-
-    }
-
-    public double GetParameterStepSize(string parameter) {
-      int i = ControllableParameterBounds.RowNames.TakeWhile(x => x != parameter).Count();
-      if (i < ControllableParameterBounds.Rows)
-        return ControllableParameterBounds[i, 2];
-      throw new ArgumentException(string.Format("GetParameterStepSize: Invalid parameter name {0}", parameter));
-    }
-
-    public void SetParameterStepSize(string parameter, double stepSize) {
-      int i = ControllableParameterBounds.RowNames.TakeWhile(x => x != parameter).Count();
-      if (i < ControllableParameterBounds.Rows) {
-        ControllableParameterBounds[i, 2] = stepSize;
-        OnParametersChanged(this, EventArgs.Empty);
-      } else {
-        throw new ArgumentException(string.Format("SetParameterStepSize: Invalid parameter name {0}", parameter));
-      }
-    }
-
-
-    public bool GetParameterActive(string parameter) {
-      var item = ControllableParameters.SingleOrDefault(x => x.Value == parameter);
-      if (item == null)
-        throw new ArgumentException(string.Format("GetParameterActive: Invalid target name {0}", parameter));
-      return ControllableParameters.ItemChecked(item);
-    }
-
-    public void SetParameterActive(string parameter, bool active) {
-      var item = ControllableParameters.SingleOrDefault(x => x.Value == parameter);
-      if (item == null)
-        throw new ArgumentException(string.Format("SetParameterActive: Invalid target name {0}", parameter));
-      ControllableParameters.SetItemCheckedState(item, active);
-      OnParametersChanged(this, EventArgs.Empty);
-    }
-
     /// <summary>
     /// Returns the parameter bounds (min and max) and the step size for the specified parameter
@@ -376,4 +294,50 @@
     }
 
+    public void SetParameterBounds(string parameterName, double min, double max, double step) {
+      int i = ControllableParameterBounds.RowNames.TakeWhile(x => x != parameterName).Count();
+      if (i < ControllableParameterBounds.Rows) {
+        ControllableParameterBounds[i, 0] = min;
+        ControllableParameterBounds[i, 1] = max;
+        ControllableParameterBounds[i, 2] = step;
+        UpdateEncoding();
+        OnParametersChanged(this, EventArgs.Empty);
+      } else {
+        throw new ArgumentException(string.Format("SetParameterBounds: Invalid parameter name {0}", parameterName));
+      }
+
+    }
+
+    public double GetParameterStepSize(string parameter) {
+      int i = ControllableParameterBounds.RowNames.TakeWhile(x => x != parameter).Count();
+      if (i < ControllableParameterBounds.Rows)
+        return ControllableParameterBounds[i, 2];
+      throw new ArgumentException(string.Format("GetParameterStepSize: Invalid parameter name {0}", parameter));
+    }
+
+    public void SetParameterStepSize(string parameter, double stepSize) {
+      int i = ControllableParameterBounds.RowNames.TakeWhile(x => x != parameter).Count();
+      if (i < ControllableParameterBounds.Rows) {
+        ControllableParameterBounds[i, 2] = stepSize;
+        OnParametersChanged(this, EventArgs.Empty);
+        return;
+      }
+      throw new ArgumentException(string.Format("SetParameterStepSize: Invalid parameter name {0}", parameter));
+    }
+
+    public bool GetParameterActive(string parameter) {
+      var item = ControllableParameters.SingleOrDefault(x => x.Value == parameter);
+      if (item == null)
+        throw new ArgumentException(string.Format("GetParameterActive: Invalid target name {0}", parameter));
+      return ControllableParameters.ItemChecked(item);
+    }
+
+    public void SetParameterActive(string parameter, bool active) {
+      var item = ControllableParameters.SingleOrDefault(x => x.Value == parameter);
+      if (item == null)
+        throw new ArgumentException(string.Format("SetParameterActive: Invalid target name {0}", parameter));
+      ControllableParameters.SetItemCheckedState(item, active);
+      OnParametersChanged(this, EventArgs.Empty);
+    }
+
     public void SetControllableParameters(IEnumerable<string> parameterNames) {
       ControllableParameters = new CheckedItemList<StringValue>();
@@ -410,5 +374,5 @@
     }
     #endregion // process parameters
-    #endregion // IProcessParameterOprimizationProblem methods
+    #endregion // IGoalSeekingProblem methods
 
     #region data members
@@ -431,6 +395,5 @@
     private MultiObjectiveGoalSeekingProblem(bool deserializing) : base(deserializing) { }
 
-    private MultiObjectiveGoalSeekingProblem(MultiObjectiveGoalSeekingProblem original, Cloner cloner)
-      : base(original, cloner) {
+    private MultiObjectiveGoalSeekingProblem(MultiObjectiveGoalSeekingProblem original, Cloner cloner) : base(original, cloner) {
       this.dataset = cloner.Clone(original.dataset);
       this.problemData = cloner.Clone(original.problemData);
@@ -512,17 +475,13 @@
         ++i;
       }
-      i = 0;
-      var qualities = new double[ActiveTargets.Count()];
       var estimatedValues = GetEstimatedGoalValues(vector, round: true);
-      // round target estimated values and calculate qualities
-      foreach (var target in ActiveTargets) {
-        var estimatedValue = estimatedValues[i];
-        var goal = GetTargetGoal(target);
-        var weight = GetTargetWeight(target);
-        var variance = GetTargetVariance(target);
-        qualities[i] = weight * Math.Pow(estimatedValue - goal, 2) / variance;
-        ++i;
-      }
-      return qualities;
+      var qualities = TargetList.CheckedItems.Zip(estimatedValues, (t, v) => new { Name = t.Value.Value, Index = t.Index, EstimatedValue = v })
+                                .Select(target => {
+                                  var goal = TargetGoals[target.Index, 0];
+                                  var weight = TargetGoals[target.Index, 1];
+                                  var variance = TargetGoals[target.Index, 2];
+                                  return weight * Math.Pow(target.EstimatedValue - goal, 2) / variance;
+                                });
+      return qualities.ToArray();
     }
 
@@ -561,5 +520,5 @@
           continue;
         var vector = individuals[i].RealVector();
-        var estimatedValues = GetEstimatedGoalValues(vector);
+        var estimatedValues = GetEstimatedGoalValues(vector).ToList();
         var rowValues = new double[columnNames.Count];
         rowValues[0] = qualitySum;
@@ -658,5 +617,9 @@
     private void UpdateControllableParameters() {
       if (ProblemData == null) return;
-      SetControllableParameters(ProblemData.Dataset.DoubleVariables);
+       if (ProblemData == null) return;
+      var variablesUsedForPrediction = ModelCollection.Any()
+        ? ModelCollection.SelectMany(x => x.VariablesUsedForPrediction).Distinct()
+        : ProblemData.Dataset.DoubleVariables;
+      SetControllableParameters(variablesUsedForPrediction);
     }
 
@@ -715,11 +678,14 @@
       }
     }
-    #endregion
-
-    #region util
+
+    private bool IsValidTarget(string target) {
+      return TargetList.Any(x => x.Value == target);
+    }
     private static double RoundToNearestStepMultiple(double value, double step) {
       return step * (long)Math.Round(value / step);
     }
-
+    private IEnumerable<IRegressionModel> GetModels(string target) {
+      return ModelCollection.Where(x => x.TargetVariable == target);
+    }
     private class DoubleEqualityComparer : IEqualityComparer<double> {
       public bool Equals(double x, double y) { return x.IsAlmost(y); }
Index: /branches/HeuristicLab.GoalSeekingProblem/HeuristicLab.GoalSeekingProblem/3.4/Plugin.cs
===================================================================
--- /branches/HeuristicLab.GoalSeekingProblem/HeuristicLab.GoalSeekingProblem/3.4/Plugin.cs	(revision 14323)
+++ /branches/HeuristicLab.GoalSeekingProblem/HeuristicLab.GoalSeekingProblem/3.4/Plugin.cs	(revision 14324)
@@ -22,7 +22,7 @@
 using HeuristicLab.PluginInfrastructure;
 
-namespace HeuristicLab.ProcessParameterOptimization {
-  [Plugin("HeuristicLab.ProcessParameterOptimization", "3.3.0.0")]
-  [PluginFile("HeuristicLab.ProcessParameterOptimization-3.3.dll", PluginFileType.Assembly)]
+namespace HeuristicLab.GoalSeekingProblem {
+  [Plugin("HeuristicLab.GoalSeekingProblem", "3.4.0.0")]
+  [PluginFile("HeuristicLab.GoalSeekingProblem-3.4.dll", PluginFileType.Assembly)]
   [PluginDependency("HeuristicLab.Collections", "3.3")]
   [PluginDependency("HeuristicLab.Common", "3.3")]
Index: /branches/HeuristicLab.GoalSeekingProblem/HeuristicLab.GoalSeekingProblem/3.4/Properties/AssemblyInfo.cs
===================================================================
--- /branches/HeuristicLab.GoalSeekingProblem/HeuristicLab.GoalSeekingProblem/3.4/Properties/AssemblyInfo.cs	(revision 14323)
+++ /branches/HeuristicLab.GoalSeekingProblem/HeuristicLab.GoalSeekingProblem/3.4/Properties/AssemblyInfo.cs	(revision 14324)
@@ -54,3 +54,3 @@
 // [assembly: AssemblyVersion("1.0.*")]
 [assembly: AssemblyVersion("3.3.0.0")]
-[assembly: AssemblyFileVersion("3.3.11.480")]
+[assembly: AssemblyFileVersion("3.3.11.14321")]
Index: /branches/HeuristicLab.GoalSeekingProblem/HeuristicLab.GoalSeekingProblem/3.4/SingleObjectiveGoalSeekingProblem.cs
===================================================================
--- /branches/HeuristicLab.GoalSeekingProblem/HeuristicLab.GoalSeekingProblem/3.4/SingleObjectiveGoalSeekingProblem.cs	(revision 14323)
+++ /branches/HeuristicLab.GoalSeekingProblem/HeuristicLab.GoalSeekingProblem/3.4/SingleObjectiveGoalSeekingProblem.cs	(revision 14324)
@@ -34,9 +34,10 @@
 using HeuristicLab.Problems.DataAnalysis;
 
-namespace HeuristicLab.ProcessParameterOptimization {
-  [Item("Process parameter optimization problem (single-objective)", "Represents a single objective optimization problem which uses configurable regression solutions to evaluate targets from a given dataset.")]
+namespace HeuristicLab.GoalSeeking {
+  [Item("Goal seeking problem (single-objective)", "Represents a single objective optimization problem which uses configurable regression solutions to evaluate targets from a given dataset.")]
   [Creatable("Problems")]
   [StorableClass]
   public sealed class SingleObjectiveGoalSeekingProblem : SingleObjectiveBasicProblem<RealVectorEncoding>, IGoalSeekingProblem {
+    #region parameter names
     private const string ModifiableDatasetParameterName = "Dataset";
     private const string ProblemDataParameterName = "ProblemData";
@@ -50,4 +51,5 @@
     private const string AllowedRangesParameterName = "AllowedRanges";
     private const string QualitySumCutoffParameterName = "QualitySumCutoff";
+    #endregion
 
     #region parameters
@@ -61,7 +63,4 @@
       get { return (IValueParameter<IRegressionProblemData>)Parameters[ProblemDataParameterName]; }
     }
-    public IValueParameter<IDataset> ModifiableDatasetParameter {
-      get { return (IValueParameter<IDataset>)Parameters[ModifiableDatasetParameterName]; }
-    }
     public IValueParameter<CheckedItemList<StringValue>> ControllableParametersParameter {
       get { return (IValueParameter<CheckedItemList<StringValue>>)Parameters[ControllableParametersParameterName]; }
@@ -91,13 +90,4 @@
       get { return TargetGoalsParameter.Value; }
       set { TargetGoalsParameter.Value = value; }
-    }
-    // the AllowedRanges property is only used by the pareto folding analyzer
-    public RealVector AllowedRanges {
-      get { return AllowedRangesParameter.Value; }
-      set { AllowedRangesParameter.Value = value; }
-    }
-    public double QualitySumCutoff {
-      get { return QualitySumCutoffParameter.Value.Value; }
-      set { QualitySumCutoffParameter.Value.Value = value; }
     }
     #endregion
@@ -138,28 +128,21 @@
 
     #region targets
-    public IEnumerable<string> ActiveTargets {
-      get { return TargetList.CheckedItems.Select(x => x.Value.Value); }
-    }
-
-    public IEnumerable<string> Targets {
-      get { return TargetList.Select(x => x.Value); }
-    }
-
     public ICheckedItemList<StringValue> TargetList {
       get { return TargetsParameter.Value; }
       set { TargetsParameter.Value = (CheckedItemList<StringValue>)value; }
     }
+    private IEnumerable<string> ActiveTargets {
+      get { return TargetList.CheckedItems.Select(x => x.Value.Value); }
+    }
     #endregion
 
     #region parameters
-    public IEnumerable<string> ActiveParameters {
+    private IEnumerable<string> ActiveParameters {
       get { return ControllableParameters.CheckedItems.Select(x => x.Value.Value); }
     }
-
     public ICheckedItemList<StringValue> ControllableParameters {
       get { return ControllableParametersParameter.Value; }
       set { ControllableParametersParameter.Value = (CheckedItemList<StringValue>)value; }
     }
-
     public DoubleMatrix ControllableParameterBounds {
       get { return ControllableParameterBoundsParameter.Value; }
@@ -171,42 +154,15 @@
     #region IProcessParameterOptimizationProblem methods
     #region solutions
-    public double GetVariableValue(string variableName) {
-      return dataset.GetDoubleValue(variableName, 0);
-    }
-
-    public void SetVariableValue(string variableName, double variableValue) {
-      dataset.SetVariableValue(variableValue, variableName, 0); // will throw if the variable is not present in the dataset
-    }
-
-    public double[] GetEstimatedGoalValues(IEnumerable<double> parameters, bool round = false) {
+    public IEnumerable<double> GetEstimatedGoalValues(IEnumerable<double> parameterValues, bool round = false) {
       var ds = (ModifiableDataset)dataset.Clone();
-      var estimatedValues = new double[ActiveTargets.Count()];
-      var e1 = parameters.GetEnumerator();
-      var e2 = ActiveParameters.GetEnumerator();
-      while (e1.MoveNext() && e2.MoveNext())
-        ds.SetVariableValue(e1.Current, e2.Current, 0);
+      foreach (var parameter in ActiveParameters.Zip(parameterValues, (p, v) => new { Name = p, Value = v })) {
+        ds.SetVariableValue(parameter.Value, parameter.Name, 0);
+      }
       var rows = new[] { 0 }; // actually just one row
-      int i = 0;
-      var models = ModelCollection.ToList();
-      foreach (var target in TargetList.CheckedItems) {
-        var average = 0d;
-        var count = 0;
-        var targetName = target.Value.Value;
-
-        foreach (var model in models) {
-          if (targetName != model.TargetVariable)
-            continue;
-          average += model.GetEstimatedValues(ds, rows).Single();
-          count++;
-        }
-        var estimatedValue = average / count;
-        if (round) {
-          var accuracy = GetTargetStepSize(targetName);
-          estimatedValues[i] = RoundToNearestStepMultiple(estimatedValue, accuracy);
-        } else {
-          estimatedValues[i] = estimatedValue;
-        }
-        ++i;
-      }
+
+      var estimatedValues =
+        round ? ActiveTargets.Select(t => RoundToNearestStepMultiple(GetModels(t).Average(m => m.GetEstimatedValues(ds, rows).Single()), GetTargetStepSize(t)))
+              : ActiveTargets.Select(t => GetModels(t).Average(m => m.GetEstimatedValues(ds, rows).Single()));
+
       return estimatedValues;
     }
@@ -255,5 +211,5 @@
 
     public double GetTargetGoal(string target) {
-      if (!Targets.Contains(target))
+      if (!IsValidTarget(target))
         throw new ArgumentException(string.Format("The target variable name \"{0}\" does not exist in the dataset.", target));
       int i = TargetGoals.RowNames.TakeWhile(x => x != target).Count();
@@ -262,5 +218,5 @@
 
     public void SetTargetGoal(string target, double goal) {
-      if (!Targets.Contains(target))
+      if (!IsValidTarget(target))
         throw new ArgumentException(string.Format("The target variable name \"{0}\" does not exist in the dataset.", target));
       int i = TargetGoals.RowNames.TakeWhile(x => x != target).Count();
@@ -270,5 +226,5 @@
 
     public double GetTargetWeight(string target) {
-      if (!Targets.Contains(target))
+      if (!IsValidTarget(target))
         throw new ArgumentException(string.Format("The target variable name \"{0}\" does not exist in the dataset.", target));
       int i = TargetGoals.RowNames.TakeWhile(x => x != target).Count();
@@ -277,5 +233,5 @@
 
     public void SetTargetWeight(string target, double weight) {
-      if (!Targets.Contains(target))
+      if (!IsValidTarget(target))
         throw new ArgumentException(string.Format("The target variable name \"{0}\" does not exist in the dataset.", target));
       int i = TargetGoals.RowNames.TakeWhile(x => x != target).Count();
@@ -285,5 +241,5 @@
 
     public double GetTargetVariance(string target) {
-      if (!Targets.Contains(target))
+      if (!IsValidTarget(target))
         throw new ArgumentException(string.Format("The target variable name \"{0}\" does not exist in the dataset.", target));
       int i = TargetGoals.RowNames.TakeWhile(x => x != target).Count();
@@ -292,5 +248,5 @@
 
     public void SetTargetVariance(string target, double variance) {
-      if (!Targets.Contains(target))
+      if (!IsValidTarget(target))
         throw new ArgumentException(string.Format("The target variable name \"{0}\" does not exist in the dataset.", target));
       int i = TargetGoals.RowNames.TakeWhile(x => x != target).Count();
@@ -300,5 +256,5 @@
 
     public double GetTargetStepSize(string target) {
-      if (!Targets.Contains(target))
+      if (!IsValidTarget(target))
         throw new ArgumentException(string.Format("The target variable name \"{0}\" does not exist in the dataset.", target));
       int i = TargetGoals.RowNames.TakeWhile(x => x != target).Count();
@@ -307,5 +263,5 @@
 
     public void SetTargetStepSize(string target, double stepSize) {
-      if (!Targets.Contains(target))
+      if (!IsValidTarget(target))
         throw new ArgumentException(string.Format("The target variable name \"{0}\" does not exist in the dataset.", target));
       int i = TargetGoals.RowNames.TakeWhile(x => x != target).Count();
@@ -323,49 +279,4 @@
 
     #region process parameters
-    public void SetParameterBounds(string parameterName, double min, double max, double step) {
-      int i = ControllableParameterBounds.RowNames.TakeWhile(x => x != parameterName).Count();
-      if (i < ControllableParameterBounds.Rows) {
-        ControllableParameterBounds[i, 0] = min;
-        ControllableParameterBounds[i, 1] = max;
-        ControllableParameterBounds[i, 2] = step;
-        UpdateEncoding();
-        OnParametersChanged(this, EventArgs.Empty);
-      } else {
-        throw new ArgumentException(string.Format("SetParameterBounds: Invalid parameter name {0}", parameterName));
-      }
-    }
-
-    public double GetParameterStepSize(string parameter) {
-      int i = ControllableParameterBounds.RowNames.TakeWhile(x => x != parameter).Count();
-      if (i < ControllableParameterBounds.Rows)
-        return ControllableParameterBounds[i, 2];
-      throw new ArgumentException(string.Format("GetParameterStepSize: Invalid parameter name {0}", parameter));
-    }
-
-    public void SetParameterStepSize(string parameter, double stepSize) {
-      int i = ControllableParameterBounds.RowNames.TakeWhile(x => x != parameter).Count();
-      if (i < ControllableParameterBounds.Rows) {
-        ControllableParameterBounds[i, 2] = stepSize;
-        OnParametersChanged(this, EventArgs.Empty);
-      } else {
-        throw new ArgumentException(string.Format("SetParameterStepSize: Invalid parameter name {0}", parameter));
-      }
-    }
-
-    public bool GetParameterActive(string parameter) {
-      var item = ControllableParameters.SingleOrDefault(x => x.Value == parameter);
-      if (item == null)
-        throw new ArgumentException(string.Format("GetParameterActive: Invalid target name {0}", parameter));
-      return ControllableParameters.ItemChecked(item);
-    }
-
-    public void SetParameterActive(string parameter, bool active) {
-      var item = ControllableParameters.SingleOrDefault(x => x.Value == parameter);
-      if (item == null)
-        throw new ArgumentException(string.Format("SetParameterActive: Invalid target name {0}", parameter));
-      ControllableParameters.SetItemCheckedState(item, active);
-      OnParametersChanged(this, EventArgs.Empty);
-    }
-
     /// <summary>
     /// Returns the parameter bounds (min and max) and the step size for the specified parameter
@@ -384,4 +295,49 @@
     }
 
+    public void SetParameterBounds(string parameterName, double min, double max, double step) {
+      int i = ControllableParameterBounds.RowNames.TakeWhile(x => x != parameterName).Count();
+      if (i < ControllableParameterBounds.Rows) {
+        ControllableParameterBounds[i, 0] = min;
+        ControllableParameterBounds[i, 1] = max;
+        ControllableParameterBounds[i, 2] = step;
+        UpdateEncoding();
+        OnParametersChanged(this, EventArgs.Empty);
+      } else {
+        throw new ArgumentException(string.Format("SetParameterBounds: Invalid parameter name {0}", parameterName));
+      }
+    }
+
+    public double GetParameterStepSize(string parameter) {
+      int i = ControllableParameterBounds.RowNames.TakeWhile(x => x != parameter).Count();
+      if (i < ControllableParameterBounds.Rows)
+        return ControllableParameterBounds[i, 2];
+      throw new ArgumentException(string.Format("GetParameterStepSize: Invalid parameter name {0}", parameter));
+    }
+
+    public void SetParameterStepSize(string parameter, double stepSize) {
+      int i = ControllableParameterBounds.RowNames.TakeWhile(x => x != parameter).Count();
+      if (i < ControllableParameterBounds.Rows) {
+        ControllableParameterBounds[i, 2] = stepSize;
+        OnParametersChanged(this, EventArgs.Empty);
+        return;
+      }
+      throw new ArgumentException(string.Format("SetParameterStepSize: Invalid parameter name {0}", parameter));
+    }
+
+    public bool GetParameterActive(string parameter) {
+      var item = ControllableParameters.SingleOrDefault(x => x.Value == parameter);
+      if (item == null)
+        throw new ArgumentException(string.Format("GetParameterActive: Invalid target name {0}", parameter));
+      return ControllableParameters.ItemChecked(item);
+    }
+
+    public void SetParameterActive(string parameter, bool active) {
+      var item = ControllableParameters.SingleOrDefault(x => x.Value == parameter);
+      if (item == null)
+        throw new ArgumentException(string.Format("SetParameterActive: Invalid target name {0}", parameter));
+      ControllableParameters.SetItemCheckedState(item, active);
+      OnParametersChanged(this, EventArgs.Empty);
+    }
+
     public void SetControllableParameters(IEnumerable<string> parameterNames) {
       ControllableParameters = new CheckedItemList<StringValue>();
@@ -418,5 +374,5 @@
     }
     #endregion // process parameters
-    #endregion // IProcessParameterOprimizationProblem methods
+    #endregion // IGoalSeekingProblem methods
 
     #region data members
@@ -425,5 +381,5 @@
 
     public override bool Maximization {
-      get { return true; }
+      get { return false; }
     }
     #endregion
@@ -433,6 +389,5 @@
     private SingleObjectiveGoalSeekingProblem(bool deserializing) : base(deserializing) { }
 
-    private SingleObjectiveGoalSeekingProblem(SingleObjectiveGoalSeekingProblem original, Cloner cloner)
-      : base(original, cloner) {
+    private SingleObjectiveGoalSeekingProblem(SingleObjectiveGoalSeekingProblem original, Cloner cloner) : base(original, cloner) {
       this.dataset = cloner.Clone(original.dataset);
       this.problemData = cloner.Clone(original.problemData);
@@ -487,5 +442,4 @@
       var vector = individual.RealVector();
       vector.ElementNames = ActiveParameters;
-
       int i = 0;
       // round vector according to parameter step sizes
@@ -495,17 +449,13 @@
         ++i;
       }
-      i = 0;
-      var quality = 0d;
       var estimatedValues = GetEstimatedGoalValues(vector, round: true);
-      // round target estimated values and calculate qualities
-      foreach (var target in ActiveTargets) {
-        var estimatedValue = estimatedValues[i];
-        var goal = GetTargetGoal(target);
-        var weight = GetTargetWeight(target);
-        var variance = GetTargetVariance(target);
-        quality += weight * Math.Pow(estimatedValue - goal, 2) / variance;
-        ++i;
-      }
-      return quality / i;
+      var quality = TargetList.CheckedItems.Zip(estimatedValues, (t, v) => new { Name = t.Value.Value, Index = t.Index, EstimatedValue = v })
+                                .Average(target => {
+                                  var goal = TargetGoals[target.Index, 0];
+                                  var weight = TargetGoals[target.Index, 1];
+                                  var variance = TargetGoals[target.Index, 2];
+                                  return weight * Math.Pow(target.EstimatedValue - goal, 2) / variance;
+                                });
+      return quality;
     }
 
@@ -576,5 +526,8 @@
     private void UpdateControllableParameters() {
       if (ProblemData == null) return;
-      SetControllableParameters(ProblemData.Dataset.DoubleVariables);
+      var variablesUsedForPrediction = ModelCollection.Any()
+        ? ModelCollection.SelectMany(x => x.VariablesUsedForPrediction).Distinct()
+        : ProblemData.Dataset.DoubleVariables;
+      SetControllableParameters(variablesUsedForPrediction);
     }
 
@@ -628,10 +581,13 @@
       }
     }
-    #endregion
-
-    #region util
+    private bool IsValidTarget(string target) {
+      return TargetList.Any(x => x.Value == target);
+    }
     private static double RoundToNearestStepMultiple(double value, double step) {
       return step * (long)Math.Round(value / step);
     }
+    private IEnumerable<IRegressionModel> GetModels(string target) {
+      return ModelCollection.Where(x => x.TargetVariable == target);
+    }
     #endregion
   }
