Index: branches/GP.Grammar.Editor/HeuristicLab.Analysis/3.3/DataVisualization/DataRowVisualProperties.cs
===================================================================
--- branches/GP.Grammar.Editor/HeuristicLab.Analysis/3.3/DataVisualization/DataRowVisualProperties.cs	(revision 6284)
+++ branches/GP.Grammar.Editor/HeuristicLab.Analysis/3.3/DataVisualization/DataRowVisualProperties.cs	(revision 6377)
@@ -36,5 +36,16 @@
       Columns,
       Points,
-      Bars
+      Bars,
+      Histogram
+    }
+    #endregion
+    #region LineStyle
+    public enum DataRowLineStyle {
+      Dash,
+      DashDot,
+      DashDotDot,
+      Dot,
+      NotSet,
+      Solid
     }
     #endregion
@@ -60,4 +71,14 @@
       }
     }
+    private bool secondXAxis;
+    public bool SecondXAxis {
+      get { return secondXAxis; }
+      set {
+        if (secondXAxis != value) {
+          secondXAxis = value;
+          OnPropertyChanged("SecondXAxis");
+        }
+      }
+    }
     private Color color;
     public Color Color {
@@ -70,4 +91,14 @@
       }
     }
+    private DataRowLineStyle lineStyle;
+    public DataRowLineStyle LineStyle {
+      get { return lineStyle; }
+      set {
+        if (lineStyle != value) {
+          lineStyle = value;
+          OnPropertyChanged("LineStyle");
+        }
+      }
+    }
     private bool startIndexZero;
     public bool StartIndexZero {
@@ -77,4 +108,34 @@
           startIndexZero = value;
           OnPropertyChanged("StartIndexZero");
+        }
+      }
+    }
+    private int lineWidth;
+    public int LineWidth {
+      get { return lineWidth; }
+      set {
+        if (lineWidth != value) {
+          lineWidth = value;
+          OnPropertyChanged("LineWidth");
+        }
+      }
+    }
+    private int bins;
+    public int Bins {
+      get { return bins; }
+      set {
+        if (bins != value) {
+          bins = value;
+          OnPropertyChanged("Bins");
+        }
+      }
+    }
+    private bool exactBins;
+    public bool ExactBins {
+      get { return exactBins; }
+      set {
+        if (exactBins != value) {
+          exactBins = value;
+          OnPropertyChanged("ExactBins");
         }
       }
@@ -92,4 +153,9 @@
       set { secondYAxis = value; }
     }
+    [Storable(Name = "SecondXAxis")]
+    private bool StorableSecondXAxis {
+      get { return secondXAxis; }
+      set { secondXAxis = value; }
+    }
     [Storable(Name = "Color")]
     private Color StorableColor {
@@ -97,8 +163,28 @@
       set { color = value; }
     }
+    [Storable(Name = "LineStyle")]
+    private DataRowLineStyle StorableLineStyle {
+      get { return lineStyle; }
+      set { lineStyle = value; }
+    }
     [Storable(Name = "StartIndexZero")]
     private bool StorableStartIndexZero {
       get { return startIndexZero; }
       set { startIndexZero = value; }
+    }
+    [Storable(Name = "LineWidth")]
+    private int StorableLineWidth {
+      get { return lineWidth; }
+      set { lineWidth = value; }
+    }
+    [Storable(Name = "Bins")]
+    private int StorableBins {
+      get { return bins; }
+      set { bins = value; }
+    }
+    [Storable(Name = "ExactBins")]
+    private bool StorableExactBins {
+      get { return exactBins; }
+      set { exactBins = value; }
     }
     #endregion
@@ -110,12 +196,22 @@
       this.chartType = original.chartType;
       this.secondYAxis = original.secondYAxis;
+      this.secondXAxis = original.secondXAxis;
       this.color = original.color;
+      this.lineStyle = original.lineStyle;
       this.startIndexZero = original.startIndexZero;
+      this.lineWidth = original.lineWidth;
+      this.bins = original.bins;
+      this.exactBins = original.exactBins;
     }
     public DataRowVisualProperties() {
       chartType = DataRowChartType.Line;
       secondYAxis = false;
+      secondXAxis = false;
       color = Color.Empty;
+      lineStyle = DataRowLineStyle.Solid;
       startIndexZero = false;
+      lineWidth = 1;
+      bins = 10;
+      exactBins = false;
     }
 
