Index: /branches/HeuristicLab.GoalSeekingProblem/HeuristicLab.GoalSeekingProblem.Views/3.4/GoalSeekingOptimizerView.Designer.cs
===================================================================
--- /branches/HeuristicLab.GoalSeekingProblem/HeuristicLab.GoalSeekingProblem.Views/3.4/GoalSeekingOptimizerView.Designer.cs	(revision 14380)
+++ /branches/HeuristicLab.GoalSeekingProblem/HeuristicLab.GoalSeekingProblem.Views/3.4/GoalSeekingOptimizerView.Designer.cs	(revision 14380)
@@ -0,0 +1,249 @@
+﻿namespace HeuristicLab.GoalSeeking {
+  partial class GoalSeekingOptimizerView {
+    /// <summary> 
+    /// Required designer variable.
+    /// </summary>
+    private System.ComponentModel.IContainer components = null;
+
+    /// <summary> 
+    /// Clean up any resources being used.
+    /// </summary>
+    /// <param name="disposing">true if managed resources should be disposed; otherwise, false.</param>
+    protected override void Dispose(bool disposing) {
+      if (disposing && (components != null)) {
+        components.Dispose();
+      }
+      base.Dispose(disposing);
+    }
+
+    #region Component Designer generated code
+
+    /// <summary> 
+    /// Required method for Designer support - do not modify 
+    /// the contents of this method with the code editor.
+    /// </summary>
+    private void InitializeComponent() {
+      this.tabControl = new System.Windows.Forms.TabControl();
+      this.problemTab = new System.Windows.Forms.TabPage();
+      this.problemViewHost = new HeuristicLab.MainForm.WindowsForms.ViewHost();
+      this.algorithmTab = new System.Windows.Forms.TabPage();
+      this.algorithmViewHost = new HeuristicLab.MainForm.WindowsForms.ViewHost();
+      this.dataTab = new System.Windows.Forms.TabPage();
+      this.dataViewHost = new HeuristicLab.MainForm.WindowsForms.ViewHost();
+      this.resultsTab = new System.Windows.Forms.TabPage();
+      this.resultsViewHost = new HeuristicLab.MainForm.WindowsForms.ViewHost();
+      ((System.ComponentModel.ISupportInitialize)(this.errorProvider)).BeginInit();
+      this.tabControl.SuspendLayout();
+      this.problemTab.SuspendLayout();
+      this.algorithmTab.SuspendLayout();
+      this.dataTab.SuspendLayout();
+      this.resultsTab.SuspendLayout();
+      this.SuspendLayout();
+      // 
+      // startButton
+      // 
+      this.startButton.Location = new System.Drawing.Point(6, 636);
+      this.toolTip.SetToolTip(this.startButton, "Start/Resume Optimizer");
+      // 
+      // executionTimeTextBox
+      // 
+      this.executionTimeTextBox.Location = new System.Drawing.Point(936, 640);
+      // 
+      // executionTimeLabel
+      // 
+      this.executionTimeLabel.Location = new System.Drawing.Point(847, 643);
+      // 
+      // pauseButton
+      // 
+      this.pauseButton.Location = new System.Drawing.Point(36, 636);
+      this.toolTip.SetToolTip(this.pauseButton, "Pause Optimizer");
+      // 
+      // stopButton
+      // 
+      this.stopButton.Location = new System.Drawing.Point(66, 636);
+      this.toolTip.SetToolTip(this.stopButton, "Stop Optimizer");
+      // 
+      // resetButton
+      // 
+      this.resetButton.Location = new System.Drawing.Point(96, 636);
+      this.toolTip.SetToolTip(this.resetButton, "Reset Optimizer");
+      // 
+      // nameTextBox
+      // 
+      this.errorProvider.SetIconAlignment(this.nameTextBox, System.Windows.Forms.ErrorIconAlignment.MiddleLeft);
+      this.errorProvider.SetIconPadding(this.nameTextBox, 2);
+      this.nameTextBox.Size = new System.Drawing.Size(1008, 20);
+      // 
+      // infoLabel
+      // 
+      this.infoLabel.Location = new System.Drawing.Point(995, 3);
+      // 
+      // tabControl
+      // 
+      this.tabControl.AllowDrop = true;
+      this.tabControl.Anchor = ((System.Windows.Forms.AnchorStyles)((((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom) 
+            | System.Windows.Forms.AnchorStyles.Left) 
+            | System.Windows.Forms.AnchorStyles.Right)));
+      this.tabControl.Controls.Add(this.problemTab);
+      this.tabControl.Controls.Add(this.algorithmTab);
+      this.tabControl.Controls.Add(this.dataTab);
+      this.tabControl.Controls.Add(this.resultsTab);
+      this.tabControl.Location = new System.Drawing.Point(3, 26);
+      this.tabControl.Name = "tabControl";
+      this.tabControl.SelectedIndex = 0;
+      this.tabControl.Size = new System.Drawing.Size(1070, 604);
+      this.tabControl.TabIndex = 0;
+      // 
+      // problemTab
+      // 
+      this.problemTab.AllowDrop = true;
+      this.problemTab.Controls.Add(this.problemViewHost);
+      this.problemTab.Location = new System.Drawing.Point(4, 22);
+      this.problemTab.Name = "problemTab";
+      this.problemTab.Padding = new System.Windows.Forms.Padding(3);
+      this.problemTab.Size = new System.Drawing.Size(527, 259);
+      this.problemTab.TabIndex = 0;
+      this.problemTab.Text = "Problem";
+      this.problemTab.UseVisualStyleBackColor = true;
+      this.problemTab.DragDrop += new System.Windows.Forms.DragEventHandler(this.problemTab_DragDrop);
+      this.problemTab.DragEnter += new System.Windows.Forms.DragEventHandler(this.problemTab_DragEnter);
+      // 
+      // problemViewHost
+      // 
+      this.problemViewHost.AllowDrop = true;
+      this.problemViewHost.BackColor = System.Drawing.Color.Transparent;
+      this.problemViewHost.Caption = "View";
+      this.problemViewHost.Content = null;
+      this.problemViewHost.Dock = System.Windows.Forms.DockStyle.Fill;
+      this.problemViewHost.Enabled = false;
+      this.problemViewHost.Location = new System.Drawing.Point(3, 3);
+      this.problemViewHost.Name = "problemViewHost";
+      this.problemViewHost.ReadOnly = false;
+      this.problemViewHost.Size = new System.Drawing.Size(521, 253);
+      this.problemViewHost.TabIndex = 0;
+      this.problemViewHost.ViewsLabelVisible = true;
+      this.problemViewHost.ViewType = null;
+      // 
+      // algorithmTab
+      // 
+      this.algorithmTab.AllowDrop = true;
+      this.algorithmTab.Controls.Add(this.algorithmViewHost);
+      this.algorithmTab.Location = new System.Drawing.Point(4, 22);
+      this.algorithmTab.Name = "algorithmTab";
+      this.algorithmTab.Padding = new System.Windows.Forms.Padding(3);
+      this.algorithmTab.Size = new System.Drawing.Size(950, 554);
+      this.algorithmTab.TabIndex = 1;
+      this.algorithmTab.Text = "Algorithm";
+      this.algorithmTab.UseVisualStyleBackColor = true;
+      this.algorithmTab.DragDrop += new System.Windows.Forms.DragEventHandler(this.algorithmTab_DragDrop);
+      this.algorithmTab.DragEnter += new System.Windows.Forms.DragEventHandler(this.algorithmTab_DragEnter);
+      // 
+      // algorithmViewHost
+      // 
+      this.algorithmViewHost.Caption = "View";
+      this.algorithmViewHost.Content = null;
+      this.algorithmViewHost.Dock = System.Windows.Forms.DockStyle.Fill;
+      this.algorithmViewHost.Enabled = false;
+      this.algorithmViewHost.Location = new System.Drawing.Point(3, 3);
+      this.algorithmViewHost.Name = "algorithmViewHost";
+      this.algorithmViewHost.ReadOnly = false;
+      this.algorithmViewHost.Size = new System.Drawing.Size(944, 548);
+      this.algorithmViewHost.TabIndex = 0;
+      this.algorithmViewHost.ViewsLabelVisible = true;
+      this.algorithmViewHost.ViewType = null;
+      // 
+      // dataTab
+      // 
+      this.dataTab.AllowDrop = true;
+      this.dataTab.Controls.Add(this.dataViewHost);
+      this.dataTab.Location = new System.Drawing.Point(4, 22);
+      this.dataTab.Name = "dataTab";
+      this.dataTab.Padding = new System.Windows.Forms.Padding(3);
+      this.dataTab.Size = new System.Drawing.Size(1062, 578);
+      this.dataTab.TabIndex = 2;
+      this.dataTab.Text = "Data";
+      this.dataTab.UseVisualStyleBackColor = true;
+      this.dataTab.DragDrop += new System.Windows.Forms.DragEventHandler(this.dataTab_DragDrop);
+      this.dataTab.DragEnter += new System.Windows.Forms.DragEventHandler(this.dataTab_DragEnter);
+      // 
+      // dataViewHost
+      // 
+      this.dataViewHost.AllowDrop = true;
+      this.dataViewHost.Caption = "View";
+      this.dataViewHost.Content = null;
+      this.dataViewHost.Dock = System.Windows.Forms.DockStyle.Fill;
+      this.dataViewHost.Enabled = false;
+      this.dataViewHost.Location = new System.Drawing.Point(3, 3);
+      this.dataViewHost.Name = "dataViewHost";
+      this.dataViewHost.ReadOnly = false;
+      this.dataViewHost.Size = new System.Drawing.Size(1056, 572);
+      this.dataViewHost.TabIndex = 0;
+      this.dataViewHost.ViewsLabelVisible = true;
+      this.dataViewHost.ViewType = null;
+      // 
+      // resultsTab
+      // 
+      this.resultsTab.Controls.Add(this.resultsViewHost);
+      this.resultsTab.Location = new System.Drawing.Point(4, 22);
+      this.resultsTab.Name = "resultsTab";
+      this.resultsTab.Size = new System.Drawing.Size(950, 554);
+      this.resultsTab.TabIndex = 3;
+      this.resultsTab.Text = "Results";
+      this.resultsTab.UseVisualStyleBackColor = true;
+      // 
+      // resultsViewHost
+      // 
+      this.resultsViewHost.Caption = "View";
+      this.resultsViewHost.Content = null;
+      this.resultsViewHost.Dock = System.Windows.Forms.DockStyle.Fill;
+      this.resultsViewHost.Enabled = false;
+      this.resultsViewHost.Location = new System.Drawing.Point(0, 0);
+      this.resultsViewHost.Name = "resultsViewHost";
+      this.resultsViewHost.ReadOnly = false;
+      this.resultsViewHost.Size = new System.Drawing.Size(950, 554);
+      this.resultsViewHost.TabIndex = 0;
+      this.resultsViewHost.ViewsLabelVisible = true;
+      this.resultsViewHost.ViewType = null;
+      // 
+      // GoalSeekingOptimizerView
+      // 
+      this.AllowDrop = true;
+      this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F);
+      this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
+      this.Controls.Add(this.tabControl);
+      this.Name = "GoalSeekingOptimizerView";
+      this.Size = new System.Drawing.Size(1076, 663);
+      this.Controls.SetChildIndex(this.tabControl, 0);
+      this.Controls.SetChildIndex(this.nameLabel, 0);
+      this.Controls.SetChildIndex(this.nameTextBox, 0);
+      this.Controls.SetChildIndex(this.infoLabel, 0);
+      this.Controls.SetChildIndex(this.resetButton, 0);
+      this.Controls.SetChildIndex(this.stopButton, 0);
+      this.Controls.SetChildIndex(this.pauseButton, 0);
+      this.Controls.SetChildIndex(this.executionTimeLabel, 0);
+      this.Controls.SetChildIndex(this.executionTimeTextBox, 0);
+      this.Controls.SetChildIndex(this.startButton, 0);
+      ((System.ComponentModel.ISupportInitialize)(this.errorProvider)).EndInit();
+      this.tabControl.ResumeLayout(false);
+      this.problemTab.ResumeLayout(false);
+      this.algorithmTab.ResumeLayout(false);
+      this.dataTab.ResumeLayout(false);
+      this.resultsTab.ResumeLayout(false);
+      this.ResumeLayout(false);
+      this.PerformLayout();
+
+    }
+
+    #endregion
+
+    private System.Windows.Forms.TabControl tabControl;
+    private System.Windows.Forms.TabPage problemTab;
+    private System.Windows.Forms.TabPage algorithmTab;
+    private System.Windows.Forms.TabPage dataTab;
+    private System.Windows.Forms.TabPage resultsTab;
+    private MainForm.WindowsForms.ViewHost problemViewHost;
+    private MainForm.WindowsForms.ViewHost algorithmViewHost;
+    private MainForm.WindowsForms.ViewHost dataViewHost;
+    private MainForm.WindowsForms.ViewHost resultsViewHost;
+  }
+}
Index: /branches/HeuristicLab.GoalSeekingProblem/HeuristicLab.GoalSeekingProblem.Views/3.4/GoalSeekingOptimizerView.cs
===================================================================
--- /branches/HeuristicLab.GoalSeekingProblem/HeuristicLab.GoalSeekingProblem.Views/3.4/GoalSeekingOptimizerView.cs	(revision 14380)
+++ /branches/HeuristicLab.GoalSeekingProblem/HeuristicLab.GoalSeekingProblem.Views/3.4/GoalSeekingOptimizerView.cs	(revision 14380)
@@ -0,0 +1,139 @@
+﻿#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.Windows.Forms;
+using HeuristicLab.MainForm;
+using HeuristicLab.Optimization;
+using HeuristicLab.Optimization.Views;
+using HeuristicLab.Problems.DataAnalysis;
+
+namespace HeuristicLab.GoalSeeking {
+  [View("GoalSeekingOptimizer View", "")]
+  [Content(typeof(GoalSeekingOptimizer), true)]
+  public partial class GoalSeekingOptimizerView : IOptimizerView {
+    public GoalSeekingOptimizerView() {
+      InitializeComponent();
+      Content = new GoalSeekingOptimizer();
+    }
+
+    public new GoalSeekingOptimizer Content {
+      get { return (GoalSeekingOptimizer)base.Content; }
+      set { base.Content = value; }
+    }
+
+    protected override void OnContentChanged() {
+      base.OnContentChanged();
+      if (Content == null)
+        return;
+
+      if (Content.Optimizer != null)
+        algorithmViewHost.Content = Content.Optimizer;
+
+      if (Content.Problem != null)
+        problemViewHost.Content = Content.Problem;
+
+      if (Content.ProblemData != null)
+        dataViewHost.Content = Content.ProblemData;
+    }
+
+    protected override void RegisterContentEvents() {
+      base.RegisterContentEvents();
+      Content.AlgorithmChanged += (o, e) => { algorithmViewHost.Content = Content.Optimizer; };
+      Content.ProblemChanged += (o, e) => { problemViewHost.Content = Content.Problem; };
+      Content.ProblemDataChanged += (o, e) => { dataViewHost.Content = Content.ProblemData; };
+    }
+
+    protected override void DeregisterContentEvents() {
+      base.DeregisterContentEvents();
+    }
+
+    #region event handlers
+    private void problemTab_DragDrop(object sender, DragEventArgs e) {
+      if (e.Data.GetDataPresent(HeuristicLab.Common.Constants.DragDropDataFormat)) {
+        try {
+          Content.Problem = (IGoalSeekingProblem)e.Data.GetData(HeuristicLab.Common.Constants.DragDropDataFormat);
+          problemViewHost.Content = Content.Problem;
+        }
+        catch (Exception ex) {
+          MessageBox.Show(ex.Message, "Set problem", MessageBoxButtons.OK, MessageBoxIcon.Error);
+        }
+      }
+    }
+
+    private void problemTab_DragEnter(object sender, DragEventArgs e) {
+      e.Effect = DragDropEffects.None;
+      if (!e.Data.GetDataPresent(HeuristicLab.Common.Constants.DragDropDataFormat))
+        return;
+
+      var data = e.Data.GetData(HeuristicLab.Common.Constants.DragDropDataFormat);
+
+      if (data is IGoalSeekingProblem)
+        e.Effect = DragDropEffects.Copy;
+    }
+
+    private void algorithmTab_DragDrop(object sender, DragEventArgs e) {
+      if (e.Data.GetDataPresent(HeuristicLab.Common.Constants.DragDropDataFormat)) {
+        try {
+          Content.Optimizer = (IAlgorithm)e.Data.GetData(HeuristicLab.Common.Constants.DragDropDataFormat);
+          algorithmViewHost.Content = Content.Optimizer;
+        }
+        catch (Exception ex) {
+          MessageBox.Show(ex.Message, "Set algorithm", MessageBoxButtons.OK, MessageBoxIcon.Error);
+        }
+      }
+    }
+
+    private void algorithmTab_DragEnter(object sender, DragEventArgs e) {
+      e.Effect = DragDropEffects.None;
+      if (!e.Data.GetDataPresent(HeuristicLab.Common.Constants.DragDropDataFormat))
+        return;
+
+      var data = e.Data.GetData(HeuristicLab.Common.Constants.DragDropDataFormat);
+      if (data is IAlgorithm)
+        e.Effect = DragDropEffects.Copy;
+    }
+    #endregion
+
+    private void dataTab_DragDrop(object sender, DragEventArgs e) {
+      if (e.Data.GetDataPresent(HeuristicLab.Common.Constants.DragDropDataFormat)) {
+        try {
+          Content.ProblemData = (IRegressionProblemData)e.Data.GetData(HeuristicLab.Common.Constants.DragDropDataFormat);
+          dataViewHost.Content = Content.ProblemData;
+        }
+        catch (Exception ex) {
+          // provide some information to the user
+          MessageBox.Show(ex.Message, "Set problem data", MessageBoxButtons.OK, MessageBoxIcon.Error);
+        }
+      }
+    }
+
+    private void dataTab_DragEnter(object sender, DragEventArgs e) {
+      e.Effect = DragDropEffects.None;
+      if (!e.Data.GetDataPresent(HeuristicLab.Common.Constants.DragDropDataFormat))
+        return;
+
+      var data = e.Data.GetData(HeuristicLab.Common.Constants.DragDropDataFormat);
+      if (data is IRegressionProblemData)
+        e.Effect = DragDropEffects.Copy;
+    }
+  }
+}
Index: /branches/HeuristicLab.GoalSeekingProblem/HeuristicLab.GoalSeekingProblem.Views/3.4/GoalSeekingProblem.Views.csproj
===================================================================
--- /branches/HeuristicLab.GoalSeekingProblem/HeuristicLab.GoalSeekingProblem.Views/3.4/GoalSeekingProblem.Views.csproj	(revision 14379)
+++ /branches/HeuristicLab.GoalSeekingProblem/HeuristicLab.GoalSeekingProblem.Views/3.4/GoalSeekingProblem.Views.csproj	(revision 14380)
@@ -41,4 +41,9 @@
       <Private>False</Private>
     </Reference>
