Index: branches/OaaS/HeuristicLab.Analysis/3.3/AlleleFrequencyAnalysis/AlleleFrequencyAnalyzer.cs
===================================================================
--- branches/OaaS/HeuristicLab.Analysis/3.3/AlleleFrequencyAnalysis/AlleleFrequencyAnalyzer.cs	(revision 8228)
+++ branches/OaaS/HeuristicLab.Analysis/3.3/AlleleFrequencyAnalysis/AlleleFrequencyAnalyzer.cs	(revision 9363)
@@ -20,4 +20,5 @@
 #endregion
 
+using System;
 using System.Collections.Generic;
 using System.Linq;
@@ -88,5 +89,13 @@
     }
 
-    #region AlleleFrequencyIdEqualityComparer
+    #region Equality Comparers
+    private class AlleleIdEqualityComparer : IEqualityComparer<Allele> {
+      public bool Equals(Allele x, Allele y) {
+        return x.Id == y.Id;
+      }
+      public int GetHashCode(Allele obj) {
+        return obj.Id.GetHashCode();
+      }
+    }
     private class AlleleFrequencyIdEqualityComparer : IEqualityComparer<AlleleFrequency> {
       public bool Equals(AlleleFrequency x, AlleleFrequency y) {
@@ -112,5 +121,5 @@
         bool max = MaximizationParameter.ActualValue.Value;
         ItemArray<T> solutions = SolutionParameter.ActualValue;
-        ItemArray<DoubleValue> qualities = QualityParameter.ActualValue;
+        double[] qualities = QualityParameter.ActualValue.Select(x => x.Value).ToArray();
         T bestKnownSolution = BestKnownSolutionParameter.ActualValue;
         bool storeHistory = StoreHistoryParameter.Value.Value;
@@ -120,12 +129,12 @@
         if (!max) {
           bestIndex = qualities
-            .Select((x, index) => new { index, x.Value })
+            .Select((x, i) => new { Index = i, Value = x })
             .OrderBy(x => x.Value)
-            .First().index;
+            .First().Index;
         } else {
           bestIndex = qualities
-            .Select((x, index) => new { index, x.Value })
+            .Select((x, i) => new { Index = i, Value = x })
             .OrderByDescending(x => x.Value)
-            .First().index;
+            .First().Index;
         }
 
@@ -142,5 +151,5 @@
                                                           x.Count() / ((double)solutions.Length),
                                                           x.Average(a => a.Allele.Impact),
-                                                          x.Average(a => a.Quality.Value),
+                                                          x.Average(a => a.Quality),
                                                           bestKnownAlleles == null ? false : bestKnownAlleles.Any(a => a.Id == x.Key),
                                                           bestAlleles.Any(a => a.Id == x.Key)));
@@ -248,4 +257,51 @@
         else
           ((DoubleValue)results["Lost Alleles of Best Known Solution"].Value).Value = lostRelevantAllelesCount;
+
+        // calculate contained alleles of best known solution and relative quality
+        if (bestKnownAlleles != null) {
+          double qualityRange = Math.Abs(qualities.Max() - qualities.Min());
+          var points = solutions.Select((s, index) => new Point2D<double>(CalculateAlleles(s).Intersect(bestKnownAlleles, new AlleleIdEqualityComparer()).Count(),
+                                                                          Math.Abs(qualities[index] - qualities[bestIndex]) / qualityRange));
+          var avgContainedReleventAlleles = points.Select(x => x.X).Average();
+
+          var plot = new ScatterPlot("Contained Alleles of Best Known Solution and Relative Solution Qualtiy", null);
+          plot.VisualProperties.XAxisTitle = "Contained Alleles of Best Known Solution";
+          plot.VisualProperties.YAxisTitle = "Relative Solution Quality";
+          plot.VisualProperties.XAxisMinimumAuto = false;
+          plot.VisualProperties.XAxisMinimumFixedValue = 0.0;
+          plot.VisualProperties.XAxisMaximumAuto = false;
+          plot.VisualProperties.XAxisMaximumFixedValue = bestKnownAlleles.Length;
+          plot.VisualProperties.YAxisMinimumAuto = false;
+          plot.VisualProperties.YAxisMinimumFixedValue = 0.0;
+          plot.VisualProperties.YAxisMaximumAuto = false;
+          plot.VisualProperties.YAxisMaximumFixedValue = 1.0;
+          var row = new ScatterPlotDataRow("Solutions of Current Generation", null, points);
+          row.VisualProperties.PointStyle = ScatterPlotDataRowVisualProperties.ScatterPlotDataRowPointStyle.Circle;
+          row.VisualProperties.PointSize = 5;
+          plot.Rows.Add(row);
+
+          if (!results.ContainsKey("Scatter Plot"))
+            results.Add(new Result("Scatter Plot", plot));
+          else
+            results["Scatter Plot"].Value = plot;
+          if (storeHistory) {
+            if (!results.ContainsKey("Scatter Plot History")) {
+              results.Add(new Result("Scatter Plot History", new ScatterPlotHistory()));
+            }
+            ((ScatterPlotHistory)results["Scatter Plot History"].Value).Add(plot);
+          }
+
+          if (!allelesTable.Rows.ContainsKey("Average Contained Alleles of Best Known Solution")) {
+            allelesTable.Rows.Add(new DataRow("Average Contained Alleles of Best Known Solution", null));
+            allelesTable.Rows["Average Contained Alleles of Best Known Solution"].VisualProperties.SecondYAxis = true;
+            allelesTable.Rows["Average Contained Alleles of Best Known Solution"].VisualProperties.StartIndexZero = true;
+          }
+          allelesTable.Rows["Average Contained Alleles of Best Known Solution"].Values.Add(avgContainedReleventAlleles);
+
+          if (!results.ContainsKey("Average Contained Alleles of Best Known Solution"))
+            results.Add(new Result("Average Contained Alleles of Best Known Solution", new DoubleValue(avgContainedReleventAlleles)));
+          else
+            ((DoubleValue)results["Average Contained Alleles of Best Known Solution"].Value).Value = avgContainedReleventAlleles;
+        }
       }
       return base.Apply();
