Index: trunk/sources/HeuristicLab.Analysis/3.3/AlleleFrequencyAnalysis/AlleleFrequencyAnalyzer.cs
===================================================================
--- trunk/sources/HeuristicLab.Analysis/3.3/AlleleFrequencyAnalysis/AlleleFrequencyAnalyzer.cs	(revision 8282)
+++ trunk/sources/HeuristicLab.Analysis/3.3/AlleleFrequencyAnalysis/AlleleFrequencyAnalyzer.cs	(revision 8283)
@@ -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)));
@@ -159,4 +168,39 @@
         } else {
           results = (ResultCollection)ResultsParameter.ActualValue[Name + " Results"].Value;
+        }
+
+        // calculate scatter plot of contained relevant alleles and relative quality
+        double avgContainedReleventAlleles = 0;
+        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));
+          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);
+          }
         }
 
@@ -205,4 +249,8 @@
           allelesTable.Rows["Lost Alleles of Best Known Solution"].VisualProperties.SecondYAxis = true;
           allelesTable.Rows["Lost Alleles of Best Known Solution"].VisualProperties.StartIndexZero = true;
+
+          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;
 
           results.Add(new Result("Alleles", allelesTable));
@@ -222,4 +270,5 @@
         allelesTable.Rows["Fixed Alleles of Best Known Solution"].Values.Add(fixedRelevantAllelesCount);
         allelesTable.Rows["Lost Alleles of Best Known Solution"].Values.Add(lostRelevantAllelesCount);
+        allelesTable.Rows["Average Contained Alleles of Best Known Solution"].Values.Add(avgContainedReleventAlleles);
 
         // store alleles values
