Index: trunk/sources/HeuristicLab.Problems.TravelingSalesman/3.3/Analyzers/BestTSPSolutionAnalyzer.cs
===================================================================
--- trunk/sources/HeuristicLab.Problems.TravelingSalesman/3.3/Analyzers/BestTSPSolutionAnalyzer.cs	(revision 3616)
+++ trunk/sources/HeuristicLab.Problems.TravelingSalesman/3.3/Analyzers/BestTSPSolutionAnalyzer.cs	(revision 3616)
@@ -0,0 +1,89 @@
+#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.Linq;
+using HeuristicLab.Common;
+using HeuristicLab.Core;
+using HeuristicLab.Data;
+using HeuristicLab.Encodings.PermutationEncoding;
+using HeuristicLab.Operators;
+using HeuristicLab.Optimization;
+using HeuristicLab.Parameters;
+using HeuristicLab.Persistence.Default.CompositeSerializers.Storable;
+
+namespace HeuristicLab.Problems.TravelingSalesman {
+  /// <summary>
+  /// An operator for analyzing the best solution of Traveling Salesman Problems given in path representation using city coordinates.
+  /// </summary>
+  [Item("BestTSPSolutionAnalyzer", "An operator for analyzing the best solution of Traveling Salesman Problems given in path representation using city coordinates.")]
+  [StorableClass]
+  public sealed class BestTSPSolutionAnalyzer : SingleSuccessorOperator, IAnalyzer {
+    public LookupParameter<DoubleMatrix> CoordinatesParameter {
+      get { return (LookupParameter<DoubleMatrix>)Parameters["Coordinates"]; }
+    }
+    public SubScopesLookupParameter<Permutation> PermutationParameter {
+      get { return (SubScopesLookupParameter<Permutation>)Parameters["Permutation"]; }
+    }
+    public SubScopesLookupParameter<DoubleValue> QualityParameter {
+      get { return (SubScopesLookupParameter<DoubleValue>)Parameters["Quality"]; }
+    }
+    public LookupParameter<PathTSPTour> BestSolutionParameter {
+      get { return (LookupParameter<PathTSPTour>)Parameters["BestSolution"]; }
+    }
+    public ValueLookupParameter<ResultCollection> ResultsParameter {
+      get { return (ValueLookupParameter<ResultCollection>)Parameters["Results"]; }
+    }
+
+    public BestTSPSolutionAnalyzer()
+      : base() {
+      Parameters.Add(new LookupParameter<DoubleMatrix>("Coordinates", "The x- and y-Coordinates of the cities."));
+      Parameters.Add(new SubScopesLookupParameter<Permutation>("Permutation", "The TSP solutions given in path representation from which the best solution should be analyzed."));
+      Parameters.Add(new SubScopesLookupParameter<DoubleValue>("Quality", "The qualities of the TSP solutions which should be analyzed."));
+      Parameters.Add(new LookupParameter<PathTSPTour>("BestSolution", "The best TSP solution."));
+      Parameters.Add(new ValueLookupParameter<ResultCollection>("Results", "The result collection where the best TSP solution should be stored."));
+    }
+
+    public override IOperation Apply() {
+      DoubleMatrix coordinates = CoordinatesParameter.ActualValue;
+      ItemArray<Permutation> permutations = PermutationParameter.ActualValue;
+      ItemArray<DoubleValue> qualities = QualityParameter.ActualValue;
+      ResultCollection results = ResultsParameter.ActualValue;
+
+      int i = qualities.Select((x, index) => new { index, x.Value }).OrderBy(x => x.Value).First().index;
+
+      PathTSPTour tour = BestSolutionParameter.ActualValue;
+      if (tour == null) {
+        tour = new PathTSPTour(coordinates, permutations[i], qualities[i]);
+        BestSolutionParameter.ActualValue = tour;
+        results.Add(new Result("Best TSP Solution", tour));
+      } else {
+        if (tour.Quality.Value > qualities[i].Value) {
+          tour.Coordinates = coordinates;
+          tour.Permutation = permutations[i];
+          tour.Quality = qualities[i];
+          results["Best TSP Solution"].Value = tour;
+        }
+      }
+
+      return base.Apply();
+    }
+  }
+}
Index: trunk/sources/HeuristicLab.Problems.TravelingSalesman/3.3/HeuristicLab.Problems.TravelingSalesman-3.3.csproj
===================================================================
--- trunk/sources/HeuristicLab.Problems.TravelingSalesman/3.3/HeuristicLab.Problems.TravelingSalesman-3.3.csproj	(revision 3520)
+++ trunk/sources/HeuristicLab.Problems.TravelingSalesman/3.3/HeuristicLab.Problems.TravelingSalesman-3.3.csproj	(revision 3616)
@@ -84,4 +84,5 @@
   </ItemGroup>
   <ItemGroup>
