Index: /trunk/sources/HeuristicLab.Algorithms.LocalSearch/3.3/LocalSearch.cs
===================================================================
--- /trunk/sources/HeuristicLab.Algorithms.LocalSearch/3.3/LocalSearch.cs	(revision 3620)
+++ /trunk/sources/HeuristicLab.Algorithms.LocalSearch/3.3/LocalSearch.cs	(revision 3621)
@@ -33,4 +33,5 @@
 using HeuristicLab.PluginInfrastructure;
 using HeuristicLab.Random;
+using HeuristicLab.Analysis;
 
 namespace HeuristicLab.Algorithms.LocalSearch {
@@ -71,4 +72,10 @@
       get { return (ValueParameter<IntValue>)Parameters["SampleSize"]; }
     }
+    private ValueParameter<MultiAnalyzer> MoveAnalyzerParameter {
+      get { return (ValueParameter<MultiAnalyzer>)Parameters["MoveAnalyzer"]; }
+    }
+    private ValueParameter<MultiAnalyzer> AnalyzerParameter {
+      get { return (ValueParameter<MultiAnalyzer>)Parameters["Analyzer"]; }
+    }
     #endregion
 
@@ -102,4 +109,12 @@
       set { SampleSizeParameter.Value = value; }
     }
+    public MultiAnalyzer MoveAnalyzer {
+      get { return MoveAnalyzerParameter.Value; }
+      set { MoveAnalyzerParameter.Value = value; }
+    }
+    public MultiAnalyzer Analyzer {
+      get { return AnalyzerParameter.Value; }
+      set { AnalyzerParameter.Value = value; }
+    }
     private RandomCreator RandomCreator {
       get { return (RandomCreator)OperatorGraph.InitialOperator; }
@@ -111,6 +126,9 @@
       get { return (LocalSearchMainLoop)SolutionsCreator.Successor; }
     }
-    #endregion
-
+    private BestAverageWorstQualityAnalyzer moveQualityAnalyzer;
+    #endregion
+
+    [StorableConstructor]
+    private LocalSearch(bool deserializing) : base(deserializing) { }
     public LocalSearch()
       : base() {
@@ -122,5 +140,7 @@
       Parameters.Add(new ValueParameter<IntValue>("MaximumIterations", "The maximum number of generations which should be processed.", new IntValue(1000)));
       Parameters.Add(new ValueParameter<IntValue>("SampleSize", "Number of moves that MultiMoveGenerators should create. This is ignored for Exhaustive- and SingleMoveGenerators.", new IntValue(100)));
-
+      Parameters.Add(new ValueParameter<MultiAnalyzer>("MoveAnalyzer", "The operator used to analyze the moves in each iteration.", new MultiAnalyzer()));
+      Parameters.Add(new ValueParameter<MultiAnalyzer>("Analyzer", "The operator used to analyze each iteration.", new MultiAnalyzer()));
+      
       RandomCreator randomCreator = new RandomCreator();
       SolutionsCreator solutionsCreator = new SolutionsCreator();
@@ -144,9 +164,9 @@
       lsMainLoop.RandomParameter.ActualName = RandomCreator.RandomParameter.ActualName;
       lsMainLoop.ResultsParameter.ActualName = "Results";
+      lsMainLoop.MoveAnalyzerParameter.ActualName = MoveAnalyzerParameter.Name;
+      lsMainLoop.AnalyzerParameter.ActualName = AnalyzerParameter.Name;
 
       Initialize();
     }
