Index: branches/HeuristicLab.Analysis.AlgorithmBehavior/HeuristicLab.Analysis.AlgorithmBehavior.Analyzers/3.3/DuplicateSolutionsAnalyzer.cs
===================================================================
--- branches/HeuristicLab.Analysis.AlgorithmBehavior/HeuristicLab.Analysis.AlgorithmBehavior.Analyzers/3.3/DuplicateSolutionsAnalyzer.cs	(revision 8415)
+++ branches/HeuristicLab.Analysis.AlgorithmBehavior/HeuristicLab.Analysis.AlgorithmBehavior.Analyzers/3.3/DuplicateSolutionsAnalyzer.cs	(revision 8415)
@@ -0,0 +1,99 @@
+﻿#region License Information
+/* HeuristicLab
+ * Copyright (C) 2002-2012 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.Operators;
+using HeuristicLab.Optimization;
+using HeuristicLab.Optimization.Operators;
+using HeuristicLab.Parameters;
+using HeuristicLab.Persistence.Default.CompositeSerializers.Storable;
+using HeuristicLab.Problems.TravelingSalesman;
+
+namespace HeuristicLab.Analysis.AlgorithmBehavior.Analyzers {
+  [Item("DuplicateSolutionsAnalyzer", "An operator that analyzes duplicate solutions in the population.")]
+  [StorableClass]
+  public class DuplicateSolutionsAnalyzer : SingleSuccessorOperator, IAnalyzer {
+    private const string ResultsParameterName = "Results";
+
+    #region IAnalyzer Members
+    public bool EnabledByDefault {
+      get { return false; }
+    }
+    #endregion
+
+    #region Parameter properties
+    public ILookupParameter<ResultCollection> ResultsParameter {
+      get { return (ILookupParameter<ResultCollection>)Parameters[ResultsParameterName]; }
+    }
+    public IValueParameter<SingleObjectiveSolutionSimilarityCalculator> SimilarityCalculatorParameter {
+      get { return (IValueParameter<SingleObjectiveSolutionSimilarityCalculator>)Parameters["SimilarityCalculator"]; }
+    }
+    #endregion
+
+    #region Properties
+    public ResultCollection Results {
+      get { return ResultsParameter.ActualValue; }
+    }
+
+    private DataRow dtRow;
+    #endregion
+
+    [StorableConstructor]
+    private DuplicateSolutionsAnalyzer(bool deserializing) : base(deserializing) { }
+    private DuplicateSolutionsAnalyzer(DuplicateSolutionsAnalyzer original, Cloner cloner) : base(original, cloner) { }
+    public DuplicateSolutionsAnalyzer()
+      : base() {
+      Parameters.Add(new LookupParameter<ResultCollection>(ResultsParameterName, "The results collection where the analysis values should be stored."));
+      Parameters.Add(new ValueParameter<SingleObjectiveSolutionSimilarityCalculator>("SimilarityCalculator", new TSPSimilarityCalculator()));
+      SimilarityCalculatorParameter.Value.SolutionVariableName = "TSPTour";
+      SimilarityCalculatorParameter.Value.QualityVariableName = "TSPTourLength";
+    }
+
+    public override IDeepCloneable Clone(Cloner cloner) {
+      return new DuplicateSolutionsAnalyzer(this, cloner);
+    }
+
+    public override IOperation Apply() {
+      if (!Results.ContainsKey("Duplicate Solutions")) {
+        DataTable dt = new DataTable("Duplicate Solutions");
+        dtRow = new DataRow("Duplicate Solutions per Generation");
+        dt.Rows.Add(dtRow);
+        Results.Add(new Result("Duplicate Solutions", dt));
+      }
+
+      var similarities = SimilarityCalculatorParameter.Value.CalculateSolutionCrowdSimilarity(ExecutionContext.Scope);
+      int counter = 0;
+      for (int i = 0; i < similarities.Length; i++) {
+        for (int j = 0; j < similarities[i].Length; j++) {
+          if (similarities[i][j] == 1.0 && i != j) {
+            counter++;
+            break;
+          }
+        }
+      }
+      dtRow.Values.Add(counter);
+
+      return base.Apply();
+    }
+  }
+}
Index: branches/HeuristicLab.Analysis.AlgorithmBehavior/HeuristicLab.Analysis.AlgorithmBehavior.Analyzers/3.3/HeuristicLab.Analysis.AlgorithmBehavior.Analyzers-3.3.csproj
===================================================================
--- branches/HeuristicLab.Analysis.AlgorithmBehavior/HeuristicLab.Analysis.AlgorithmBehavior.Analyzers/3.3/HeuristicLab.Analysis.AlgorithmBehavior.Analyzers-3.3.csproj	(revision 8411)
+++ branches/HeuristicLab.Analysis.AlgorithmBehavior/HeuristicLab.Analysis.AlgorithmBehavior.Analyzers/3.3/HeuristicLab.Analysis.AlgorithmBehavior.Analyzers-3.3.csproj	(revision 8415)
@@ -98,4 +98,5 @@
   </ItemGroup>
   <ItemGroup>
+    <Compile Include="DuplicateSolutionsAnalyzer.cs" />
     <Compile Include="MutationPerformanceAnalyzer.cs" />
     <Compile Include="CrossoverPerformanceAnalyzer.cs" />
Index: branches/HeuristicLab.Analysis.AlgorithmBehavior/HeuristicLab.Analysis.AlgorithmBehavior.Analyzers/3.3/MutationPerformanceAnalyzer.cs
===================================================================
--- branches/HeuristicLab.Analysis.AlgorithmBehavior/HeuristicLab.Analysis.AlgorithmBehavior.Analyzers/3.3/MutationPerformanceAnalyzer.cs	(revision 8411)
+++ branches/HeuristicLab.Analysis.AlgorithmBehavior/HeuristicLab.Analysis.AlgorithmBehavior.Analyzers/3.3/MutationPerformanceAnalyzer.cs	(revision 8415)
@@ -125,5 +125,5 @@
         cnt = 0;
 
-        DataTable dt = new DataTable("Average Mutatioin Performance");
+        DataTable dt = new DataTable("Average Mutation Performance");
         dtRow = new DataRow("Average Mutation Performance per Generation");
         dt.Rows.Add(dtRow);