+    <Compile Include="Analyzers\BestTSPSolutionAnalyzer.cs" />
     <Compile Include="Evaluators\TSPEuclideanPathEvaluator.cs" />
     <Compile Include="Evaluators\TSPGeoPathEvaluator.cs" />
@@ -97,9 +98,5 @@
     <Compile Include="TravelingSalesmanProblem.cs" />
     <Compile Include="TSPLIBTourParser.cs" />
-    <Compile Include="Interfaces\ICoordinatesTSPSolutionsVisualizer.cs" />
-    <Compile Include="Interfaces\IPathCoordinatesTSPSolutionsVisualizer.cs" />
-    <Compile Include="Interfaces\ITSPSolutionsVisualizer.cs" />
     <Compile Include="PathTSPTour.cs" />
-    <Compile Include="Visualizers\BestPathTSPTourVisualizer.cs" />
     <Compile Include="Evaluators\TSPCoordinatesPathEvaluator.cs" />
     <Compile Include="Evaluators\TSPEvaluator.cs" />
Index: trunk/sources/HeuristicLab.Problems.TravelingSalesman/3.3/Interfaces/ICoordinatesTSPSolutionsVisualizer.cs
===================================================================
--- trunk/sources/HeuristicLab.Problems.TravelingSalesman/3.3/Interfaces/ICoordinatesTSPSolutionsVisualizer.cs	(revision 3520)
+++ 	(revision )
@@ -1,33 +1,0 @@
-#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 HeuristicLab.Common;
-using HeuristicLab.Core;
-using HeuristicLab.Data;
-
-namespace HeuristicLab.Problems.TravelingSalesman {
-  /// <summary>
-  /// An interface which represents an operator for visualizing tours of Traveling Salesman Problems using city coordinates.
-  /// </summary>
-  public interface ICoordinatesTSPSolutionsVisualizer : ITSPSolutionsVisualizer {
-    ILookupParameter<DoubleMatrix> CoordinatesParameter { get; }
-  }
-}
Index: trunk/sources/HeuristicLab.Problems.TravelingSalesman/3.3/Interfaces/IPathCoordinatesTSPSolutionsVisualizer.cs
===================================================================
--- trunk/sources/HeuristicLab.Problems.TravelingSalesman/3.3/Interfaces/IPathCoordinatesTSPSolutionsVisualizer.cs	(revision 3520)
+++ 	(revision )
@@ -1,33 +1,0 @@
-#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 HeuristicLab.Common;
-using HeuristicLab.Core;
-using HeuristicLab.Encodings.PermutationEncoding;
-
-namespace HeuristicLab.Problems.TravelingSalesman {
-  /// <summary>
-  /// An interface which represents an operator for visualizing tours of Traveling Salesman Problems given in path representation using city coordinates.
-  /// </summary>
-  public interface IPathCoordinatesTSPSolutionsVisualizer : ICoordinatesTSPSolutionsVisualizer {
-    ILookupParameter<ItemArray<Permutation>> PermutationParameter { get; }
-  }
-}
Index: trunk/sources/HeuristicLab.Problems.TravelingSalesman/3.3/Interfaces/ITSPSolutionsVisualizer.cs
===================================================================
--- trunk/sources/HeuristicLab.Problems.TravelingSalesman/3.3/Interfaces/ITSPSolutionsVisualizer.cs	(revision 3520)
+++ 	(revision )
@@ -1,29 +1,0 @@
-#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 HeuristicLab.Optimization;
-
-namespace HeuristicLab.Problems.TravelingSalesman {
-  /// <summary>
-  /// An interface which represents an operator for visualizing solutions of Traveling Salesman Problems.
-  /// </summary>
-  public interface ITSPSolutionsVisualizer : ISingleObjectiveSolutionsVisualizer { }
-}
Index: trunk/sources/HeuristicLab.Problems.TravelingSalesman/3.3/PathTSPTour.cs
===================================================================
--- trunk/sources/HeuristicLab.Problems.TravelingSalesman/3.3/PathTSPTour.cs	(revision 3520)
+++ trunk/sources/HeuristicLab.Problems.TravelingSalesman/3.3/PathTSPTour.cs	(revision 3616)
@@ -65,4 +65,17 @@
       }
     }
+    [Storable]
+    private DoubleValue quality;
+    public DoubleValue Quality {
+      get { return quality; }
+      set {
+        if (quality != value) {
+          if (quality != null) DeregisterQualityEvents();
+          quality = value;
+          if (quality != null) RegisterQualityEvents();
+          OnQualityChanged();
+        }
+      }
+    }
 
     public PathTSPTour() : base() { }