-    [StorableConstructor]
-    private LocalSearch(bool deserializing) : base(deserializing) { }
 
     public override IDeepCloneable Clone(Cloner cloner) {
@@ -173,6 +193,8 @@
       ParameterizeMoveEvaluators();
       ParameterizeMoveMakers();
+      ParameterizeAnalyzers();
       UpdateMoveGenerator();
       UpdateMoveParameters();
+      UpdateAnalyzers();
       Problem.Evaluator.QualityParameter.ActualNameChanged += new EventHandler(Evaluator_QualityParameter_ActualNameChanged);
       base.OnProblemChanged();
@@ -189,4 +211,5 @@
       ParameterizeMoveEvaluators();
       ParameterizeMoveMakers();
+      ParameterizeAnalyzers();
       Problem.Evaluator.QualityParameter.ActualNameChanged += new EventHandler(Evaluator_QualityParameter_ActualNameChanged);
       base.Problem_EvaluatorChanged(sender, e);
@@ -202,4 +225,5 @@
       UpdateMoveGenerator();
       UpdateMoveParameters();
+      UpdateAnalyzers();
       ParameterizeMainLoop();
       ParameterizeMoveEvaluators();
@@ -219,4 +243,5 @@
       ParameterizeMoveEvaluators();
       ParameterizeMoveMakers();
+      ParameterizeAnalyzers();
     }
     private void MoveEvaluator_MoveQualityParameter_ActualNameChanged(object sender, EventArgs e) {
@@ -224,4 +249,5 @@
       ParameterizeMoveEvaluators();
       ParameterizeMoveMakers();
+      ParameterizeAnalyzers();
     }
     #endregion
@@ -230,4 +256,6 @@
     [StorableHook(HookType.AfterDeserialization)]
     private void Initialize() {
+      InitializeAnalyzers();
+      UpdateAnalyzers();
       if (Problem != null) {
         Problem.Evaluator.QualityParameter.ActualNameChanged += new EventHandler(Evaluator_QualityParameter_ActualNameChanged);
@@ -238,4 +266,8 @@
       MoveGeneratorParameter.ValueChanged += new EventHandler(MoveGeneratorParameter_ValueChanged);
       MoveEvaluatorParameter.ValueChanged += new EventHandler(MoveEvaluatorParameter_ValueChanged);
+    }
+    private void InitializeAnalyzers() {
+      moveQualityAnalyzer = new BestAverageWorstQualityAnalyzer();
+      ParameterizeAnalyzers();
     }
     private void UpdateMoveGenerator() {
@@ -281,4 +313,13 @@
       }
     }
+    private void UpdateAnalyzers() {
+      Analyzer.Operators.Clear();
+      MoveAnalyzer.Operators.Clear();
+      MoveAnalyzer.Operators.Add(moveQualityAnalyzer);
+      /*if (Problem != null) {
+        foreach (ISolutionAnalyzer analyzer in Problem.Operators.OfType<ISolutionAnalyzer>().OrderBy(x => x.Name))
+          Analyzer.Operators.Add(analyzer);
+      }*/
+    }
     private void ClearMoveParameters() {
       MoveMakerParameter.ValidValues.Clear();
@@ -312,4 +353,13 @@
       }
     }
+    private void ParameterizeAnalyzers() {
+      moveQualityAnalyzer.ResultsParameter.ActualName = "Results";
+      if (Problem != null) {
+        moveQualityAnalyzer.MaximizationParameter.ActualName = Problem.MaximizationParameter.Name;
+        if (MoveEvaluator != null)
+          moveQualityAnalyzer.QualityParameter.ActualName = MoveEvaluator.MoveQualityParameter.ActualName;
+        moveQualityAnalyzer.BestKnownQualityParameter.ActualName = Problem.BestKnownQualityParameter.Name;
+      }
+    }
     #endregion
   }
Index: /trunk/sources/HeuristicLab.Algorithms.LocalSearch/3.3/LocalSearchMainLoop.cs
===================================================================
--- /trunk/sources/HeuristicLab.Algorithms.LocalSearch/3.3/LocalSearchMainLoop.cs	(revision 3620)
+++ /trunk/sources/HeuristicLab.Algorithms.LocalSearch/3.3/LocalSearchMainLoop.cs	(revision 3621)
@@ -68,9 +68,9 @@
       get { return (ValueLookupParameter<IOperator>)Parameters["MoveMaker"]; }
     }