Index: branches/GP.Grammar.Editor/HeuristicLab.Analysis/3.3/DataVisualization/DataTableVisualProperties.cs
===================================================================
--- branches/GP.Grammar.Editor/HeuristicLab.Analysis/3.3/DataVisualization/DataTableVisualProperties.cs	(revision 6284)
+++ branches/GP.Grammar.Editor/HeuristicLab.Analysis/3.3/DataVisualization/DataTableVisualProperties.cs	(revision 6377)
@@ -21,4 +21,5 @@
 
 using System.ComponentModel;
+using System.Drawing;
 using HeuristicLab.Common;
 using HeuristicLab.Persistence.Default.CompositeSerializers.Storable;
@@ -30,4 +31,46 @@
   [StorableClass]
   public class DataTableVisualProperties : DeepCloneable, INotifyPropertyChanged {
+    private Font titleFont;
+    public Font TitleFont {
+      get { return titleFont; }
+      set {
+        if (titleFont == null || value == null
+          || titleFont.Name != value.Name || titleFont.Size != value.Size || titleFont.Style != value.Style) {
+          titleFont = value;
+          OnPropertyChanged("TitleFont");
+        }
+      }
+    }
+    private Color titleColor;
+    public Color TitleColor {
+      get { return titleColor; }
+      set {
+        if (titleColor != value) {
+          titleColor = value;
+          OnPropertyChanged("TitleFontColor");
+        }
+      }
+    }
+    private Font axisTitleFont;
+    public Font AxisTitleFont {
+      get { return axisTitleFont; }
+      set {
+        if (axisTitleFont == null || axisTitleFont == null
+          || axisTitleFont.Name != value.Name || axisTitleFont.Size != value.Size || axisTitleFont.Style != value.Style) {
+          axisTitleFont = value;
+          OnPropertyChanged("AxisTitleFont");
+        }
+      }
+    }
+    private Color axisTitleColor;
+    public Color AxisTitleColor {
+      get { return axisTitleColor; }
+      set {
+        if (axisTitleColor != value) {
+          axisTitleColor = value;
+          OnPropertyChanged("AxisTitleColor");
+        }
+      }
+    }
     private string xAxisTitle;
     public string XAxisTitle {
@@ -54,4 +97,16 @@
     }
 
+    private string secondXAxisTitle;
+    public string SecondXAxisTitle {
+      get { return secondXAxisTitle; }
+      set {
+        if (value == null) value = string.Empty;
+        if (secondXAxisTitle != value) {
+          secondXAxisTitle = value;
+          OnPropertyChanged("SecondXAxisTitle");
+        }
+      }
+    }
+
     private string secondYAxisTitle;
     public string SecondYAxisTitle {
@@ -66,5 +121,209 @@
     }
 
+    private bool xAxisMinimumAuto;
+    public bool XAxisMinimumAuto {
+      get { return xAxisMinimumAuto; }
+      set {
+        if (xAxisMinimumAuto != value) {
+          xAxisMinimumAuto = value;
+          if (value) xAxisMinimumFixedValue = double.NaN;
+          OnPropertyChanged("XAxisMinimumAuto");
+        }
+      }
+    }
+
+    private bool xAxisMaximumAuto;
+    public bool XAxisMaximumAuto {
+      get { return xAxisMaximumAuto; }
+      set {
+        if (xAxisMaximumAuto != value) {
+          xAxisMaximumAuto = value;
+          if (value) xAxisMaximumFixedValue = double.NaN;
+          OnPropertyChanged("XAxisMaximumAuto");
+        }
+      }
+    }
+
+    private double xAxisMinimumFixedValue;
+    public double XAxisMinimumFixedValue {
+      get { return xAxisMinimumFixedValue; }
+      set {
+        if (xAxisMinimumFixedValue != value) {
+          xAxisMinimumFixedValue = value;
+          OnPropertyChanged("XAxisMinimumFixedValue");
+        }
+      }
+    }
+
+    private double xAxisMaximumFixedValue;
+    public double XAxisMaximumFixedValue {
+      get { return xAxisMaximumFixedValue; }
+      set {
+        if (xAxisMaximumFixedValue != value) {
+          xAxisMaximumFixedValue = value;
+          OnPropertyChanged("XAxisMaximumFixedValue");
+        }
+      }
+    }
+
+    private bool secondXAxisMinimumAuto;
+    public bool SecondXAxisMinimumAuto {
+      get { return secondXAxisMinimumAuto; }
+      set {
+        if (secondXAxisMinimumAuto != value) {
+          secondXAxisMinimumAuto = value;
+          if (value) secondXAxisMinimumFixedValue = double.NaN;
+          OnPropertyChanged("SecondXAxisMinimumAuto");
+        }
+      }
+    }
+
+    private bool secondXAxisMaximumAuto;
+    public bool SecondXAxisMaximumAuto {
+      get { return secondXAxisMaximumAuto; }
+      set {
+        if (secondXAxisMaximumAuto != value) {
+          secondXAxisMaximumAuto = value;
+          if (value) secondXAxisMaximumFixedValue = double.NaN;
+          OnPropertyChanged("SecondXAxisMaximumAuto");
+        }
+      }
+    }
+
+    private double secondXAxisMinimumFixedValue;
+    public double SecondXAxisMinimumFixedValue {
+      get { return secondXAxisMinimumFixedValue; }
+      set {
+        if (secondXAxisMinimumFixedValue != value) {
+          secondXAxisMinimumFixedValue = value;
+          OnPropertyChanged("SecondXAxisMinimumFixedValue");
+        }
+      }
+    }
+
+    private double secondXAxisMaximumFixedValue;
+    public double SecondXAxisMaximumFixedValue {
+      get { return secondXAxisMaximumFixedValue; }
+      set {
+        if (secondXAxisMaximumFixedValue != value) {
+          secondXAxisMaximumFixedValue = value;
+          OnPropertyChanged("SecondXAxisMaximumFixedValue");
+        }
+      }
+    }
+
+    private bool yAxisMinimumAuto;
+    public bool YAxisMinimumAuto {
+      get { return yAxisMinimumAuto; }
+      set {
+        if (yAxisMinimumAuto != value) {
+          yAxisMinimumAuto = value;
+          if (value) yAxisMinimumFixedValue = double.NaN;
+          OnPropertyChanged("YAxisMinimumAuto");
+        }
+      }
+    }
+
+    private bool yAxisMaximumAuto;
+    public bool YAxisMaximumAuto {
+      get { return yAxisMaximumAuto; }
+      set {
+        if (yAxisMaximumAuto != value) {
+          yAxisMaximumAuto = value;
+          if (value) yAxisMaximumFixedValue = double.NaN;
+          OnPropertyChanged("YAxisMaximumAuto");
+        }
+      }
+    }
+
+    private double yAxisMinimumFixedValue;
+    public double YAxisMinimumFixedValue {
+      get { return yAxisMinimumFixedValue; }
+      set {
+        if (yAxisMinimumFixedValue != value) {
+          yAxisMinimumFixedValue = value;
+          OnPropertyChanged("YAxisMinimumFixedValue");
+        }
+      }
+    }
+
+    private double yAxisMaximumFixedValue;
+    public double YAxisMaximumFixedValue {
+      get { return yAxisMaximumFixedValue; }
+      set {
+        if (yAxisMaximumFixedValue != value) {
+          yAxisMaximumFixedValue = value;
+          OnPropertyChanged("YAxisMaximumFixedValue");
+        }
+      }
+    }
+
+    private bool secondYAxisMinimumAuto;
+    public bool SecondYAxisMinimumAuto {
+      get { return secondYAxisMinimumAuto; }
+      set {
+        if (secondYAxisMinimumAuto != value) {
+          secondYAxisMinimumAuto = value;
+          if (value) secondYAxisMinimumFixedValue = double.NaN;
+          OnPropertyChanged("SecondYAxisMinimumAuto");
+        }
+      }
+    }
+
+    private bool secondYAxisMaximumAuto;
+    public bool SecondYAxisMaximumAuto {
+      get { return secondYAxisMaximumAuto; }
+      set {
+        if (secondYAxisMaximumAuto != value) {
+          secondYAxisMaximumAuto = value;
+          if (value) secondYAxisMaximumFixedValue = double.NaN;
+          OnPropertyChanged("SecondYAxisMaximumAuto");
+        }
+      }
+    }
+
+    private double secondYAxisMinimumFixedValue;
+    public double SecondYAxisMinimumFixedValue {
+      get { return secondYAxisMinimumFixedValue; }
+      set {
+        if (secondYAxisMinimumFixedValue != value) {
+          secondYAxisMinimumFixedValue = value;
+          OnPropertyChanged("SecondYAxisMinimumFixedValue");
+        }
+      }
+    }
+
+    private double secondYAxisMaximumFixedValue;
+    public double SecondYAxisMaximumFixedValue {
+      get { return secondYAxisMaximumFixedValue; }
+      set {
+        if (secondYAxisMaximumFixedValue != value) {
+          secondYAxisMaximumFixedValue = value;
+          OnPropertyChanged("SecondYAxisMaximumFixedValue");
+        }
+      }
+    }
+
     #region Persistence Properties
+    [Storable(Name = "TitleFont")]
+    private Font StorableTitleFont {
+      get { return titleFont; }
+      set { titleFont = value; }
+    }
+    [Storable(Name = "TitleColor")]
+    private Color StorableTitleColor {
+      get { return titleColor; }
+      set { titleColor = value; }
+    }
+    [Storable(Name = "AxisTitleFont")]
+    private Font StorableAxisTitleFont {
+      get { return axisTitleFont; }
+      set { axisTitleFont = value; }
+    }
+    [Storable(Name = "AxisTitleColor")]
+    private Color StorableAxisTitleColor {
+      get { return axisTitleColor; }
+      set { axisTitleColor = value; }
+    }
     [Storable(Name = "XAxisTitle")]
     private string StorableXAxisTitle {
@@ -77,4 +336,9 @@
       set { yAxisTitle = value; }
     }
+    [Storable(Name = "SecondXAxisTitle")]
+    private string StorableSecondXAxisTitle {
+      get { return secondXAxisTitle; }
+      set { secondXAxisTitle = value; }
+    }
     [Storable(Name = "SecondYAxisTitle")]
     private string StorableSecondYAxisTitle {
@@ -82,4 +346,84 @@
       set { secondYAxisTitle = value; }
     }
+    [Storable(Name = "XAxisMinimumAuto")]
+    private bool StorableXAxisMinimumAuto {
+      get { return xAxisMinimumAuto; }
+      set { xAxisMinimumAuto = value; }
+    }
+    [Storable(Name = "XAxisMaximumAuto")]
+    private bool StorableXAxisMaximumAuto {
+      get { return xAxisMaximumAuto; }
+      set { xAxisMaximumAuto = value; }
+    }
+    [Storable(Name = "XAxisMinimumFixedValue")]
+    private double StorableXAxisMinimumFixedValue {
+      get { return xAxisMinimumFixedValue; }
+      set { xAxisMinimumFixedValue = value; }
+    }
+    [Storable(Name = "XAxisMaximumFixedValue")]
+    private double StorableXAxisMaximumFixedValue {
+      get { return xAxisMaximumFixedValue; }
+      set { xAxisMaximumFixedValue = value; }
+    }
+    [Storable(Name = "SecondXAxisMinimumAuto")]
+    private bool StorableSecondXAxisMinimumAuto {
+      get { return secondXAxisMinimumAuto; }
+      set { secondXAxisMinimumAuto = value; }
+    }
+    [Storable(Name = "SecondXAxisMaximumAuto")]
+    private bool StorableSecondXAxisMaximumAuto {
+      get { return secondXAxisMaximumAuto; }
+      set { secondXAxisMaximumAuto = value; }
+    }
+    [Storable(Name = "SecondXAxisMinimumFixedValue")]
+    private double StorableSecondXAxisMinimumFixedValue {
+      get { return secondXAxisMinimumFixedValue; }
+      set { secondXAxisMinimumFixedValue = value; }
+    }
+    [Storable(Name = "SecondXAxisMaximumFixedValue")]
+    private double StorableSecondXAxisMaximumFixedValue {
+      get { return secondXAxisMaximumFixedValue; }
+      set { secondXAxisMaximumFixedValue = value; }
+    }
+    [Storable(Name = "YAxisMinimumAuto")]
+    private bool StorableYAxisMinimumAuto {
+      get { return yAxisMinimumAuto; }
+      set { yAxisMinimumAuto = value; }
+    }
+    [Storable(Name = "YAxisMaximumAuto")]
+    private bool StorableYAxisMaximumAuto {
+      get { return yAxisMaximumAuto; }
+      set { yAxisMaximumAuto = value; }
+    }
+    [Storable(Name = "YAxisMinimumFixedValue")]
+    private double StorableYAxisMinimumFixedValue {
+      get { return yAxisMinimumFixedValue; }
+      set { yAxisMinimumFixedValue = value; }
+    }
+    [Storable(Name = "YAxisMaximumFixedValue")]
+    private double StorableYAxisMaximumFixedValue {
+      get { return yAxisMaximumFixedValue; }
+      set { yAxisMaximumFixedValue = value; }
+    }
+    [Storable(Name = "SecondYAxisMinimumAuto")]
+    private bool StorableSecondYAxisMinimumAuto {
+      get { return secondYAxisMinimumAuto; }
+      set { secondYAxisMinimumAuto = value; }
+    }
+    [Storable(Name = "SecondYAxisMaximumAuto")]
+    private bool StorableSecondYAxisMaximumAuto {
+      get { return secondYAxisMaximumAuto; }
+      set { secondYAxisMaximumAuto = value; }
+    }
+    [Storable(Name = "SecondYAxisMinimumFixedValue")]
+    private double StorableSecondYAxisMinimumFixedValue {
+      get { return secondYAxisMinimumFixedValue; }
+      set { secondYAxisMinimumFixedValue = value; }
+    }
+    [Storable(Name = "SecondYAxisMaximumFixedValue")]
+    private double StorableSecondYAxisMaximumFixedValue {
+      get { return secondYAxisMaximumFixedValue; }
+      set { secondYAxisMaximumFixedValue = value; }
+    }
     #endregion
 
@@ -88,12 +432,52 @@
     protected DataTableVisualProperties(DataTableVisualProperties original, Cloner cloner)
       : base(original, cloner) {
+      if (original.titleFont != null)
+        this.titleFont = (Font)original.titleFont.Clone();
+      if (original.axisTitleFont != null)
+        this.axisTitleFont = (Font)original.axisTitleFont.Clone();
       this.xAxisTitle = original.xAxisTitle;
       this.yAxisTitle = original.yAxisTitle;
+      this.secondXAxisTitle = original.secondXAxisTitle;
       this.secondYAxisTitle = original.secondYAxisTitle;
+      this.xAxisMinimumAuto = original.xAxisMinimumAuto;
+      this.xAxisMinimumFixedValue = original.xAxisMinimumFixedValue;
+      this.xAxisMaximumAuto = original.xAxisMaximumAuto;
+      this.xAxisMaximumFixedValue = original.xAxisMaximumFixedValue;
+      this.secondXAxisMinimumAuto = original.secondXAxisMinimumAuto;
+      this.secondXAxisMinimumFixedValue = original.secondXAxisMinimumFixedValue;
+      this.secondXAxisMaximumAuto = original.secondXAxisMaximumAuto;
+      this.secondXAxisMaximumFixedValue = original.secondXAxisMaximumFixedValue;
+      this.yAxisMinimumAuto = original.yAxisMinimumAuto;
+      this.yAxisMinimumFixedValue = original.yAxisMinimumFixedValue;
+      this.yAxisMaximumAuto = original.yAxisMaximumAuto;
+      this.yAxisMaximumFixedValue = original.yAxisMaximumFixedValue;
+      this.secondYAxisMinimumAuto = original.secondYAxisMinimumAuto;
+      this.secondYAxisMinimumFixedValue = original.secondYAxisMinimumFixedValue;
+      this.secondYAxisMaximumAuto = original.secondYAxisMaximumAuto;
+      this.secondYAxisMaximumFixedValue = original.secondYAxisMaximumFixedValue;
     }
     public DataTableVisualProperties() {
+      titleColor = Color.Black;
+      axisTitleColor = Color.Black;
       this.xAxisTitle = string.Empty;
       this.yAxisTitle = string.Empty;
+      this.secondXAxisTitle = string.Empty;
       this.secondYAxisTitle = string.Empty;
+      this.xAxisMinimumAuto = true;
+      this.xAxisMinimumFixedValue = double.NaN;
+      this.xAxisMaximumAuto = true;
+      this.xAxisMaximumFixedValue = double.NaN;
+      this.secondXAxisMinimumAuto = true;
+      this.secondXAxisMinimumFixedValue = double.NaN;
+      this.secondXAxisMaximumAuto = true;
+      this.secondXAxisMaximumFixedValue = double.NaN;
+      this.yAxisMinimumAuto = true;
+      this.yAxisMinimumFixedValue = double.NaN;
+      this.yAxisMaximumAuto = true;
+      this.yAxisMaximumFixedValue = double.NaN;
+      this.secondYAxisMinimumAuto = true;
+      this.secondYAxisMinimumFixedValue = double.NaN;
+      this.secondYAxisMaximumAuto = true;
+      this.secondYAxisMaximumFixedValue = double.NaN;
     }
 
Index: branches/GP.Grammar.Editor/HeuristicLab.Analysis/3.3/HeuristicLab.Analysis-3.3.csproj
===================================================================
--- branches/GP.Grammar.Editor/HeuristicLab.Analysis/3.3/HeuristicLab.Analysis-3.3.csproj	(revision 6284)
+++ branches/GP.Grammar.Editor/HeuristicLab.Analysis/3.3/HeuristicLab.Analysis-3.3.csproj	(revision 6377)
@@ -138,4 +138,5 @@
     <Compile Include="HeuristicLabAnalysisPlugin.cs" />
     <Compile Include="Properties\AssemblyInfo.cs" />
+    <Compile Include="QualityAnalysis\QualityDistributionAnalyzer.cs" />
     <Compile Include="ValueAnalysis\MinAverageMaxValueAnalyzer.cs" />
     <Compile Include="ValueAnalysis\MinAverageMaxValueCalculator.cs" />
Index: branches/GP.Grammar.Editor/HeuristicLab.Analysis/3.3/MultidimensionalScaling/MultidimensionalScaling.cs
===================================================================
--- branches/GP.Grammar.Editor/HeuristicLab.Analysis/3.3/MultidimensionalScaling/MultidimensionalScaling.cs	(revision 6284)
+++ branches/GP.Grammar.Editor/HeuristicLab.Analysis/3.3/MultidimensionalScaling/MultidimensionalScaling.cs	(revision 6377)
@@ -68,5 +68,5 @@
     /// In every iteration it tries to find the best location for every item.</param>
     /// <returns>A Nx2 matrix where the first column represents the x- and the second column the y coordinates.</returns>
-    public static DoubleMatrix KruskalShepard(DoubleMatrix dissimilarities, DoubleMatrix coordinates, int maximumIterations = 20) {
+    public static DoubleMatrix KruskalShepard(DoubleMatrix dissimilarities, DoubleMatrix coordinates, int maximumIterations = 10) {
       int dimension = dissimilarities.Rows;
       if (dimension != dissimilarities.Columns || coordinates.Rows != dimension) throw new ArgumentException("The number of coordinates and the number of rows and columns in the dissimilarities matrix do not match.");
@@ -75,8 +75,8 @@
       double epsf = 0;
       double epsx = 0;
-      int maxits = 100;
-      alglib.mincgstate state = null;
-      alglib.mincgreport rep;
+      int maxits = 0;
 
+      alglib.minlmstate state;
+      alglib.minlmreport rep;
       for (int iterations = 0; iterations < maximumIterations; iterations++) {
         bool changed = false;
@@ -85,12 +85,8 @@
 
           try {
-            if ((iterations == 0 && i == 0)) {
-              alglib.mincgcreate(c, out state);
-              alglib.mincgsetcond(state, epsg, epsf, epsx, maxits);
-            } else {
-              alglib.mincgrestartfrom(state, c);
-            }
-            alglib.mincgoptimize(state, StressGradient, null, new Info(coordinates, dissimilarities, i));
-            alglib.mincgresults(state, out c, out rep);
+            alglib.minlmcreatevj(dimension - 1, c, out state);
+            alglib.minlmsetcond(state, epsg, epsf, epsx, maxits);
+            alglib.minlmoptimize(state, StressFitness, StressJacobian, null, new Info(coordinates, dissimilarities, i));
+            alglib.minlmresults(state, out c, out rep);
           } catch (alglib.alglibexception) { }
           if (!double.IsNaN(c[0]) && !double.IsNaN(c[1])) {
@@ -105,16 +101,26 @@
     }
 
-    // computes the function and the gradient of the raw stress function.
-    private static void StressGradient(double[] x, ref double func, double[] grad, object obj) {
-      func = 0; grad[0] = 0; grad[1] = 0;
+    private static void StressFitness(double[] x, double[] fi, object obj) {
       Info info = (obj as Info);
       for (int i = 0; i < info.Coordinates.Rows; i++) {
-        double c = info.Dissimilarities[info.Row, i];
+        double f = Stress(x, info.Dissimilarities[info.Row, i], info.Coordinates[i, 0], info.Coordinates[i, 1]);
+        if (i < info.Row) fi[i] = f;
+        else if (i > info.Row) fi[i - 1] = f;
+      }
+    }
+
+    private static void StressJacobian(double[] x, double[] fi, double[,] jac, object obj) {
+      Info info = (obj as Info);
+      int idx = 0;
+      for (int i = 0; i < info.Coordinates.Rows; i++) {
         if (i != info.Row) {
+          double c = info.Dissimilarities[info.Row, i];
           double a = info.Coordinates[i, 0];
           double b = info.Coordinates[i, 1];
-          func += Stress(x, c, a, b);
-          grad[0] += ((2 * x[0] - 2 * a) * Math.Sqrt(x[1] * x[1] - 2 * b * x[1] + x[0] * x[0] - 2 * a * x[0] + b * b + a * a) - 2 * c * x[0] + 2 * a * c) / Math.Sqrt(x[1] * x[1] - 2 * b * x[1] + x[0] * x[0] - 2 * a * x[0] + b * b + a * a);
-          grad[1] += ((2 * x[1] - 2 * b) * Math.Sqrt(x[1] * x[1] - 2 * b * x[1] + x[0] * x[0] - 2 * a * x[0] + b * b + a * a) - 2 * c * x[1] + 2 * b * c) / Math.Sqrt(x[1] * x[1] - 2 * b * x[1] + x[0] * x[0] - 2 * a * x[0] + b * b + a * a);
+          double f = Stress(x, c, a, b);
+          fi[idx] = f;
+          jac[idx, 0] = 2 * (x[0] - a) * (Math.Sqrt((a - x[0]) * (a - x[0]) + (b - x[1]) * (b - x[1])) - c) / Math.Sqrt((a - x[0]) * (a - x[0]) + (b - x[1]) * (b - x[1]));
+          jac[idx, 1] = 2 * (x[1] - b) * (Math.Sqrt((a - x[0]) * (a - x[0]) + (b - x[1]) * (b - x[1])) - c) / Math.Sqrt((a - x[0]) * (a - x[0]) + (b - x[1]) * (b - x[1]));
+          idx++;
         }
       }
Index: branches/GP.Grammar.Editor/HeuristicLab.Analysis/3.3/QualityAnalysis/QualityDistributionAnalyzer.cs
===================================================================
--- branches/GP.Grammar.Editor/HeuristicLab.Analysis/3.3/QualityAnalysis/QualityDistributionAnalyzer.cs	(revision 6377)
+++ branches/GP.Grammar.Editor/HeuristicLab.Analysis/3.3/QualityAnalysis/QualityDistributionAnalyzer.cs	(revision 6377)
@@ -0,0 +1,135 @@
+﻿#region License Information
+/* HeuristicLab
+ * Copyright (C) 2002-2011 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.Operators;
+using HeuristicLab.Optimization;
+using HeuristicLab.Parameters;
+using HeuristicLab.Persistence.Default.CompositeSerializers.Storable;
+
+namespace HeuristicLab.Analysis.QualityAnalysis {
+  [Item("QualityDistributionAnalyzer", "Analyzes the distribution of the quality values in that it adds a Histogram of them into the result collection.")]
+  [StorableClass]
+  public class QualityDistributionAnalyzer : SingleSuccessorOperator, IAnalyzer, IIterationBasedOperator {
+
+    #region Parameter properties
+    public IScopeTreeLookupParameter<DoubleValue> QualityParameter {
+      get { return (IScopeTreeLookupParameter<DoubleValue>)Parameters["Quality"]; }
+    }
+    public IValueLookupParameter<ResultCollection> ResultsParameter {
+      get { return (IValueLookupParameter<ResultCollection>)Parameters["Results"]; }
+    }
+    private ValueParameter<StringValue> HistogramNameParameter {
+      get { return (ValueParameter<StringValue>)Parameters["HistogramName"]; }
+    }
+    private ValueParameter<BoolValue> StoreHistoryParameter {
+      get { return (ValueParameter<BoolValue>)Parameters["StoreHistory"]; }
+    }
+    public ILookupParameter<IntValue> IterationsParameter {
+      get { return (ILookupParameter<IntValue>)Parameters["Iterations"]; }
+    }
+    public IValueLookupParameter<IntValue> MaximumIterationsParameter {
+      get { return (IValueLookupParameter<IntValue>)Parameters["MaximumIterations"]; }
+    }
+    #endregion
+
+    public string HistogramName {
+      get { return HistogramNameParameter.Value.Value; }
+      set { HistogramNameParameter.Value.Value = value; }
+    }
+
+    public bool StoreHistory {
+      get { return StoreHistoryParameter.Value.Value; }
+      set { StoreHistoryParameter.Value.Value = value; }
+    }
+
+    [StorableConstructor]
+    protected QualityDistributionAnalyzer(bool deserializing) : base(deserializing) { }
+    protected QualityDistributionAnalyzer(QualityDistributionAnalyzer original, Cloner cloner)
+      : base(original, cloner) {
+    }
+    public QualityDistributionAnalyzer()
+      : base() {
+      Parameters.Add(new ScopeTreeLookupParameter<DoubleValue>("Quality", "The value which represents the quality of a solution."));
+      Parameters.Add(new ValueLookupParameter<ResultCollection>("Results", "The results collection where the analysis values should be stored."));
+      Parameters.Add(new FixedValueParameter<StringValue>("HistogramName", "The name of the histogram that gets injected in to the results collection.", new StringValue("Quality Distribution")));
+      Parameters.Add(new FixedValueParameter<BoolValue>("StoreHistory", "True if the history should be stored in addition to the current distribution", new BoolValue(false)));
+      Parameters.Add(new LookupParameter<IntValue>("Iterations", "Optional: A value indicating the current iteration."));
+      Parameters.Add(new ValueLookupParameter<IntValue>("MaximumIterations", "Unused", new IntValue(-1)));
+
+      QualityParameter.Hidden = true;
+      ResultsParameter.Hidden = true;
+      IterationsParameter.Hidden = true;
+      MaximumIterationsParameter.Hidden = true;
+    }
+
+    public override IDeepCloneable Clone(Cloner cloner) {
+      return new QualityDistributionAnalyzer(this, cloner);
+    }
+
+    public override IOperation Apply() {
+      DataTable qualityDistribution = null;
+      ResultCollection results = ResultsParameter.ActualValue;
+      string description = "Shows the quality distributions in the current population.";
+      if (results.ContainsKey(HistogramName)) {
+        qualityDistribution = results[HistogramName].Value as DataTable;
+      } else {
+        qualityDistribution = new DataTable("Population Quality Distribution", description);
+        qualityDistribution.VisualProperties.XAxisTitle = QualityParameter.ActualName;
+        qualityDistribution.VisualProperties.YAxisTitle = "Frequency";
+        results.Add(new Result(HistogramName, description, qualityDistribution));
+      }
+      DataRow row;
+      if (!qualityDistribution.Rows.TryGetValue("QualityDistribution", out row)) {
+        row = new DataRow("QualityDistribution");
+        row.VisualProperties.ChartType = DataRowVisualProperties.DataRowChartType.Histogram;
+        qualityDistribution.Rows.Add(row);
+      }
+      var qualities = QualityParameter.ActualValue;
+      row.Values.Replace(qualities.Select(x => x.Value));
+
+      if (StoreHistory) {
+        string historyResultName = HistogramName + " History";
+        DataTableHistory qdHistory = null;
+        if (results.ContainsKey(historyResultName)) {
+          qdHistory = results[historyResultName].Value as DataTableHistory;
+        } else {
+          qdHistory = new DataTableHistory();
+          results.Add(new Result(historyResultName, qdHistory));
+        }
+        DataTable table = (DataTable)qualityDistribution.Clone();
+        IntValue iteration = IterationsParameter.ActualValue;
+        if (iteration != null) {
+          string iterationName = IterationsParameter.ActualName;
+          if (iterationName.EndsWith("s")) iterationName = iterationName.Remove(iterationName.Length - 1);
+          string appendix = " at " + iterationName + " " + iteration.Value.ToString();
+          table.Name += appendix;
+          table.Rows["QualityDistribution"].Name += appendix;
+        }
+        qdHistory.Add(table);
+      }
+      return base.Apply();
+    }
+  }
+}
Index: branches/GP.Grammar.Editor/HeuristicLab.Analysis/3.3/Tests/MultidimensionalScalingTest.cs
===================================================================
--- branches/GP.Grammar.Editor/HeuristicLab.Analysis/3.3/Tests/MultidimensionalScalingTest.cs	(revision 6284)
+++ branches/GP.Grammar.Editor/HeuristicLab.Analysis/3.3/Tests/MultidimensionalScalingTest.cs	(revision 6377)
@@ -21,4 +21,5 @@
 
 using System;
+using System.Globalization;
 using HeuristicLab.Data;
 using Microsoft.VisualStudio.TestTools.UnitTesting;
@@ -42,6 +43,9 @@
       distances3[0, 2] = distances3[2, 0] = 6.4;
       distances3[1, 2] = distances3[2, 1] = 5;
-      stress = MultidimensionalScaling.CalculateNormalizedStress(distances3,
-        MultidimensionalScaling.KruskalShepard(distances3));
+      DoubleMatrix coords3 = MultidimensionalScaling.KruskalShepard(distances3);
+      Console.WriteLine("Coordinates: ");
+      Console.WriteLine("A = ({0}, {1}), B = ({2}, {3}), C = ({4}, {5})", coords3[0, 0], coords3[0, 1], coords3[1, 0], coords3[1, 1], coords3[2, 0], coords3[2, 1]);
+      stress = MultidimensionalScaling.CalculateNormalizedStress(distances3, coords3);
+      Console.WriteLine("Stress = " + stress.ToString(CultureInfo.InvariantCulture.NumberFormat));
       Assert.IsTrue(stress < 0.1);
       DoubleMatrix distances4 = new DoubleMatrix(4, 4);