@@ -78,4 +91,11 @@
       Initialize();
     }
+    public PathTSPTour(DoubleMatrix coordinates, Permutation permutation, DoubleValue quality)
+      : base() {
+      this.coordinates = coordinates;
+      this.permutation = permutation;
+      this.quality = quality;
+      Initialize();
+    }
     [StorableConstructor]
     private PathTSPTour(bool deserializing) : base(deserializing) { }
@@ -85,4 +105,5 @@
       if (coordinates != null) RegisterCoordinatesEvents();
       if (permutation != null) RegisterPermutationEvents();
+      if (quality != null) RegisterQualityEvents();
     }
 
@@ -92,4 +113,5 @@
       clone.coordinates = (DoubleMatrix)cloner.Clone(coordinates);
       clone.permutation = (Permutation)cloner.Clone(permutation);
+      clone.quality = (DoubleValue)cloner.Clone(quality);
       clone.Initialize();
       return clone;
@@ -106,4 +128,10 @@
     private void OnPermutationChanged() {
       var changed = PermutationChanged;
+      if (changed != null)
+        changed(this, EventArgs.Empty);
+    }
+    public event EventHandler QualityChanged;
+    private void OnQualityChanged() {
+      var changed = QualityChanged;
       if (changed != null)
         changed(this, EventArgs.Empty);
@@ -126,4 +154,10 @@
       Permutation.Reset -= new EventHandler(Permutation_Reset);
     }
+    private void RegisterQualityEvents() {
+      Quality.ValueChanged += new EventHandler(Quality_ValueChanged);
+    }
+    private void DeregisterQualityEvents() {
+      Quality.ValueChanged -= new EventHandler(Quality_ValueChanged);
+    }
 
     private void Coordinates_ItemChanged(object sender, EventArgs<int, int> e) {
@@ -139,4 +173,7 @@
       OnPermutationChanged();
     }
+    private void Quality_ValueChanged(object sender, EventArgs e) {
+      OnQualityChanged();
+    }
     #endregion
   }
Index: trunk/sources/HeuristicLab.Problems.TravelingSalesman/3.3/TravelingSalesmanProblem.cs
===================================================================
--- trunk/sources/HeuristicLab.Problems.TravelingSalesman/3.3/TravelingSalesmanProblem.cs	(revision 3520)
+++ trunk/sources/HeuristicLab.Problems.TravelingSalesman/3.3/TravelingSalesmanProblem.cs	(revision 3616)
@@ -71,10 +71,4 @@
       get { return EvaluatorParameter; }
     }
-    public OptionalValueParameter<ITSPSolutionsVisualizer> VisualizerParameter {
-      get { return (OptionalValueParameter<ITSPSolutionsVisualizer>)Parameters["Visualizer"]; }
-    }
-    IParameter IProblem.VisualizerParameter {
-      get { return VisualizerParameter; }
-    }
     public OptionalValueParameter<DoubleValue> BestKnownQualityParameter {
       get { return (OptionalValueParameter<DoubleValue>)Parameters["BestKnownQuality"]; }
@@ -118,11 +112,4 @@
       get { return EvaluatorParameter.Value; }
     }
-    public ITSPSolutionsVisualizer Visualizer {
-      get { return VisualizerParameter.Value; }
-      set { VisualizerParameter.Value = value; }
-    }
-    ISolutionsVisualizer IProblem.Visualizer {
-      get { return VisualizerParameter.Value; }
-    }
     public DoubleValue BestKnownQuality {
       get { return BestKnownQualityParameter.Value; }
@@ -133,7 +120,10 @@
       set { BestKnownSolutionParameter.Value = value; }
     }
-    private List<IPermutationOperator> operators;
+    private List<IOperator> operators;
     public IEnumerable<IOperator> Operators {
-      get { return operators.Cast<IOperator>(); }
+      get { return operators; }
+    }
+    private BestTSPSolutionAnalyzer Analyzer {
+      get { return operators.OfType<BestTSPSolutionAnalyzer>().FirstOrDefault(); }
     }
     #endregion
@@ -143,5 +133,4 @@
       RandomPermutationCreator creator = new RandomPermutationCreator();
       TSPRoundedEuclideanPathEvaluator evaluator = new TSPRoundedEuclideanPathEvaluator();
-      BestPathTSPTourVisualizer visualizer = new BestPathTSPTourVisualizer();
 
       Parameters.Add(new ValueParameter<BoolValue>("Maximization", "Set to false as the Traveling Salesman Problem is a minimization problem.", new BoolValue(false)));