+    <Reference Include="HeuristicLab.Core.Views-3.3, Version=3.3.0.0, Culture=neutral, PublicKeyToken=ba48961d6f65dcec, processorArchitecture=MSIL">
+      <SpecificVersion>False</SpecificVersion>
+      <HintPath>..\..\..\..\trunk\sources\bin\HeuristicLab.Core.Views-3.3.dll</HintPath>
+      <Private>False</Private>
+    </Reference>
     <Reference Include="HeuristicLab.MainForm-3.3">
       <HintPath>..\..\..\..\trunk\sources\bin\HeuristicLab.MainForm-3.3.dll</HintPath>
@@ -49,6 +54,21 @@
       <Private>False</Private>
     </Reference>
+    <Reference Include="HeuristicLab.Optimization-3.3, Version=3.3.0.0, Culture=neutral, PublicKeyToken=ba48961d6f65dcec, processorArchitecture=MSIL">
+      <SpecificVersion>False</SpecificVersion>
+      <HintPath>..\..\..\..\trunk\sources\bin\HeuristicLab.Optimization-3.3.dll</HintPath>
+      <Private>False</Private>
+    </Reference>
+    <Reference Include="HeuristicLab.Optimization.Views-3.3, Version=3.3.0.0, Culture=neutral, PublicKeyToken=ba48961d6f65dcec, processorArchitecture=MSIL">
+      <SpecificVersion>False</SpecificVersion>
+      <HintPath>..\..\..\..\trunk\sources\bin\HeuristicLab.Optimization.Views-3.3.dll</HintPath>
+      <Private>False</Private>
+    </Reference>
     <Reference Include="HeuristicLab.PluginInfrastructure-3.3">
       <HintPath>..\..\..\..\trunk\sources\bin\HeuristicLab.PluginInfrastructure-3.3.dll</HintPath>
