Index: trunk/sources/HeuristicLab.Problems.ExternalEvaluation/3.3/Analyzers/BestExternalEvaluationSolutionAnalyzer.cs
===================================================================
--- trunk/sources/HeuristicLab.Problems.ExternalEvaluation/3.3/Analyzers/BestExternalEvaluationSolutionAnalyzer.cs	(revision 3861)
+++ trunk/sources/HeuristicLab.Problems.ExternalEvaluation/3.3/Analyzers/BestExternalEvaluationSolutionAnalyzer.cs	(revision 3861)
@@ -0,0 +1,108 @@
+﻿#region License Information
+/* HeuristicLab
+ * Copyright (C) 2002-2010 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.Collections.Generic;
+using System.Linq;
+using HeuristicLab.Optimization;
+using HeuristicLab.Data;
+using HeuristicLab.Core;
+using HeuristicLab.Operators;
+using HeuristicLab.Parameters;
+using HeuristicLab.Persistence.Default.CompositeSerializers.Storable;
+
+namespace HeuristicLab.Problems.ExternalEvaluation {
+  /// <summary>
+  /// An operator for analyzing the best solution for an external evaluation problem.
+  /// </summary>
+  [Item("BestExternalEvaluationSolutionAnalyzer", "An operator for analyzing the best solution (=scope) for an external evaluation problem.")]
+  [StorableClass]
+  class BestExternalEvaluationSolutionAnalyzer : SingleSuccessorOperator, IAnalyzer {
+    public LookupParameter<BoolValue> MaximizationParameter {
+      get { return (LookupParameter<BoolValue>)Parameters["Maximization"]; }
+    }
+    public ScopeTreeLookupParameter<DoubleValue> QualityParameter {
+      get { return (ScopeTreeLookupParameter<DoubleValue>)Parameters["Quality"]; }
+    }
+    public ILookupParameter<IScope> BestSolutionParameter {
+      get { return (ILookupParameter<IScope>)Parameters["BestSolution"]; }
+    }
+    public ILookupParameter<IScope> BestKnownSolutionParameter {
+      get { return (ILookupParameter<IScope>)Parameters["BestKnownSolution"]; }
+    }
+    public ILookupParameter<DoubleValue> BestKnownQualityParameter {
+      get { return (ILookupParameter<DoubleValue>)Parameters["BestKnownQuality"]; }
+    }
+    public IValueLookupParameter<ResultCollection> ResultsParameter {
+      get { return (IValueLookupParameter<ResultCollection>)Parameters["Results"]; }
+    }
+
+    public BestExternalEvaluationSolutionAnalyzer()
+      : base() {
+      Parameters.Add(new LookupParameter<BoolValue>("Maximization", "True if the problem is a maximization problem."));
+      Parameters.Add(new ScopeTreeLookupParameter<DoubleValue>("Quality", "The qualities of the solutions."));
+      Parameters.Add(new LookupParameter<IScope>("BestSolution", "The best solution."));
+      Parameters.Add(new LookupParameter<IScope>("BestKnownSolution", "The best known solution."));
+      Parameters.Add(new LookupParameter<DoubleValue>("BestKnownQuality", "The quality of the best known solution."));
+      Parameters.Add(new ValueLookupParameter<ResultCollection>("Results", "The result collection where the solution should be stored."));
+    }
+
+    public override IOperation Apply() {
+      ItemArray<DoubleValue> qualities = QualityParameter.ActualValue;
+      ResultCollection results = ResultsParameter.ActualValue;
+      bool max = MaximizationParameter.ActualValue.Value;
+      DoubleValue bestKnownQuality = BestKnownQualityParameter.ActualValue;
+
+      int i = qualities.Select((x, index) => new { index, x.Value }).OrderBy(x => x.Value).First().index;
+      
+      IEnumerable<IScope> scopes = new IScope[] { ExecutionContext.Scope };
+      for (int j = 0; j < QualityParameter.Depth; j++)
+        scopes = scopes.Select(x => (IEnumerable<IScope>)x.SubScopes).Aggregate((a, b) => a.Concat(b));
+      IScope currentBestScope = scopes.ToList()[i];
+
+      if (bestKnownQuality == null ||
+          max && qualities[i].Value > bestKnownQuality.Value
+          || !max && qualities[i].Value < bestKnownQuality.Value) {
+        BestKnownQualityParameter.ActualValue = new DoubleValue(qualities[i].Value);
+        BestKnownSolutionParameter.ActualValue = (IScope)currentBestScope.Clone();
+      }
+
+      IScope solution = BestSolutionParameter.ActualValue;
+      if (solution == null) {
+        solution = (IScope)currentBestScope.Clone();
+        BestSolutionParameter.ActualValue = solution;
+        results.Add(new Result("Best Solution", solution));
+      } else {
+        string qualityName = QualityParameter.TranslatedName;
+        if (solution.Variables.ContainsKey(qualityName)) {
+          double bestSoFarQuality = (solution.Variables[qualityName].Value as DoubleValue).Value;
+          if (max && qualities[i].Value > bestSoFarQuality
+            || !max && qualities[i].Value < bestSoFarQuality) {
+            solution = (IScope)currentBestScope.Clone();
+            BestSolutionParameter.ActualValue = solution;
+            results["Best Solution"].Value = solution;
+          }
+        }
+      }
+
+      return base.Apply();
+    }
+  }
+}
Index: trunk/sources/HeuristicLab.Problems.ExternalEvaluation/3.3/ExternalEvaluationProblem.cs
===================================================================
--- trunk/sources/HeuristicLab.Problems.ExternalEvaluation/3.3/ExternalEvaluationProblem.cs	(revision 3860)
+++ trunk/sources/HeuristicLab.Problems.ExternalEvaluation/3.3/ExternalEvaluationProblem.cs	(revision 3861)
@@ -20,11 +20,14 @@
 #endregion
 
+using System;
+using System.Collections.Generic;
+using System.Drawing;
+using System.Linq;
+using HeuristicLab.Collections;
 using HeuristicLab.Core;
+using HeuristicLab.Data;
+using HeuristicLab.Optimization;
+using HeuristicLab.Parameters;
 using HeuristicLab.Persistence.Default.CompositeSerializers.Storable;
-using HeuristicLab.Parameters;
-using System.Drawing;
-using HeuristicLab.Optimization;
-using HeuristicLab.Data;
-using HeuristicLab.Operators;
 
 namespace HeuristicLab.Problems.ExternalEvaluation {
@@ -35,4 +38,10 @@
       get { return HeuristicLab.Common.Resources.VS2008ImageLibrary.Type; }
     }
+    public new ParameterCollection Parameters {
+      get { return base.Parameters; }
+    }
+    IKeyedItemCollection<string, IParameter> IParameterizedItem.Parameters {
+      get { return Parameters; }
+    }
 
     #region Parameters
@@ -49,6 +58,6 @@
       get { return MaximizationParameter; }
     }
-    public ValueParameter<IOperator> SolutionCreatorParameter {
-      get { return (ValueParameter<IOperator>)Parameters["SolutionCreator"]; }
+    public ValueParameter<ISolutionCreator> SolutionCreatorParameter {
+      get { return (ValueParameter<ISolutionCreator>)Parameters["SolutionCreator"]; }
     }
     IParameter IProblem.SolutionCreatorParameter {
@@ -66,4 +75,7 @@
     public OptionalValueParameter<IScope> BestKnownSolutionParameter {
       get { return (OptionalValueParameter<IScope>)Parameters["BestKnownSolution"]; }
+    }
+    public ValueParameter<ItemList<IOperator>> OperatorsParameter {
+      get { return (ValueParameter<ItemList<IOperator>>)Parameters["Operators"]; }
     }
     #endregion
@@ -74,5 +86,5 @@
       set { MaximizationParameter.Value = value; }
     }
-    public IOperator SolutionCreator {
+    public ISolutionCreator SolutionCreator {
       get { return SolutionCreatorParameter.Value; }
       set { SolutionCreatorParameter.Value = value; }
@@ -81,5 +93,5 @@
       get { return SolutionCreatorParameter.Value; }
     }
-    public ISingleObjectiveTestFunctionProblemEvaluator Evaluator {
+    public IExternalEvaluationProblemEvaluator Evaluator {
       get { return EvaluatorParameter.Value; }
       set { EvaluatorParameter.Value = value; }
@@ -95,22 +107,112 @@
       set { BestKnownQualityParameter.Value = value; }
     }
-    private List<IOperator> operators;
     public IEnumerable<IOperator> Operators {
-      get { return operators; }
-    }
-    private BestSingleObjectiveTestFunctionSolutionAnalyzer BestSingleObjectiveTestFunctionSolutionAnalyzer {
-      get { return operators.OfType<BestSingleObjectiveTestFunctionSolutionAnalyzer>().FirstOrDefault(); }
-    }
-    #endregion
-
+      get { return OperatorsParameter.Value; }
+    }
+    private BestExternalEvaluationSolutionAnalyzer BestExternalEvaluationSolutionAnalyzer {
+      get { return OperatorsParameter.Value.OfType<BestExternalEvaluationSolutionAnalyzer>().FirstOrDefault(); }
+    }
+    #endregion
+
+    [StorableConstructor]
+    protected ExternalEvaluationProblem(bool deserializing) : base(deserializing) { }
     public ExternalEvaluationProblem()
       : base() {
       ExternalEvaluator evaluator = new ExternalEvaluator();
-      EmptyOperator solutionCreator = new EmptyOperator();
+      ExternalEvaluationSolutionCreator solutionCreator = new ExternalEvaluationSolutionCreator();
 
       Parameters.Add(new ValueParameter<IExternalEvaluationDriver>("Driver", "The communication driver that is used to exchange data with the external process."));
       Parameters.Add(new ValueParameter<IExternalEvaluationProblemEvaluator>("Evaluator", "The evaluator that collects the values to exchange.", evaluator));
       Parameters.Add(new ValueParameter<IOperator>("SolutionCreator", "An operator to create the solution components.", solutionCreator));
-    }
+      Parameters.Add(new ValueParameter<BoolValue>("Maximization", "Set to false as most test functions are minimization problems.", new BoolValue(false)));
+      Parameters.Add(new OptionalValueParameter<DoubleValue>("BestKnownQuality", "The quality of the best known solution of this problem."));
+      Parameters.Add(new OptionalValueParameter<IScope>("BestKnownSolution", "The best known solution for this external evaluation problem."));
+      Parameters.Add(new ValueParameter<ItemList<IOperator>>("Operators", "The operators that are passed to the algorithm.", new ItemList<IOperator>()));
+
+      InitializeOperators();
+      AttachEventHandlers();
+    }
+
+    #region Events
+    public event EventHandler SolutionCreatorChanged;
+    private void OnSolutionCreatorChanged() {
+      EventHandler handler = SolutionCreatorChanged;
+      if (handler != null) handler(this, EventArgs.Empty);
+    }
+    public event EventHandler EvaluatorChanged;
+    private void OnEvaluatorChanged() {
+      EventHandler handler = EvaluatorChanged;
+      if (handler != null) handler(this, EventArgs.Empty);
+    }
+    public event EventHandler OperatorsChanged;
+    private void OnOperatorsChanged() {
+      EventHandler handler = OperatorsChanged;
+      if (handler != null) handler(this, EventArgs.Empty);
+    }
+    public event EventHandler Reset;
+    private void OnReset() {
+      EventHandler handler = Reset;
+      if (handler != null) handler(this, EventArgs.Empty);
+    }
+
+    private void SolutionCreatorParameter_ValueChanged(object sender, EventArgs e) {
+      OnSolutionCreatorChanged();
+    }
+    private void EvaluatorParameter_ValueChanged(object sender, EventArgs e) {
+      OnEvaluatorChanged();
+    }
+    private void Evaluator_QualityParameter_ActualNameChanged(object sender, EventArgs e) {
+      // TODO: Following code is not yet approved behavior, but it's the best effort I can make here regarding wiring
+      string qualityName = Evaluator.QualityParameter.ActualName;
+      foreach (IOperator op in OperatorsParameter.Value) {
+        foreach (ILookupParameter<DoubleValue> param in op.Parameters.OfType<ILookupParameter<DoubleValue>>()) {
+          if (param.Name.Equals("Quality")) param.ActualName = qualityName;
+        }
+        foreach (IScopeTreeLookupParameter<DoubleValue> param in op.Parameters.OfType<IScopeTreeLookupParameter<DoubleValue>>()) {
+          if (param.Name.Equals("Quality")) param.ActualName = qualityName;
+        }
+      }
+    }
+    private void OperatorsParameter_ValueChanged(object sender, EventArgs e) {
+      OnOperatorsChanged();
+    }
+    private void OperatorsParameter_Value_ItemsAdded(object sender, EventArgs e) {
+      OnOperatorsChanged();
+    }
+    private void OperatorsParameter_Value_ItemsRemoved(object sender, EventArgs e) {
+      OnOperatorsChanged();
+    }
+    private void OperatorsParameter_Value_CollectionReset(object sender, EventArgs e) {
+      OnOperatorsChanged();
+    }
+    #endregion
+
+    #region Helpers
+    private void InitializeOperators() {
+      ItemList<IOperator> operators = OperatorsParameter.Value;
+      operators.Add(new BestExternalEvaluationSolutionAnalyzer());
+      ParameterizeAnalyzers();
+    }
+    [StorableHook(HookType.AfterDeserialization)]
+    private void AttachEventHandlers() {
+      SolutionCreatorParameter.ValueChanged += new EventHandler(SolutionCreatorParameter_ValueChanged);
+      EvaluatorParameter.ValueChanged += new EventHandler(EvaluatorParameter_ValueChanged);
+      Evaluator.QualityParameter.ActualNameChanged += new EventHandler(Evaluator_QualityParameter_ActualNameChanged);
+      OperatorsParameter.ValueChanged += new System.EventHandler(OperatorsParameter_ValueChanged);
+      OperatorsParameter.Value.ItemsAdded += new CollectionItemsChangedEventHandler<IndexedItem<IOperator>>(OperatorsParameter_Value_ItemsAdded);
+      OperatorsParameter.Value.ItemsRemoved += new CollectionItemsChangedEventHandler<IndexedItem<IOperator>>(OperatorsParameter_Value_ItemsRemoved);
+      OperatorsParameter.Value.CollectionReset += new CollectionItemsChangedEventHandler<IndexedItem<IOperator>>(OperatorsParameter_Value_CollectionReset);
+    }
+    private void ParameterizeAnalyzers() {
+      BestExternalEvaluationSolutionAnalyzer.ResultsParameter.ActualName = "Results";
+      BestExternalEvaluationSolutionAnalyzer.QualityParameter.ActualName = Evaluator.QualityParameter.ActualName;
+      BestExternalEvaluationSolutionAnalyzer.BestKnownQualityParameter.ActualName = BestKnownQualityParameter.Name;
+      BestExternalEvaluationSolutionAnalyzer.BestKnownSolutionParameter.ActualName = BestKnownSolutionParameter.Name;
+      BestExternalEvaluationSolutionAnalyzer.MaximizationParameter.ActualName = MaximizationParameter.Name;
+    }
+    private void ParameterizeEvaluator() {
+      Evaluator.DriverParameter.ActualName = DriverParameter.Name;
+    }
+    #endregion
   }
 }
Index: trunk/sources/HeuristicLab.Problems.ExternalEvaluation/3.3/ExternalEvaluationSolutionCreator.cs
===================================================================
--- trunk/sources/HeuristicLab.Problems.ExternalEvaluation/3.3/ExternalEvaluationSolutionCreator.cs	(revision 3860)
+++ trunk/sources/HeuristicLab.Problems.ExternalEvaluation/3.3/ExternalEvaluationSolutionCreator.cs	(revision 3861)
@@ -33,4 +33,12 @@
   [StorableClass]
   public class ExternalEvaluationSolutionCreator : CheckedMultiOperator<IOperator>, ISolutionCreator {
+    public override IOperation Apply() {
+      OperationCollection result = new OperationCollection();
+      foreach (IOperator op in Operators.CheckedItems.OrderBy(x => x.Index).Select(x => x.Value)) {
+        result.Add(ExecutionContext.CreateOperation(op));
+      }
+      result.Add(base.Apply());
+      return result;
+    }
   }
 }
Index: trunk/sources/HeuristicLab.Problems.ExternalEvaluation/3.3/HeuristicLab.Problems.ExternalEvaluation-3.3.csproj
===================================================================
--- trunk/sources/HeuristicLab.Problems.ExternalEvaluation/3.3/HeuristicLab.Problems.ExternalEvaluation-3.3.csproj	(revision 3860)
+++ trunk/sources/HeuristicLab.Problems.ExternalEvaluation/3.3/HeuristicLab.Problems.ExternalEvaluation-3.3.csproj	(revision 3861)
@@ -79,4 +79,5 @@
   </ItemGroup>
   <ItemGroup>
+    <Compile Include="Analyzers\BestExternalEvaluationSolutionAnalyzer.cs" />
     <Compile Include="Drivers\ExternalEvaluationDriver.cs" />
     <Compile Include="Drivers\ExternalEvaluationProcessDriver.cs" />
Index: trunk/sources/HeuristicLab.Problems.ExternalEvaluation/3.3/Interfaces/IExternalEvaluationProblemEvaluator.cs
===================================================================
--- trunk/sources/HeuristicLab.Problems.ExternalEvaluation/3.3/Interfaces/IExternalEvaluationProblemEvaluator.cs	(revision 3860)
+++ trunk/sources/HeuristicLab.Problems.ExternalEvaluation/3.3/Interfaces/IExternalEvaluationProblemEvaluator.cs	(revision 3861)
@@ -25,7 +25,10 @@
 using System.Text;
 using HeuristicLab.Optimization;
+using HeuristicLab.Core;
+using HeuristicLab.Data;
 
 namespace HeuristicLab.Problems.ExternalEvaluation {
   public interface IExternalEvaluationProblemEvaluator : ISingleObjectiveEvaluator {
+    IValueLookupParameter<IExternalEvaluationDriver> DriverParameter { get; }
   }
 }