@@ -151,5 +140,4 @@
       Parameters.Add(new ValueParameter<IPermutationCreator>("SolutionCreator", "The operator which should be used to create new TSP solutions.", creator));
       Parameters.Add(new ValueParameter<ITSPEvaluator>("Evaluator", "The operator which should be used to evaluate TSP solutions.", evaluator));
-      Parameters.Add(new OptionalValueParameter<ITSPSolutionsVisualizer>("Visualizer", "The operator which should be used to visualize TSP solutions.", visualizer));
       Parameters.Add(new OptionalValueParameter<DoubleValue>("BestKnownQuality", "The quality of the best known solution of this TSP instance."));
       Parameters.Add(new OptionalValueParameter<Permutation>("BestKnownSolution", "The best known solution of this TSP instance."));
@@ -166,5 +154,4 @@
       ParameterizeSolutionCreator();
       ParameterizeEvaluator();
-      ParameterizeVisualizer();
 
       Initialize();
@@ -221,9 +208,4 @@
         EvaluatorChanged(this, EventArgs.Empty);
     }
-    public event EventHandler VisualizerChanged;
-    private void OnVisualizerChanged() {
-      if (VisualizerChanged != null)
-        VisualizerChanged(this, EventArgs.Empty);
-    }
     public event EventHandler OperatorsChanged;
     private void OnOperatorsChanged() {
@@ -249,5 +231,5 @@
       ParameterizeSolutionCreator();
       ParameterizeEvaluator();
-      ParameterizeVisualizer();
+      ParameterizeAnalyzer();
       ParameterizeOperators();
       OnSolutionCreatorChanged();
@@ -255,5 +237,5 @@
     private void SolutionCreator_PermutationParameter_ActualNameChanged(object sender, EventArgs e) {
       ParameterizeEvaluator();
-      ParameterizeVisualizer();
+      ParameterizeAnalyzer();
       ParameterizeOperators();
     }
@@ -262,14 +244,10 @@
       ParameterizeEvaluator();
       UpdateMoveEvaluators();
-      ParameterizeVisualizer();
+      ParameterizeAnalyzer();
       ClearDistanceMatrix();
       OnEvaluatorChanged();
     }
     private void Evaluator_QualityParameter_ActualNameChanged(object sender, EventArgs e) {
-      ParameterizeVisualizer();
-    }
-    private void VisualizerParameter_ValueChanged(object sender, EventArgs e) {
-      ParameterizeVisualizer();
-      OnVisualizerChanged();
+      ParameterizeAnalyzer();
     }
     private void MoveGenerator_InversionMoveParameter_ActualNameChanged(object sender, EventArgs e) {
@@ -298,10 +276,11 @@
       EvaluatorParameter.ValueChanged += new EventHandler(EvaluatorParameter_ValueChanged);
       Evaluator.QualityParameter.ActualNameChanged += new EventHandler(Evaluator_QualityParameter_ActualNameChanged);
-      VisualizerParameter.ValueChanged += new EventHandler(VisualizerParameter_ValueChanged);
     }
 
     private void InitializeOperators() {
-      operators = new List<IPermutationOperator>();
-      operators.AddRange(ApplicationManager.Manager.GetInstances<IPermutationOperator>());
+      operators = new List<IOperator>();
+      operators.Add(new BestTSPSolutionAnalyzer());
+      ParameterizeAnalyzer();
+      operators.AddRange(ApplicationManager.Manager.GetInstances<IPermutationOperator>().Cast<IOperator>());
       ParameterizeOperators();
       UpdateMoveEvaluators();
@@ -344,11 +323,10 @@
       }
     }
-    private void ParameterizeVisualizer() {
-      if (Visualizer != null) {
-        Visualizer.QualityParameter.ActualName = Evaluator.QualityParameter.ActualName;
-        if (Visualizer is ICoordinatesTSPSolutionsVisualizer)
-          ((ICoordinatesTSPSolutionsVisualizer)Visualizer).CoordinatesParameter.ActualName = CoordinatesParameter.Name;
-        if (Visualizer is IPathCoordinatesTSPSolutionsVisualizer)
-          ((IPathCoordinatesTSPSolutionsVisualizer)Visualizer).PermutationParameter.ActualName = SolutionCreator.PermutationParameter.ActualName;
+    private void ParameterizeAnalyzer() {
+      if (Analyzer != null) {
+        Analyzer.QualityParameter.ActualName = Evaluator.QualityParameter.ActualName;
+        Analyzer.CoordinatesParameter.ActualName = CoordinatesParameter.Name;
+        Analyzer.PermutationParameter.ActualName = SolutionCreator.PermutationParameter.ActualName;
+        Analyzer.ResultsParameter.ActualName = "Results";
       }
     }