+      <Private>False</Private>
+    </Reference>
+    <Reference Include="HeuristicLab.Problems.DataAnalysis-3.4, Version=3.4.0.0, Culture=neutral, PublicKeyToken=ba48961d6f65dcec, processorArchitecture=MSIL">
+      <SpecificVersion>False</SpecificVersion>
+      <HintPath>..\..\..\..\trunk\sources\bin\HeuristicLab.Problems.DataAnalysis-3.4.dll</HintPath>
       <Private>False</Private>
     </Reference>
@@ -65,4 +85,10 @@
   </ItemGroup>
   <ItemGroup>
+    <Compile Include="GoalSeekingOptimizerView.cs">
+      <SubType>UserControl</SubType>
+    </Compile>
+    <Compile Include="GoalSeekingOptimizerView.Designer.cs">
+      <DependentUpon>GoalSeekingOptimizerView.cs</DependentUpon>
+    </Compile>
     <Compile Include="InputParameterView.cs">
       <SubType>UserControl</SubType>
Index: /branches/HeuristicLab.GoalSeekingProblem/HeuristicLab.GoalSeekingProblem/3.4/GoalSeekingOptimizer.cs
===================================================================
--- /branches/HeuristicLab.GoalSeekingProblem/HeuristicLab.GoalSeekingProblem/3.4/GoalSeekingOptimizer.cs	(revision 14380)
+++ /branches/HeuristicLab.GoalSeekingProblem/HeuristicLab.GoalSeekingProblem/3.4/GoalSeekingOptimizer.cs	(revision 14380)
@@ -0,0 +1,357 @@
+﻿#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 System.Threading;
+using HeuristicLab.Common;
+using HeuristicLab.Core;
+using HeuristicLab.Optimization;
+using HeuristicLab.Persistence.Default.CompositeSerializers.Storable;
+using HeuristicLab.Problems.DataAnalysis;
+
+namespace HeuristicLab.GoalSeeking {
+  [StorableClass]
+  [Item("GoalSeeking Optimizer", "A wrapper for the GoalSeekingProblem class to facilitate adding models and problem data.")]
+  [Creatable("Algorithms")]
+  public class GoalSeekingOptimizer : NamedItem, IOptimizer, IStorableContent {
+    [Storable]
+    private IGoalSeekingProblem problem;
+    public IGoalSeekingProblem Problem {
+      get { return problem; }
+      set {
+        if (value == null || value == problem)
+          return;
+
+        problem = value;
+        // the problem takes precedence over the algorithm. if the algorithm is unsuitable we remove it.
+        if (optimizer != null && !optimizer.ProblemType.IsInstanceOfType(problem)) {
+          optimizer = null;
+          OnAlgorithmChanged();
+        }
+        if (optimizer != null)
+          optimizer.Problem = problem;
+      }
+    }
+
+    [Storable]
+    private IAlgorithm optimizer;
+    public IAlgorithm Optimizer {
+      get { return optimizer; }
+      set {
+        if (value == null || value == optimizer)
+          return;
+
+        // make sure the algorithm is suitable for the problem.
+        if (problem != null && !value.ProblemType.IsInstanceOfType(problem))
+          throw new InvalidOperationException("The algorithm is incompatible with the problem.");
+
+        optimizer = value;
+        optimizer.Problem = problem;
+        RegisterOptimizerEvents();
+        OnAlgorithmChanged();
+      }
+    }
+
+    [Storable]
+    private IRegressionProblemData problemData;
+    public IRegressionProblemData ProblemData {
+      get { return problemData; }
+      set {
+        if (value == null || value == problemData)
+          return;
+
+        if (problem == null)
+          throw new InvalidOperationException("Cannot set problem data. Please configure a problem first.");
+
+        problemData = value;
+        problem.Configure(problemData, problemData.TrainingIndices.First());
+        OnProblemDataChanged();
+      }
+    }
+
+    public GoalSeekingOptimizer() {
+      Name = "Goal Seeking Optimizer";
+    }
+
+    [StorableConstructor]
+    protected GoalSeekingOptimizer(bool deserializing) : base(deserializing) { }
+
+
+    [StorableHook(HookType.AfterDeserialization)]
+    private void AfterDeserialization() {
+      if (optimizer != null)
+        RegisterOptimizerEvents();
+    }
+
+    protected GoalSeekingOptimizer(GoalSeekingOptimizer original, Cloner cloner) : base(original, cloner) {
+      this.Optimizer = (IAlgorithm)original.Optimizer.Clone(cloner);
+      this.Problem = (IGoalSeekingProblem)original.Problem.Clone(cloner);
+      this.ProblemData = (IRegressionProblemData)original.ProblemData.Clone(cloner);
+    }
+
+    public override IDeepCloneable Clone(Cloner cloner) {
+      return new GoalSeekingOptimizer(this, cloner);
+    }
+
+    public EventHandler ProblemChanged;
+    private void OnProblemChanged() {
+      var changed = ProblemChanged;
+      if (changed != null)
+        changed(this, EventArgs.Empty);
+    }
+
+    public EventHandler AlgorithmChanged;
+    private void OnAlgorithmChanged() {
+      var changed = AlgorithmChanged;
+      if (changed != null)
+        changed(this, EventArgs.Empty);
+    }
+
+    public EventHandler ProblemDataChanged;
+    private void OnProblemDataChanged() {
+      var changed = ProblemDataChanged;
+      if (changed != null)
+        changed(this, EventArgs.Empty);
+    }
+
+    private int calculatedRows;
+    private readonly ManualResetEvent mutex = new ManualResetEvent(false);
+    public void Start() {
+      if ((ExecutionState != ExecutionState.Prepared) && (ExecutionState != ExecutionState.Paused))
+        throw new InvalidOperationException(string.Format("Start not allowed in execution state \"{0}\".", ExecutionState));
+      if (optimizer == null) return;
+
+      Prepare(clearRuns: true);
+
+      calculatedRows = 0;
+
+      var row = problemData.TrainingIndices.Skip(calculatedRows).First();
+      problem.Configure(problemData, row);
+      optimizer.Prepare();
+      optimizer.Start();
+    }
+
+    public void Pause() {
+      if (ExecutionState != ExecutionState.Started)
+        throw new InvalidOperationException(string.Format("Pause not allowed in execution state \"{0}\".", ExecutionState));
+      if (optimizer == null) return;
+      if (optimizer.ExecutionState != ExecutionState.Started) return;
+      // a race-condition may occur when the algorithm has changed the state by itself in the meantime
+      try { optimizer.Pause(); }
+      catch (InvalidOperationException) { }
+    }
+
+    public void Stop() {
+      if ((ExecutionState != ExecutionState.Started) && (ExecutionState != ExecutionState.Paused))
+        throw new InvalidOperationException(string.Format("Stop not allowed in execution state \"{0}\".", ExecutionState));
+      if (optimizer == null) return;
+      if (optimizer.ExecutionState != ExecutionState.Started && optimizer.ExecutionState != ExecutionState.Paused) {
+        OnStopped();
+        return;
+      }
+      // a race-condition may occur when the algorithm has changed the state by itself in the meantime
+      try { optimizer.Stop(); }
+      catch (InvalidOperationException) { }
+    }
+
+    public void Prepare() {
+      Prepare(false);
+    }
+
+    public void Prepare(bool clearRuns) {
+      if ((ExecutionState != ExecutionState.Prepared) && (ExecutionState != ExecutionState.Paused) && (ExecutionState != ExecutionState.Stopped))
+        throw new InvalidOperationException(string.Format("Prepare not allowed in execution state \"{0}\".", ExecutionState));
+      if (optimizer != null) {
+        ExecutionTime = TimeSpan.Zero;
+        if (clearRuns) optimizer.Runs.Clear();
+        // a race-condition may occur when the algorithm has changed the state by itself in the meantime
+        try { optimizer.Prepare(clearRuns); }
+        catch (InvalidOperationException) { }
+      } else {
+        ExecutionState = ExecutionState.Stopped;
+      }
+    }
+
+    [Storable]
+    private TimeSpan executionTime;
+    public TimeSpan ExecutionTime {
+      get {
+        if ((Optimizer != null) && (Optimizer.ExecutionState != ExecutionState.Stopped))
+          return executionTime + Optimizer.ExecutionTime;
+        else
+          return executionTime;
+      }
+      private set {
+        executionTime = value;
+        OnExecutionTimeChanged();
+      }
+    }
+
+    public RunCollection Runs {
+      get {
+        if (optimizer == null)
+          return new RunCollection(); // return an empty run collection
+        return Optimizer.Runs;
+      }
+    }
+
+    public IEnumerable<IOptimizer> NestedOptimizers { get; }
+
+    public string Filename { get; set; }
+
+    #region Events
+    protected override void OnNameChanged() {
+      base.OnNameChanged();
+    }
+
+    #region event firing
+    public ExecutionState ExecutionState { get; private set; }
+    public event EventHandler ExecutionStateChanged;
+    private void OnExecutionStateChanged() {
+      EventHandler handler = ExecutionStateChanged;
+      if (handler != null) handler(this, EventArgs.Empty);
+    }
+
+    public event EventHandler ExecutionTimeChanged;
+    private void OnExecutionTimeChanged() {
+      EventHandler handler = ExecutionTimeChanged;
+      if (handler != null) handler(this, EventArgs.Empty);
+    }
+
+    public event EventHandler Prepared;
+    private void OnPrepared() {
+      ExecutionState = ExecutionState.Prepared;
+      EventHandler handler = Prepared;
+      if (handler != null) handler(this, EventArgs.Empty);
+    }
+
+    public event EventHandler Started;
+    private void OnStarted() {
+      ExecutionState = ExecutionState.Started;
+      EventHandler handler = Started;
+      if (handler != null) handler(this, EventArgs.Empty);
+    }
+
+    public event EventHandler Paused;
+    private void OnPaused() {
+      ExecutionState = ExecutionState.Paused;
+      EventHandler handler = Paused;
+      if (handler != null) handler(this, EventArgs.Empty);
+    }
+
+    public event EventHandler Stopped;
+    private void OnStopped() {
+      ExecutionState = ExecutionState.Stopped;
+      EventHandler handler = Stopped;
+      if (handler != null) handler(this, EventArgs.Empty);
+    }
+
+    public event EventHandler<EventArgs<Exception>> ExceptionOccurred;
+    private void OnExceptionOccurred(Exception exception) {
+      EventHandler<EventArgs<Exception>> handler = ExceptionOccurred;
+      if (handler != null) handler(this, new EventArgs<Exception>(exception));
+    }
+
+    public event EventHandler OptimizerChanged;
+    private void OnOptimizerChanged() {
+      EventHandler handler = OptimizerChanged;
+      if (handler != null) handler(this, EventArgs.Empty);
+    }
+
+    public event EventHandler RepetitionsChanged;
+    private void OnRepetitionsChanged() {
+      EventHandler handler = RepetitionsChanged;
+      if (handler != null) handler(this, EventArgs.Empty);
+    }
+
+    public event EventHandler RepetetionsCounterChanged;
+    private void OnRepetitionsCounterChanged() {
+      EventHandler handler = RepetetionsCounterChanged;
+      if (handler != null) handler(this, EventArgs.Empty);
+    }
+    #endregion
+
+    #region optimizer event handlers
+    private void RegisterOptimizerEvents() {
+      optimizer.ExceptionOccurred += Optimizer_ExceptionOccurred;
+      optimizer.ExecutionTimeChanged += Optimizer_ExecutionTimeChanged;
+      optimizer.Paused += Optimizer_Paused;
+      optimizer.Prepared += Optimizer_Prepared;
+      optimizer.Started += Optimizer_Started;
+      optimizer.Stopped += Optimizer_Stopped;
+    }
+
+    private void DeregisterOptimizerEvents() {
+      optimizer.ExceptionOccurred -= Optimizer_ExceptionOccurred;
+      optimizer.ExecutionTimeChanged -= Optimizer_ExecutionTimeChanged;
+      optimizer.Paused -= Optimizer_Paused;
+      optimizer.Prepared -= Optimizer_Prepared;
+      optimizer.Started -= Optimizer_Started;
+      optimizer.Stopped -= Optimizer_Stopped;
+    }
+
+    private void Optimizer_ExceptionOccurred(object sender, EventArgs<Exception> e) {
+      OnExceptionOccurred(e.Value);
+    }
+
+    private void Optimizer_ExecutionTimeChanged(object sender, EventArgs e) {
+      OnExecutionTimeChanged();
+    }
+
+    private void Optimizer_Paused(object sender, EventArgs e) {
+      if (ExecutionState == ExecutionState.Started) {
+        OnPaused();
+      }
+    }
+
+    private void Optimizer_Prepared(object sender, EventArgs e) {
+      if (ExecutionState == ExecutionState.Stopped) {
+        ExecutionTime = TimeSpan.Zero;
+        OnPrepared();
+      }
+    }
+
+    private void Optimizer_Started(object sender, EventArgs e) {
+      if (ExecutionState != ExecutionState.Started) {
+        OnStarted();
+      }
+    }
+
+    private void Optimizer_Stopped(object sender, EventArgs e) {
+      calculatedRows++;
+      ExecutionTime += optimizer.ExecutionTime;
+
+      var remainingRows = problemData.TrainingIndices.Skip(calculatedRows);
+      if (remainingRows.Any()) {
+        var row = remainingRows.First();
+        problem.Configure(problemData, row);
+        optimizer.Prepare();
+        optimizer.Start();
+      } else {
+        OnStopped();
+      }
+    }
+    #endregion
+    #endregion
+  }
+}
Index: /branches/HeuristicLab.GoalSeekingProblem/HeuristicLab.GoalSeekingProblem/3.4/GoalSeekingProblem.csproj
===================================================================
--- /branches/HeuristicLab.GoalSeekingProblem/HeuristicLab.GoalSeekingProblem/3.4/GoalSeekingProblem.csproj	(revision 14379)
+++ /branches/HeuristicLab.GoalSeekingProblem/HeuristicLab.GoalSeekingProblem/3.4/GoalSeekingProblem.csproj	(revision 14380)
@@ -190,4 +190,5 @@
     <Compile Include="Analyzers\BestSolutionAnalyzer.cs" />
     <Compile Include="GoalParameter.cs" />
+    <Compile Include="GoalSeekingOptimizer.cs" />
     <Compile Include="GoalSeekingUtil.cs" />
     <Compile Include="InputParameter.cs" />
Index: /branches/HeuristicLab.GoalSeekingProblem/HeuristicLab.GoalSeekingProblem/3.4/Properties/AssemblyInfo.cs
===================================================================
--- /branches/HeuristicLab.GoalSeekingProblem/HeuristicLab.GoalSeekingProblem/3.4/Properties/AssemblyInfo.cs	(revision 14379)
+++ /branches/HeuristicLab.GoalSeekingProblem/HeuristicLab.GoalSeekingProblem/3.4/Properties/AssemblyInfo.cs	(revision 14380)
@@ -54,3 +54,3 @@
 // [assembly: AssemblyVersion("1.0.*")]
 [assembly: AssemblyVersion("3.3.0.0")]
-[assembly: AssemblyFileVersion("3.3.11.14336")]
+[assembly: AssemblyFileVersion("3.3.11.14379")]