-    public ValueLookupParameter<IOperator> VisualizerParameter {
-      get { return (ValueLookupParameter<IOperator>)Parameters["Visualizer"]; }
-    }
-    public LookupParameter<IItem> VisualizationParameter {
-      get { return (LookupParameter<IItem>)Parameters["Visualization"]; }
+    public ValueLookupParameter<IOperator> MoveAnalyzerParameter {
+      get { return (ValueLookupParameter<IOperator>)Parameters["MoveAnalyzer"]; }
+    }
+    public ValueLookupParameter<IOperator> AnalyzerParameter {
+      get { return (ValueLookupParameter<IOperator>)Parameters["Analyzer"]; }
     }
 
@@ -104,6 +104,6 @@
       Parameters.Add(new ValueLookupParameter<IOperator>("MoveEvaluator", "The operator that evaluates a move."));
 
-      Parameters.Add(new ValueLookupParameter<IOperator>("Visualizer", "The operator used to visualize solutions."));
-      Parameters.Add(new LookupParameter<IItem>("Visualization", "The item which represents the visualization of solutions."));
+      Parameters.Add(new ValueLookupParameter<IOperator>("MoveAnalyzer", "The operator used to analyze the moves in each iteration."));
+      Parameters.Add(new ValueLookupParameter<IOperator>("Analyzer", "The operator used to analyze each iteration."));
       Parameters.Add(new ScopeParameter("CurrentScope", "The current scope which represents a population of solutions on which the TS should be applied."));
       #endregion
@@ -111,14 +111,12 @@
       #region Create operators
       VariableCreator variableCreator = new VariableCreator();
-      BestQualityMemorizer bestQualityMemorizer1 = new BestQualityMemorizer();
-      BestQualityMemorizer bestQualityMemorizer2 = new BestQualityMemorizer();
-      DataTableValuesCollector dataTableValuesCollector1 = new DataTableValuesCollector();
-      QualityDifferenceCalculator qualityDifferenceCalculator1 = new QualityDifferenceCalculator();
-      Placeholder visualizer1 = new Placeholder();
-      ResultsCollector resultsCollector = new ResultsCollector();
+      ResultsCollector resultsCollector1 = new ResultsCollector();
+      UniformSubScopesProcessor uniformSubScopesProcessor0 = new UniformSubScopesProcessor();
+      Placeholder analyzer1 = new Placeholder();
       UniformSubScopesProcessor mainProcessor = new UniformSubScopesProcessor();
       Placeholder moveGenerator = new Placeholder();
       UniformSubScopesProcessor moveEvaluationProcessor = new UniformSubScopesProcessor();
       Placeholder moveEvaluator = new Placeholder();
+      Placeholder moveAnalyzer = new Placeholder();
       BestSelector bestSelector = new BestSelector();
       RightReducer rightReducer = new RightReducer();
@@ -130,41 +128,16 @@
       IntCounter iterationsCounter = new IntCounter();
       Comparator iterationsComparator = new Comparator();
-      BestQualityMemorizer bestQualityMemorizer3 = new BestQualityMemorizer();
-      BestQualityMemorizer bestQualityMemorizer4 = new BestQualityMemorizer();
-      DataTableValuesCollector dataTableValuesCollector2 = new DataTableValuesCollector();
-      QualityDifferenceCalculator qualityDifferenceCalculator2 = new QualityDifferenceCalculator();
-      Placeholder visualizer2 = new Placeholder();
+      ResultsCollector resultsCollector2 = new ResultsCollector();
+      UniformSubScopesProcessor uniformSubScopesProcessor1 = new UniformSubScopesProcessor();
+      Placeholder analyzer2 = new Placeholder();
       ConditionalBranch iterationsTermination = new ConditionalBranch();
 
       variableCreator.CollectedValues.Add(new ValueParameter<IntValue>("Iterations", new IntValue(0)));
 
-      bestQualityMemorizer1.BestQualityParameter.ActualName = BestKnownQualityParameter.Name;
-      bestQualityMemorizer1.MaximizationParameter.ActualName = MaximizationParameter.Name;
-      bestQualityMemorizer1.QualityParameter.ActualName = QualityParameter.Name;
-
-      bestQualityMemorizer2.BestQualityParameter.ActualName = "BestQuality";
-      bestQualityMemorizer2.MaximizationParameter.ActualName = MaximizationParameter.Name;
-      bestQualityMemorizer2.QualityParameter.ActualName = QualityParameter.Name;
-
-      dataTableValuesCollector1.CollectedValues.Add(new LookupParameter<DoubleValue>("BestQuality"));
-      dataTableValuesCollector1.CollectedValues.Add(new LookupParameter<DoubleValue>("Best Known Quality", null, BestKnownQualityParameter.Name));
-      dataTableValuesCollector1.DataTableParameter.ActualName = "Qualities";
-
-      qualityDifferenceCalculator1.AbsoluteDifferenceParameter.ActualName = "AbsoluteDifferenceBestKnownToBest";
-      qualityDifferenceCalculator1.FirstQualityParameter.ActualName = BestKnownQualityParameter.Name;
-      qualityDifferenceCalculator1.RelativeDifferenceParameter.ActualName = "RelativeDifferenceBestKnownToBest";
-      qualityDifferenceCalculator1.SecondQualityParameter.ActualName = "BestQuality";
-
-      visualizer1.Name = "Visualizer (placeholder)";
-      visualizer1.OperatorParameter.ActualName = VisualizerParameter.Name;
-
-      resultsCollector.CollectedValues.Add(new LookupParameter<IntValue>("Iterations"));
-      resultsCollector.CollectedValues.Add(new LookupParameter<DoubleValue>("Best Quality", null, "BestQuality"));
-      resultsCollector.CollectedValues.Add(new LookupParameter<DoubleValue>("Best Known Quality", null, BestKnownQualityParameter.Name));
-      resultsCollector.CollectedValues.Add(new LookupParameter<DoubleValue>("Absolute Difference of Best Known Quality to Best Quality", null, "AbsoluteDifferenceBestKnownToBest"));
-      resultsCollector.CollectedValues.Add(new LookupParameter<DoubleValue>("Relative Difference of Best Known Quality to Best Quality", null, "RelativeDifferenceBestKnownToBest"));
-      resultsCollector.CollectedValues.Add(new LookupParameter<IItem>("Solution Visualization", null, VisualizationParameter.Name));
-      resultsCollector.CollectedValues.Add(new LookupParameter<DataTable>("Qualities"));
-      resultsCollector.ResultsParameter.ActualName = ResultsParameter.Name;
+      resultsCollector1.CollectedValues.Add(new LookupParameter<IntValue>("Iterations"));
+      resultsCollector1.ResultsParameter.ActualName = ResultsParameter.Name;
+
+      analyzer1.Name = "Analyzer (placeholder)";
+      analyzer1.OperatorParameter.ActualName = AnalyzerParameter.Name;
 
       mainProcessor.Name = "Solution processor (UniformSubScopesProcessor)";
@@ -175,4 +148,7 @@
       moveEvaluator.Name = "MoveEvaluator (placeholder)";
       moveEvaluator.OperatorParameter.ActualName = MoveEvaluatorParameter.Name;
+
+      moveAnalyzer.Name = "MoveAnalyzer (placeholder)";
+      moveAnalyzer.OperatorParameter.ActualName = MoveAnalyzerParameter.Name;
 
       bestSelector.CopySelected = new BoolValue(false);
@@ -204,23 +180,9 @@
       iterationsComparator.ResultParameter.ActualName = "Terminate";
 
-      bestQualityMemorizer3.BestQualityParameter.ActualName = BestKnownQualityParameter.Name;
-      bestQualityMemorizer3.MaximizationParameter.ActualName = MaximizationParameter.Name;
-      bestQualityMemorizer3.QualityParameter.ActualName = QualityParameter.Name;
-
-      bestQualityMemorizer4.BestQualityParameter.ActualName = "BestQuality";
-      bestQualityMemorizer4.MaximizationParameter.ActualName = MaximizationParameter.Name;
-      bestQualityMemorizer4.QualityParameter.ActualName = QualityParameter.Name;
-
-      dataTableValuesCollector2.CollectedValues.Add(new LookupParameter<DoubleValue>("BestQuality"));
-      dataTableValuesCollector2.CollectedValues.Add(new LookupParameter<DoubleValue>("Best Known Quality", null, BestKnownQualityParameter.Name));
-      dataTableValuesCollector2.DataTableParameter.ActualName = "Qualities";
-
-      qualityDifferenceCalculator2.AbsoluteDifferenceParameter.ActualName = "AbsoluteDifferenceBestKnownToBest";
-      qualityDifferenceCalculator2.FirstQualityParameter.ActualName = BestKnownQualityParameter.Name;
-      qualityDifferenceCalculator2.RelativeDifferenceParameter.ActualName = "RelativeDifferenceBestKnownToBest";
-      qualityDifferenceCalculator2.SecondQualityParameter.ActualName = "BestQuality";
-
-      visualizer2.Name = "Visualizer (placeholder)";
-      visualizer2.OperatorParameter.ActualName = VisualizerParameter.Name;
+      resultsCollector2.CollectedValues.Add(new LookupParameter<IntValue>("Iterations"));
+      resultsCollector2.ResultsParameter.ActualName = ResultsParameter.Name;
+
+      analyzer2.Name = "Analyzer (placeholder)";
+      analyzer2.OperatorParameter.ActualName = AnalyzerParameter.Name;
 
       iterationsTermination.Name = "Iterations Termination Condition";
@@ -230,16 +192,15 @@
       #region Create operator graph
       OperatorGraph.InitialOperator = variableCreator;
-      variableCreator.Successor = bestQualityMemorizer1;
-      bestQualityMemorizer1.Successor = bestQualityMemorizer2;
-      bestQualityMemorizer2.Successor = dataTableValuesCollector1;
-      dataTableValuesCollector1.Successor = qualityDifferenceCalculator1;
-      qualityDifferenceCalculator1.Successor = visualizer1;
-      visualizer1.Successor = resultsCollector;
-      resultsCollector.Successor = mainProcessor;
+      variableCreator.Successor = resultsCollector1;
+      resultsCollector1.Successor = uniformSubScopesProcessor0;
+      uniformSubScopesProcessor0.Operator = analyzer1;
+      uniformSubScopesProcessor0.Successor = mainProcessor;
+      analyzer1.Successor = null;
       mainProcessor.Operator = moveGenerator;
       mainProcessor.Successor = iterationsCounter;
       moveGenerator.Successor = moveEvaluationProcessor;
       moveEvaluationProcessor.Operator = moveEvaluator;
-      moveEvaluationProcessor.Successor = bestSelector;
+      moveEvaluationProcessor.Successor = moveAnalyzer;
+      moveAnalyzer.Successor = bestSelector;
       bestSelector.Successor = rightReducer;
       rightReducer.Successor = moveMakingProcessor;
@@ -253,10 +214,9 @@
       moveMaker.Successor = null;
       iterationsCounter.Successor = iterationsComparator;
-      iterationsComparator.Successor = bestQualityMemorizer3;
-      bestQualityMemorizer3.Successor = bestQualityMemorizer4;
-      bestQualityMemorizer4.Successor = dataTableValuesCollector2;
-      dataTableValuesCollector2.Successor = qualityDifferenceCalculator2;
-      qualityDifferenceCalculator2.Successor = visualizer2;
-      visualizer2.Successor = iterationsTermination;
+      iterationsComparator.Successor = resultsCollector2;
+      resultsCollector2.Successor = uniformSubScopesProcessor1;
+      uniformSubScopesProcessor1.Operator = analyzer2;
+      uniformSubScopesProcessor1.Successor = iterationsTermination;
+      analyzer2.Successor = null;
       iterationsTermination.TrueBranch = null;
       iterationsTermination.FalseBranch = mainProcessor;
