Index: branches/symbreg-factors-2650/HeuristicLab 3.3.sln
===================================================================
--- branches/symbreg-factors-2650/HeuristicLab 3.3.sln	(revision 14497)
+++ branches/symbreg-factors-2650/HeuristicLab 3.3.sln	(revision 14498)
@@ -2,5 +2,5 @@
 Microsoft Visual Studio Solution File, Format Version 12.00
 # Visual Studio 14
-VisualStudioVersion = 14.0.23107.0
+VisualStudioVersion = 14.0.25420.1
 MinimumVisualStudioVersion = 10.0.40219.1
 Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution Items", "{96396439-A764-4022-A8D2-BE021449B8D1}"
@@ -420,5 +420,5 @@
 Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "HeuristicLab.Algorithms.CMAEvolutionStrategy-3.4", "HeuristicLab.Algorithms.CMAEvolutionStrategy\3.4\HeuristicLab.Algorithms.CMAEvolutionStrategy-3.4.csproj", "{291010E4-2F4E-4D29-A795-753CFF293FDB}"
 EndProject
-Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "HeuristicLab.Encodings.LinearLinkageEncoding-3.3", "HeuristicLab.Encodings.LinearLinkageEncoding\3.3\HeuristicLab.Encodings.LinearLinkageEncoding-3.3.csproj", "{BE698769-975A-429E-828C-72BB2B6182C8}"
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "HeuristicLab.Encodings.LinearLinkageEncoding-3.4", "HeuristicLab.Encodings.LinearLinkageEncoding\3.3\HeuristicLab.Encodings.LinearLinkageEncoding-3.4.csproj", "{BE698769-975A-429E-828C-72BB2B6182C8}"
 EndProject
 Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "HeuristicLab.Problems.Orienteering-3.3", "HeuristicLab.Problems.Orienteering\3.3\HeuristicLab.Problems.Orienteering-3.3.csproj", "{D1EFA4CC-909F-41D5-9C1F-C3AF1957A372}"
Index: branches/symbreg-factors-2650/HeuristicLab.Analysis.Views/3.3/DataTableControl.cs
===================================================================
--- branches/symbreg-factors-2650/HeuristicLab.Analysis.Views/3.3/DataTableControl.cs	(revision 14497)
+++ branches/symbreg-factors-2650/HeuristicLab.Analysis.Views/3.3/DataTableControl.cs	(revision 14498)
@@ -181,5 +181,5 @@
           break;
         case DataRowVisualProperties.DataRowChartType.Histogram:
-          series.ChartType = SeriesChartType.Column;
+          series.ChartType = SeriesChartType.StackedColumn;
           series.SetCustomProperty("PointWidth", "1");
           if (!series.Color.IsEmpty && series.Color.GetBrightness() < 0.25)
@@ -500,5 +500,18 @@
       switch (row.VisualProperties.ChartType) {
         case DataRowVisualProperties.DataRowChartType.Histogram:
-          CalculateHistogram(series, row);
+          // when a single histogram is updated, all histograms must be updated. otherwise the value ranges and bin sizes may not be equal.
+          var histograms = Content.Rows
+            .Where(r => r.VisualProperties.ChartType == DataRowVisualProperties.DataRowChartType.Histogram)
+            .ToList();
+          CalculateHistogram(series, row, histograms);
+          foreach (var h in from r in histograms
+                            where r != row
+                            let s = chart.Series.FindByName(r.Name)
+                            where s != null
+                            where !invisibleSeries.Contains(s)
+                            select new { row = r, series = s }) {
+            h.series.Points.Clear();
+            CalculateHistogram(h.series, h.row, histograms);
+          }
           break;
         default: {
@@ -524,12 +537,12 @@
     }
 
-    protected virtual void CalculateHistogram(Series series, DataRow row) {
+    protected virtual void CalculateHistogram(Series series, DataRow row, IEnumerable<DataRow> histogramRows) {
       series.Points.Clear();
       if (!row.Values.Any()) return;
-      int bins = row.VisualProperties.Bins;
-
-      double minValue = row.Values.Min();
-      double maxValue = row.Values.Max();
-      double intervalWidth = (maxValue - minValue) / bins;
+
+      int bins = histogramRows.Max(r => r.VisualProperties.Bins);
+      decimal minValue = (decimal)histogramRows.Min(r => r.Values.Min());
+      decimal maxValue = (decimal)histogramRows.Max(r => r.Values.Max());
+      decimal intervalWidth = (maxValue - minValue) / bins;
       if (intervalWidth < 0) return;
       if (intervalWidth == 0) {
@@ -538,21 +551,21 @@
       }
 
-      if (!row.VisualProperties.ExactBins) {
-        intervalWidth = HumanRoundRange(intervalWidth);
+      if (!histogramRows.Any(r => r.VisualProperties.ExactBins)) {
+        intervalWidth = (decimal)HumanRoundRange((double)intervalWidth);
         minValue = Math.Floor(minValue / intervalWidth) * intervalWidth;
         maxValue = Math.Ceiling(maxValue / intervalWidth) * intervalWidth;
       }
 
-      double intervalCenter = intervalWidth / 2;
-
-      double min = 0.0, max = 0.0;
+      decimal intervalCenter = intervalWidth / 2;
+
+      decimal min = 0.0m, max = 0.0m;
       if (!Double.IsNaN(Content.VisualProperties.XAxisMinimumFixedValue) && !Content.VisualProperties.XAxisMinimumAuto)
-        min = Content.VisualProperties.XAxisMinimumFixedValue;
+        min = (decimal)Content.VisualProperties.XAxisMinimumFixedValue;
       else min = minValue;
       if (!Double.IsNaN(Content.VisualProperties.XAxisMaximumFixedValue) && !Content.VisualProperties.XAxisMaximumAuto)
-        max = Content.VisualProperties.XAxisMaximumFixedValue;
+        max = (decimal)Content.VisualProperties.XAxisMaximumFixedValue;
       else max = maxValue + intervalWidth;
 
-      double axisInterval = intervalWidth / row.VisualProperties.ScaleFactor;
+      double axisInterval = (double)intervalWidth / row.VisualProperties.ScaleFactor;
 
       var area = chart.ChartAreas[0];
@@ -562,5 +575,5 @@
 
       // get the range or intervals which define the grouping of the frequency values
-      var doubleRange = DoubleRange(min, max, intervalWidth).Skip(1).ToList();
+      var range = Range(min, max, intervalWidth).Skip(1).ToList();
 
       // aggregate the row values by unique key and frequency value
@@ -571,14 +584,14 @@
                               select new Tuple<double, double>(g.First(), g.Count())).ToList();
 
-      // shift the chart to the left so the bars are placed on the intervals
-      if (valueFrequencies.First().Item1 < doubleRange.First())
-        series.Points.Add(new DataPoint(min - intervalWidth, 0));
+      // ensure that each column is displayed completely on the chart by adding two dummy datapoints on the upper and lower range
+      series.Points.Add(new DataPoint((double)(min - intervalWidth), 0));
+      series.Points.Add(new DataPoint((double)(max + intervalWidth), 0));
 
       // add data points
       int j = 0;
-      foreach (var d in doubleRange) {
+      foreach (var d in range) {
         double sum = 0.0;
         // sum the frequency values that fall within the same interval
-        while (j < valueFrequencies.Count && valueFrequencies[j].Item1 < d) {
+        while (j < valueFrequencies.Count && (decimal)valueFrequencies[j].Item1 < d) {
           sum += valueFrequencies[j].Item2;
           ++j;
@@ -590,5 +603,5 @@
                               ? "Y"
                               : Content.VisualProperties.YAxisTitle;
-        series.Points.Add(new DataPoint(d - intervalCenter, sum) {
+        series.Points.Add(new DataPoint((double)(d - intervalCenter), sum) {
           ToolTip =
             xAxisTitle + ": [" + (d - intervalWidth) + "-" + d + ")" + Environment.NewLine +
@@ -599,6 +612,6 @@
 
     #region Helpers
-    public static IEnumerable<double> DoubleRange(double min, double max, double step) {
-      double i;
+    public static IEnumerable<decimal> Range(decimal min, decimal max, decimal step) {
+      decimal i;
       for (i = min; i <= max; i += step)
         yield return i;
Index: branches/symbreg-factors-2650/HeuristicLab.Analysis.Views/3.3/HeuristicLab.Analysis.Views-3.3.csproj
===================================================================
--- branches/symbreg-factors-2650/HeuristicLab.Analysis.Views/3.3/HeuristicLab.Analysis.Views-3.3.csproj	(revision 14497)
+++ branches/symbreg-factors-2650/HeuristicLab.Analysis.Views/3.3/HeuristicLab.Analysis.Views-3.3.csproj	(revision 14498)
@@ -105,4 +105,8 @@
   </PropertyGroup>
   <ItemGroup>
+    <Reference Include="ALGLIB-3.7.0, Version=3.7.0.0, Culture=neutral, PublicKeyToken=ba48961d6f65dcec, processorArchitecture=MSIL">
+      <HintPath>..\..\bin\ALGLIB-3.7.0.dll</HintPath>
+      <Private>False</Private>
+    </Reference>
     <Reference Include="System" />
     <Reference Include="System.Core">
Index: branches/symbreg-factors-2650/HeuristicLab.Analysis.Views/3.3/Plugin.cs.frame
===================================================================
--- branches/symbreg-factors-2650/HeuristicLab.Analysis.Views/3.3/Plugin.cs.frame	(revision 14497)
+++ branches/symbreg-factors-2650/HeuristicLab.Analysis.Views/3.3/Plugin.cs.frame	(revision 14498)
@@ -28,4 +28,5 @@
   [Plugin("HeuristicLab.Analysis.Views", "3.3.14.$WCREV$")]
   [PluginFile("HeuristicLab.Analysis.Views-3.3.dll", PluginFileType.Assembly)]
+  [PluginDependency("HeuristicLab.ALGLIB", "3.7.0")]
   [PluginDependency("HeuristicLab.Analysis", "3.3")]
   [PluginDependency("HeuristicLab.Collections", "3.3")]
Index: branches/symbreg-factors-2650/HeuristicLab.Analysis.Views/3.3/ScatterPlotControl.cs
===================================================================
--- branches/symbreg-factors-2650/HeuristicLab.Analysis.Views/3.3/ScatterPlotControl.cs	(revision 14497)
+++ branches/symbreg-factors-2650/HeuristicLab.Analysis.Views/3.3/ScatterPlotControl.cs	(revision 14498)
@@ -24,4 +24,5 @@
 using System.Drawing;
 using System.Linq;
+using System.Text;
 using System.Windows.Forms;
 using System.Windows.Forms.DataVisualization.Charting;
@@ -33,4 +34,5 @@
     protected List<Series> invisibleSeries;
     protected Dictionary<IObservableList<Point2D<double>>, ScatterPlotDataRow> pointsRowsTable;
+    protected Dictionary<Series, Series> seriesToRegressionSeriesTable;
     private double xMin, xMax, yMin, yMax;
 
@@ -51,4 +53,5 @@
       InitializeComponent();
       pointsRowsTable = new Dictionary<IObservableList<Point2D<double>>, ScatterPlotDataRow>();
+      seriesToRegressionSeriesTable = new Dictionary<Series, Series>();
       invisibleSeries = new List<Series>();
       chart.CustomizeAllChartAreas();
@@ -126,10 +129,22 @@
       foreach (var row in rows) {
         RegisterScatterPlotDataRowEvents(row);
-        Series series = new Series(row.Name);
+        Series series = new Series(row.Name) {
+          Tag = row
+        };
         if (row.VisualProperties.DisplayName.Trim() != String.Empty) series.LegendText = row.VisualProperties.DisplayName;
         else series.LegendText = row.Name;
-        ConfigureSeries(series, row);
+        var regressionSeries = new Series(row.Name + "_Regression") {
+          Tag = row,
+          ChartType = SeriesChartType.Line,
+          BorderDashStyle = ChartDashStyle.Dot,
+          IsVisibleInLegend = false,
+          Color = Color.Transparent // to avoid auto color assignment via color palette 
+        };
+        seriesToRegressionSeriesTable.Add(series, regressionSeries);
+        ConfigureSeries(series, regressionSeries, row);
         FillSeriesWithRowValues(series, row);
         chart.Series.Add(series);
+        chart.Series.Add(regressionSeries);
+        FillRegressionSeries(regressionSeries, row);
       }
       ConfigureChartArea(chart.ChartAreas[0]);
@@ -137,4 +152,5 @@
       RecalculateAxesScale(chart.ChartAreas[0]);
       UpdateYCursorInterval();
+      UpdateRegressionSeriesColors();
     }
 
@@ -146,4 +162,6 @@
         if (invisibleSeries.Contains(series))
           invisibleSeries.Remove(series);
+        chart.Series.Remove(seriesToRegressionSeriesTable[series]);
+        seriesToRegressionSeriesTable.Remove(series);
       }
       RecalculateMinMaxPointValues();
@@ -151,5 +169,5 @@
     }
 
-    private void ConfigureSeries(Series series, ScatterPlotDataRow row) {
+    private void ConfigureSeries(Series series, Series regressionSeries, ScatterPlotDataRow row) {
       series.BorderWidth = 1;
       series.BorderDashStyle = ChartDashStyle.Solid;
@@ -179,4 +197,11 @@
         xAxisTitle + " = " + "#VALX," + Environment.NewLine +
         yAxisTitle + " = " + "#VAL";
+
+      regressionSeries.BorderWidth = Math.Max(1, row.VisualProperties.PointSize / 2);
+      regressionSeries.IsVisibleInLegend = row.VisualProperties.IsRegressionVisibleInLegend &&
+        row.VisualProperties.RegressionType != ScatterPlotDataRowVisualProperties.ScatterPlotDataRowRegressionType.None;
+      regressionSeries.LegendText = string.IsNullOrEmpty(row.VisualProperties.RegressionDisplayName)
+        ? string.Format("{0}({1})", row.VisualProperties.RegressionType, row.Name)
+        : row.VisualProperties.RegressionDisplayName;
     }
 
@@ -250,4 +275,13 @@
     }
 
+    protected void UpdateRegressionSeriesColors() {
+      chart.ApplyPaletteColors();
+      foreach (var row in Content.Rows) {
+        var series = chart.Series[row.Name];
+        var regressionSeries = seriesToRegressionSeriesTable[series];
+        regressionSeries.Color = series.Color;
+      }
+    }
+
     #region Event Handlers
     #region Content Event Handlers
@@ -300,9 +334,13 @@
         ScatterPlotDataRow row = (ScatterPlotDataRow)sender;
         Series series = chart.Series[row.Name];
+        Series regressionSeries = seriesToRegressionSeriesTable[series];
         series.Points.Clear();
-        ConfigureSeries(series, row);
+        regressionSeries.Points.Clear();
+        ConfigureSeries(series, regressionSeries, row);
         FillSeriesWithRowValues(series, row);
+        FillRegressionSeries(regressionSeries, row);
         RecalculateMinMaxPointValues();
         RecalculateAxesScale(chart.ChartAreas[0]);
+        UpdateRegressionSeriesColors();
       }
     }
@@ -325,7 +363,10 @@
         if (row != null) {
           Series rowSeries = chart.Series[row.Name];
+          Series regressionSeries = seriesToRegressionSeriesTable[rowSeries];
           if (!invisibleSeries.Contains(rowSeries)) {
             rowSeries.Points.Clear();
+            regressionSeries.Points.Clear();
             FillSeriesWithRowValues(rowSeries, row);
+            FillRegressionSeries(regressionSeries, row);
             RecalculateMinMaxPointValues();
             RecalculateAxesScale(chart.ChartAreas[0]);
@@ -343,7 +384,10 @@
         if (row != null) {
           Series rowSeries = chart.Series[row.Name];
+          Series regressionSeries = seriesToRegressionSeriesTable[rowSeries];
           if (!invisibleSeries.Contains(rowSeries)) {
             rowSeries.Points.Clear();
+            regressionSeries.Points.Clear();
             FillSeriesWithRowValues(rowSeries, row);
+            FillRegressionSeries(regressionSeries, row);
             RecalculateMinMaxPointValues();
             RecalculateAxesScale(chart.ChartAreas[0]);
@@ -361,7 +405,10 @@
         if (row != null) {
           Series rowSeries = chart.Series[row.Name];
+          Series regressionSeries = seriesToRegressionSeriesTable[rowSeries];
           if (!invisibleSeries.Contains(rowSeries)) {
             rowSeries.Points.Clear();
+            regressionSeries.Points.Clear();
             FillSeriesWithRowValues(rowSeries, row);
+            FillRegressionSeries(regressionSeries, row);
             RecalculateMinMaxPointValues();
             RecalculateAxesScale(chart.ChartAreas[0]);
@@ -379,7 +426,10 @@
         if (row != null) {
           Series rowSeries = chart.Series[row.Name];
+          Series regressionSeries = seriesToRegressionSeriesTable[rowSeries];
           if (!invisibleSeries.Contains(rowSeries)) {
             rowSeries.Points.Clear();
+            regressionSeries.Points.Clear();
             FillSeriesWithRowValues(rowSeries, row);
+            FillRegressionSeries(regressionSeries, row);
             RecalculateMinMaxPointValues();
             RecalculateAxesScale(chart.ChartAreas[0]);
@@ -430,9 +480,9 @@
         invisibleSeries.Remove(series);
         if (Content != null) {
-
-          var row = (from r in Content.Rows
-                     where r.Name == series.Name
-                     select r).Single();
-          FillSeriesWithRowValues(series, row);
+          var row = (ScatterPlotDataRow)series.Tag;
+          if (seriesToRegressionSeriesTable.ContainsKey(series))
+            FillSeriesWithRowValues(series, row);
+          else
+            FillRegressionSeries(series, row);
           RecalculateMinMaxPointValues();
           this.chart.Legends[series.Legend].ForeColor = Color.Black;
@@ -469,4 +519,31 @@
         series.Points.Add(point);
       }
+      double correlation = Correlation(row.Points);
+      series.LegendToolTip = string.Format("Correlation (R²) = {0:G4}", correlation * correlation);
+    }
+
+    private void FillRegressionSeries(Series regressionSeries, ScatterPlotDataRow row) {
+      if (row.VisualProperties.RegressionType == ScatterPlotDataRowVisualProperties.ScatterPlotDataRowRegressionType.None
+        || invisibleSeries.Contains(regressionSeries))
+        return;
+
+      double[] coefficients;
+      if (!Fitting(row, out coefficients))
+        return;
+
+      // Fill regrssion series
+      var validPoints = row.Points.Where(p => !IsInvalidValue(p.X));
+      double min = validPoints.Min(p => p.X), max = validPoints.Max(p => p.X);
+      double range = max - min, delta = range / row.Points.Count;
+      for (double x = min; x < max; x += delta) {
+        regressionSeries.Points.AddXY(x, Estimate(x, row, coefficients));
+      }
+
+      // Correlation
+      var data = row.Points.Select(p => new Point2D<double>(p.Y, Estimate(p.X, row, coefficients)));
+      double correlation = Correlation(data.ToList());
+      regressionSeries.LegendToolTip = GetStringFormula(row, coefficients) + Environment.NewLine +
+                                       string.Format("Correlation (R²) = {0:G4}", correlation * correlation);
+      regressionSeries.ToolTip = GetStringFormula(row, coefficients);
     }
 
@@ -501,4 +578,171 @@
     }
     #endregion
+
+    #region Correlation and Fitting Helper
+    protected static double Correlation(IList<Point2D<double>> values) {
+      // sums of x, y, x squared etc.
+      double sx = 0.0;
+      double sy = 0.0;
+      double sxx = 0.0;
+      double syy = 0.0;
+      double sxy = 0.0;
+
+      int n = 0;
+      for (int i = 0; i < values.Count; i++) {
+        double x = values[i].X;
+        double y = values[i].Y;
+        if (IsInvalidValue(x) || IsInvalidValue(y))
+          continue;
+
+        sx += x;
+        sy += y;
+        sxx += x * x;
+        syy += y * y;
+        sxy += x * y;
+        n++;
+      }
+
+      // covariation
+      double cov = sxy / n - sx * sy / n / n;
+      // standard error of x
+      double sigmaX = Math.Sqrt(sxx / n -  sx * sx / n / n);
+      // standard error of y
+      double sigmaY = Math.Sqrt(syy / n -  sy * sy / n / n);
+
+      // correlation
+      return cov / sigmaX / sigmaY;
+    }
+
+    protected static bool Fitting(ScatterPlotDataRow row, out double[] coefficients) {
+      var xs = row.Points.Select(p => p.X).ToList();
+      var ys = row.Points.Select(p => p.Y).ToList();
+
+      // Input transformations
+      double[,] matrix;
+      int nRows;
+      switch (row.VisualProperties.RegressionType) {
+        case ScatterPlotDataRowVisualProperties.ScatterPlotDataRowRegressionType.Linear:
+          matrix = CreateMatrix(out nRows, ys, xs);
+          break;
+        case ScatterPlotDataRowVisualProperties.ScatterPlotDataRowRegressionType.Polynomial:
+          var xss = Enumerable.Range(1, row.VisualProperties.PolynomialRegressionOrder)
+            .Select(o => xs.Select(x => Math.Pow(x, o)).ToList())
+            .Reverse(); // higher order first
+          matrix = CreateMatrix(out nRows, ys, xss.ToArray());
+          break;
+        case ScatterPlotDataRowVisualProperties.ScatterPlotDataRowRegressionType.Exponential:
+          matrix = CreateMatrix(out nRows, ys.Select(y => Math.Log(y)).ToList(), xs);
+          break;
+        case ScatterPlotDataRowVisualProperties.ScatterPlotDataRowRegressionType.Power:
+          matrix = CreateMatrix(out nRows, ys.Select(y => Math.Log(y)).ToList(), xs.Select(x => Math.Log(x)).ToList());
+          break;
+        case ScatterPlotDataRowVisualProperties.ScatterPlotDataRowRegressionType.Logarithmic:
+          matrix = CreateMatrix(out nRows, ys, xs.Select(x => Math.Log(x)).ToList());
+          break;
+        default:
+          throw new ArgumentException("Unknown RegressionType: " + row.VisualProperties.RegressionType);
+      }
+
+      // Linear fitting
+      bool success = LinearFitting(matrix, nRows, out coefficients);
+      if (!success) return success;
+
+      // Output transformation
+      switch (row.VisualProperties.RegressionType) {
+        case ScatterPlotDataRowVisualProperties.ScatterPlotDataRowRegressionType.Exponential:
+        case ScatterPlotDataRowVisualProperties.ScatterPlotDataRowRegressionType.Power:
+          coefficients[1] = Math.Exp(coefficients[1]);
+          break;
+      }
+
+      return true;
+    }
+    protected static double[,] CreateMatrix(out int nRows, IList<double> ys, params IList<double>[] xss) {
+      var matrix = new double[ys.Count, xss.Length + 1];
+      int rowIdx = 0;
+      for (int i = 0; i < ys.Count; i++) {
+        if (IsInvalidValue(ys[i]) || xss.Any(xs => IsInvalidValue(xs[i])))
+          continue;
+        for (int j = 0; j < xss.Length; j++) {
+          matrix[rowIdx, j] = xss[j][i];
+        }
+        matrix[rowIdx, xss.Length] = ys[i];
+        rowIdx++;
+      }
+      nRows = rowIdx;
+      return matrix;
+    }
+
+    protected static bool LinearFitting(double[,] xsy, int nRows, out double[] coefficients) {
+      int nFeatures = xsy.GetLength(1) - 1;
+
+      alglib.linearmodel lm;
+      alglib.lrreport ar;
+      int retVal;
+      alglib.lrbuild(xsy, nRows, nFeatures, out retVal, out lm, out ar);
+      if (retVal != 1) {
+        coefficients = new double[0];
+        return false;
+      }
+
+      alglib.lrunpack(lm, out coefficients, out nFeatures);
+      return true;
+    }
+
+    protected static double Estimate(double x, ScatterPlotDataRow row, double[] coefficients) {
+      switch (row.VisualProperties.RegressionType) {
+        case ScatterPlotDataRowVisualProperties.ScatterPlotDataRowRegressionType.Linear:
+          return coefficients[0] * x + coefficients[1];
+        case ScatterPlotDataRowVisualProperties.ScatterPlotDataRowRegressionType.Polynomial:
+          return coefficients
+            .Reverse() // to match index and order
+            .Select((c, o) => c * Math.Pow(x, o))
+            .Sum();
+        case ScatterPlotDataRowVisualProperties.ScatterPlotDataRowRegressionType.Exponential:
+          return coefficients[1] * Math.Exp(coefficients[0] * x);
+        case ScatterPlotDataRowVisualProperties.ScatterPlotDataRowRegressionType.Power:
+          return coefficients[1] * Math.Pow(x, coefficients[0]);
+        case ScatterPlotDataRowVisualProperties.ScatterPlotDataRowRegressionType.Logarithmic:
+          return coefficients[0] * Math.Log(x) + coefficients[1];
+        default:
+          throw new ArgumentException("Unknown RegressionType: " + row.VisualProperties.RegressionType);
+      }
+    }
+
+    protected static string GetStringFormula(ScatterPlotDataRow row, double[] coefficients) {
+      switch (row.VisualProperties.RegressionType) {
+        case ScatterPlotDataRowVisualProperties.ScatterPlotDataRowRegressionType.Linear:
+          return string.Format("{0:G4} x {1} {2:G4}", coefficients[0], Sign(coefficients[1]), Math.Abs(coefficients[1]));
+        case ScatterPlotDataRowVisualProperties.ScatterPlotDataRowRegressionType.Polynomial:
+          var sb = new StringBuilder();
+          sb.AppendFormat("{0:G4}{1}", coefficients[0], PolyFactor(coefficients.Length - 1));
+          foreach (var x in coefficients
+            .Reverse() // match index and order
+            .Select((c, o) => new { c, o })
+            .Reverse() // higher order first
+            .Skip(1)) // highest order poly already added
+            sb.AppendFormat(" {0} {1:G4}{2}", Sign(x.c), Math.Abs(x.c), PolyFactor(x.o));
+          return sb.ToString();
+        case ScatterPlotDataRowVisualProperties.ScatterPlotDataRowRegressionType.Exponential:
+          return string.Format("{0:G4} e^({1:G4} x)", coefficients[1], coefficients[0]);
+        case ScatterPlotDataRowVisualProperties.ScatterPlotDataRowRegressionType.Power:
+          return string.Format("{0:G4} x^({1:G4})", coefficients[1], coefficients[0]);
+        case ScatterPlotDataRowVisualProperties.ScatterPlotDataRowRegressionType.Logarithmic:
+          return string.Format("{0:G4} ln(x) {1} {2:G4}", coefficients[0], Sign(coefficients[1]), Math.Abs(coefficients[1]));
+        default:
+          throw new ArgumentException("Unknown RegressionType: " + row.VisualProperties.RegressionType);
+      }
+    }
+    private static string Sign(double value) {
+      return value >= 0 ? "+" : "-";
+    }
+    private static string PolyFactor(int order) {
+      if (order == 0) return "";
+      if (order == 1) return " x";
+      if (order == 2) return " x²";
+      if (order == 3) return " x³";
+      return " x^" + order;
+    }
+    #endregion
   }
 }
Index: branches/symbreg-factors-2650/HeuristicLab.Analysis.Views/3.3/ScatterPlotDataRowVisualPropertiesControl.Designer.cs
===================================================================
--- branches/symbreg-factors-2650/HeuristicLab.Analysis.Views/3.3/ScatterPlotDataRowVisualPropertiesControl.Designer.cs	(revision 14497)
+++ branches/symbreg-factors-2650/HeuristicLab.Analysis.Views/3.3/ScatterPlotDataRowVisualPropertiesControl.Designer.cs	(revision 14498)
@@ -45,4 +45,5 @@
     /// </summary>
     private void InitializeComponent() {
+      this.components = new System.ComponentModel.Container();
       this.pointStyleComboBox = new System.Windows.Forms.ComboBox();
       this.colorDialog = new System.Windows.Forms.ColorDialog();
@@ -56,5 +57,15 @@
       this.label9 = new System.Windows.Forms.Label();
       this.label7 = new System.Windows.Forms.Label();
+      this.label4 = new System.Windows.Forms.Label();
+      this.regressionTypeComboBox = new System.Windows.Forms.ComboBox();
+      this.regressionGroupBox = new System.Windows.Forms.GroupBox();
+      this.isRegressionVisibleInLegendCheckBox = new System.Windows.Forms.CheckBox();
+      this.polynomialRegressionOrderNumericUpDown = new System.Windows.Forms.NumericUpDown();
+      this.orderLabel = new System.Windows.Forms.Label();
+      this.regressionLegendTextBox = new System.Windows.Forms.TextBox();
+      this.toolTip = new System.Windows.Forms.ToolTip(this.components);
       ((System.ComponentModel.ISupportInitialize)(this.pointSizeNumericUpDown)).BeginInit();
+      this.regressionGroupBox.SuspendLayout();
+      ((System.ComponentModel.ISupportInitialize)(this.polynomialRegressionOrderNumericUpDown)).BeginInit();
       this.SuspendLayout();
       // 
@@ -171,7 +182,104 @@
       this.label7.Text = "&Visible in Legend:";
       // 
+      // label4
+      // 
+      this.label4.AutoSize = true;
+      this.label4.Location = new System.Drawing.Point(6, 22);
+      this.label4.Name = "label4";
+      this.label4.Size = new System.Drawing.Size(34, 13);
+      this.label4.TabIndex = 7;
+      this.label4.Text = "Type:";
+      // 
+      // regressionTypeComboBox
+      // 
+      this.regressionTypeComboBox.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left) 
+            | System.Windows.Forms.AnchorStyles.Right)));
+      this.regressionTypeComboBox.DropDownStyle = System.Windows.Forms.ComboBoxStyle.DropDownList;
+      this.regressionTypeComboBox.FormattingEnabled = true;
+      this.regressionTypeComboBox.Location = new System.Drawing.Point(93, 19);
+      this.regressionTypeComboBox.Name = "regressionTypeComboBox";
+      this.regressionTypeComboBox.Size = new System.Drawing.Size(147, 21);
+      this.regressionTypeComboBox.TabIndex = 8;
+      this.regressionTypeComboBox.SelectedValueChanged += new System.EventHandler(this.regressionTypeComboBox_SelectedValueChanged);
+      // 
+      // regressionGroupBox
+      // 
+      this.regressionGroupBox.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left) 
+            | System.Windows.Forms.AnchorStyles.Right)));
+      this.regressionGroupBox.Controls.Add(this.isRegressionVisibleInLegendCheckBox);
+      this.regressionGroupBox.Controls.Add(this.regressionTypeComboBox);
+      this.regressionGroupBox.Controls.Add(this.polynomialRegressionOrderNumericUpDown);
+      this.regressionGroupBox.Controls.Add(this.orderLabel);
+      this.regressionGroupBox.Controls.Add(this.regressionLegendTextBox);
+      this.regressionGroupBox.Controls.Add(this.label4);
+      this.regressionGroupBox.Location = new System.Drawing.Point(3, 136);
+      this.regressionGroupBox.Name = "regressionGroupBox";
+      this.regressionGroupBox.Size = new System.Drawing.Size(336, 74);
+      this.regressionGroupBox.TabIndex = 9;
+      this.regressionGroupBox.TabStop = false;
+      this.regressionGroupBox.Text = "&Regression";
+      // 
+      // isRegressionVisibleInLegendCheckBox
+      // 
+      this.isRegressionVisibleInLegendCheckBox.AutoSize = true;
+      this.isRegressionVisibleInLegendCheckBox.CheckAlign = System.Drawing.ContentAlignment.MiddleRight;
+      this.isRegressionVisibleInLegendCheckBox.Location = new System.Drawing.Point(6, 48);
+      this.isRegressionVisibleInLegendCheckBox.Name = "isRegressionVisibleInLegendCheckBox";
+      this.isRegressionVisibleInLegendCheckBox.Size = new System.Drawing.Size(68, 17);
+      this.isRegressionVisibleInLegendCheckBox.TabIndex = 13;
+      this.isRegressionVisibleInLegendCheckBox.Text = "Legend: ";
+      this.isRegressionVisibleInLegendCheckBox.UseVisualStyleBackColor = true;
+      this.isRegressionVisibleInLegendCheckBox.CheckedChanged += new System.EventHandler(this.isRegressionVisibleInLegendCheckBox_CheckedChanged);
+      // 
+      // polynomialRegressionOrderNumericUpDown
+      // 
+      this.polynomialRegressionOrderNumericUpDown.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Right)));
+      this.polynomialRegressionOrderNumericUpDown.Location = new System.Drawing.Point(285, 20);
+      this.polynomialRegressionOrderNumericUpDown.Margin = new System.Windows.Forms.Padding(9, 3, 3, 3);
+      this.polynomialRegressionOrderNumericUpDown.Maximum = new decimal(new int[] {
+            6,
+            0,
+            0,
+            0});
+      this.polynomialRegressionOrderNumericUpDown.Minimum = new decimal(new int[] {
+            2,
+            0,
+            0,
+            0});
+      this.polynomialRegressionOrderNumericUpDown.Name = "polynomialRegressionOrderNumericUpDown";
+      this.polynomialRegressionOrderNumericUpDown.Size = new System.Drawing.Size(45, 20);
+      this.polynomialRegressionOrderNumericUpDown.TabIndex = 11;
+      this.toolTip.SetToolTip(this.polynomialRegressionOrderNumericUpDown, "Order only available for Polynomial");
+      this.polynomialRegressionOrderNumericUpDown.Value = new decimal(new int[] {
+            2,
+            0,
+            0,
+            0});
+      this.polynomialRegressionOrderNumericUpDown.ValueChanged += new System.EventHandler(this.polynomialRegressionOrderNumericUpDown_ValueChanged);
+      // 
+      // orderLabel
+      // 
+      this.orderLabel.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Right)));
+      this.orderLabel.AutoSize = true;
+      this.orderLabel.Location = new System.Drawing.Point(246, 22);
+      this.orderLabel.Name = "orderLabel";
+      this.orderLabel.Size = new System.Drawing.Size(36, 13);
+      this.orderLabel.TabIndex = 12;
+      this.orderLabel.Text = "Order:";
+      // 
+      // regressionLegendTextBox
+      // 
+      this.regressionLegendTextBox.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left) 
+            | System.Windows.Forms.AnchorStyles.Right)));
+      this.regressionLegendTextBox.Location = new System.Drawing.Point(93, 46);
+      this.regressionLegendTextBox.Name = "regressionLegendTextBox";
+      this.regressionLegendTextBox.Size = new System.Drawing.Size(237, 20);
+      this.regressionLegendTextBox.TabIndex = 10;
+      this.regressionLegendTextBox.Validated += new System.EventHandler(this.regressionLegendTextBox_Validated);
+      // 
       // ScatterPlotDataRowVisualPropertiesControl
       // 
       this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Inherit;
+      this.Controls.Add(this.regressionGroupBox);
       this.Controls.Add(this.pointSizeNumericUpDown);
       this.Controls.Add(this.isVisibleInLegendCheckBox);
@@ -185,6 +293,9 @@
       this.Controls.Add(this.colorButton);
       this.Name = "ScatterPlotDataRowVisualPropertiesControl";
-      this.Size = new System.Drawing.Size(342, 135);
+      this.Size = new System.Drawing.Size(342, 215);
       ((System.ComponentModel.ISupportInitialize)(this.pointSizeNumericUpDown)).EndInit();
+      this.regressionGroupBox.ResumeLayout(false);
+      this.regressionGroupBox.PerformLayout();
+      ((System.ComponentModel.ISupportInitialize)(this.polynomialRegressionOrderNumericUpDown)).EndInit();
       this.ResumeLayout(false);
       this.PerformLayout();
@@ -205,4 +316,12 @@
     private System.Windows.Forms.Label label9;
     private System.Windows.Forms.Label label3;
+    private System.Windows.Forms.Label label4;
+    private System.Windows.Forms.ComboBox regressionTypeComboBox;
+    private System.Windows.Forms.GroupBox regressionGroupBox;
+    private System.Windows.Forms.TextBox regressionLegendTextBox;
+    private System.Windows.Forms.NumericUpDown polynomialRegressionOrderNumericUpDown;
+    private System.Windows.Forms.Label orderLabel;
+    private System.Windows.Forms.ToolTip toolTip;
+    private System.Windows.Forms.CheckBox isRegressionVisibleInLegendCheckBox;
   }
 }
Index: branches/symbreg-factors-2650/HeuristicLab.Analysis.Views/3.3/ScatterPlotDataRowVisualPropertiesControl.cs
===================================================================
--- branches/symbreg-factors-2650/HeuristicLab.Analysis.Views/3.3/ScatterPlotDataRowVisualPropertiesControl.cs	(revision 14497)
+++ branches/symbreg-factors-2650/HeuristicLab.Analysis.Views/3.3/ScatterPlotDataRowVisualPropertiesControl.cs	(revision 14498)
@@ -44,4 +44,5 @@
       InitializeComponent();
       pointStyleComboBox.DataSource = Enum.GetValues(typeof(ScatterPlotDataRowVisualProperties.ScatterPlotDataRowPointStyle));
+      regressionTypeComboBox.DataSource = Enum.GetValues(typeof(ScatterPlotDataRowVisualProperties.ScatterPlotDataRowRegressionType));
       SetEnabledStateOfControls();
     }
@@ -57,4 +58,8 @@
           pointSizeNumericUpDown.Value = 1;
           displayNameTextBox.Text = String.Empty;
+          regressionTypeComboBox.SelectedIndex = -1;
+          polynomialRegressionOrderNumericUpDown.Value = 2;
+          isRegressionVisibleInLegendCheckBox.Checked = false;
+          regressionLegendTextBox.Text = string.Empty;
         } else {
           displayNameTextBox.Text = Content.DisplayName;
@@ -69,4 +74,8 @@
           pointSizeNumericUpDown.Value = Content.PointSize;
           isVisibleInLegendCheckBox.Checked = Content.IsVisibleInLegend;
+          regressionTypeComboBox.SelectedItem = Content.RegressionType;
+          polynomialRegressionOrderNumericUpDown.Value = Content.PolynomialRegressionOrder;
+          isRegressionVisibleInLegendCheckBox.Checked = Content.IsRegressionVisibleInLegend;
+          regressionLegendTextBox.Text = content.RegressionDisplayName;
         }
       }
@@ -82,4 +91,9 @@
       pointSizeNumericUpDown.Enabled = Content != null;
       displayNameTextBox.Enabled = Content != null;
+      regressionTypeComboBox.Enabled = Content != null;
+      polynomialRegressionOrderNumericUpDown.Enabled = Content != null && Content.RegressionType == ScatterPlotDataRowVisualProperties.ScatterPlotDataRowRegressionType.Polynomial;
+      orderLabel.Enabled = polynomialRegressionOrderNumericUpDown.Enabled;
+      isRegressionVisibleInLegendCheckBox.Enabled = Content != null && Content.RegressionType != ScatterPlotDataRowVisualProperties.ScatterPlotDataRowRegressionType.None;
+      regressionLegendTextBox.Enabled = Content != null && Content.RegressionType != ScatterPlotDataRowVisualProperties.ScatterPlotDataRowRegressionType.None;
     }
 
@@ -87,5 +101,5 @@
     private void pointStyleComboBox_SelectedValueChanged(object sender, EventArgs e) {
       if (!SuppressEvents && Content != null) {
-        ScatterPlotDataRowVisualProperties.ScatterPlotDataRowPointStyle selected = (ScatterPlotDataRowVisualProperties.ScatterPlotDataRowPointStyle)pointStyleComboBox.SelectedValue;
+        var selected = (ScatterPlotDataRowVisualProperties.ScatterPlotDataRowPointStyle)pointStyleComboBox.SelectedValue;
         Content.PointStyle = selected;
       }
@@ -121,4 +135,30 @@
       }
     }
+
+    private void regressionTypeComboBox_SelectedValueChanged(object sender, EventArgs e) {
+      if (!SuppressEvents && Content != null) {
+        var selected = (ScatterPlotDataRowVisualProperties.ScatterPlotDataRowRegressionType)regressionTypeComboBox.SelectedValue;
+        Content.RegressionType = selected;
+        SetEnabledStateOfControls();
+      }
+    }
+
+    private void polynomialRegressionOrderNumericUpDown_ValueChanged(object sender, EventArgs e) {
+      if (!SuppressEvents && Content != null) {
+        Content.PolynomialRegressionOrder = (int)polynomialRegressionOrderNumericUpDown.Value;
+      }
+    }
+
+    private void isRegressionVisibleInLegendCheckBox_CheckedChanged(object sender, EventArgs e) {
+      if (!SuppressEvents && Content != null) {
+        Content.IsRegressionVisibleInLegend = isRegressionVisibleInLegendCheckBox.Checked;
+      }
+    }
+
+    private void regressionLegendTextBox_Validated(object sender, EventArgs e) {
+      if (!SuppressEvents && Content != null) {
+        Content.RegressionDisplayName = regressionLegendTextBox.Text;
+      }
+    }
     #endregion
   }
Index: branches/symbreg-factors-2650/HeuristicLab.Analysis/3.3/DataVisualization/ScatterPlotDataRowVisualProperties.cs
===================================================================
--- branches/symbreg-factors-2650/HeuristicLab.Analysis/3.3/DataVisualization/ScatterPlotDataRowVisualProperties.cs	(revision 14497)
+++ branches/symbreg-factors-2650/HeuristicLab.Analysis/3.3/DataVisualization/ScatterPlotDataRowVisualProperties.cs	(revision 14498)
@@ -45,4 +45,14 @@
     }
     #endregion
+    #region
+    public enum ScatterPlotDataRowRegressionType {
+      None,
+      Linear,
+      Polynomial,
+      Exponential,
+      Logarithmic,
+      Power
+    }
+    #endregion
 
     private Color color;
@@ -101,4 +111,49 @@
       }
     }
+    private ScatterPlotDataRowRegressionType regressionType;
+    public ScatterPlotDataRowRegressionType RegressionType {
+      get { return regressionType; }
+      set {
+        if (regressionType != value) {
+          regressionType = value;
+          OnPropertyChanged("RegressionType");
+        }
+      }
+    }
+    private int polynomialRegressionOrder;
+    public int PolynomialRegressionOrder {
+      get { return polynomialRegressionOrder; }
+      set {
+        if (polynomialRegressionOrder != value) {
+          polynomialRegressionOrder = value;
+          OnPropertyChanged("PolynomialRegressionOrder");
+        }
+      }
+    }
+    private bool isRegressionVisibleInLegend;
+    public bool IsRegressionVisibleInLegend {
+      get { return isRegressionVisibleInLegend; }
+      set {
+        if (isRegressionVisibleInLegend != value) {
+          isRegressionVisibleInLegend = value;
+          OnPropertyChanged("IsRegressionVisibleInLegend");
+        }
+      }
+    }
+    private string regressionDisplayName;
+    public string RegressionDisplayName {
+      get { return regressionDisplayName ?? string.Empty; }
+      set {
+        if (regressionDisplayName != value) {
+          if (value == null && regressionDisplayName != string.Empty) {
+            regressionDisplayName = string.Empty;
+            OnPropertyChanged("RegressionDisplayName");
+          } else if (value != null) {
+            regressionDisplayName = value;
+            OnPropertyChanged("RegressionDisplayName");
+          }
+        }
+      }
+    }
 
     #region Persistence Properties
@@ -127,4 +182,24 @@
       get { return displayName; }
       set { displayName = value; }
+    }
+    [Storable(Name = "RegressionType")]
+    private ScatterPlotDataRowRegressionType StorableRegressionType {
+      get { return regressionType; }
+      set { regressionType = value; }
+    }
+    [Storable(Name = "PolynomialRegressionOrder", DefaultValue = 2)]
+    private int StorablePolynomialRegressionOrder {
+      get { return polynomialRegressionOrder; }
+      set { polynomialRegressionOrder = value; }
+    }
+    [Storable(Name = "IsRegressionVisibleInLegend", DefaultValue = true)]
+    private bool StorableIsRegressionVisibleInLegend {
+      get { return isRegressionVisibleInLegend; }
+      set { isRegressionVisibleInLegend = value; }
+    }
+    [Storable(Name = "RegressionDisplayName")]
+    private string StorableRegressionDisplayName {
+      get { return regressionDisplayName; }
+      set { regressionDisplayName = value; }
     }
     #endregion
@@ -139,4 +214,8 @@
       this.displayName = original.displayName;
       this.isVisibleInLegend = original.isVisibleInLegend;
+      this.regressionType = original.regressionType;
+      this.polynomialRegressionOrder = original.polynomialRegressionOrder;
+      this.isRegressionVisibleInLegend = original.isRegressionVisibleInLegend;
+      this.regressionDisplayName = original.regressionDisplayName;
     }
     public ScatterPlotDataRowVisualProperties() {
@@ -146,4 +225,8 @@
       displayName = String.Empty;
       isVisibleInLegend = true;
+      regressionType = ScatterPlotDataRowRegressionType.None;
+      polynomialRegressionOrder = 2;
+      isRegressionVisibleInLegend = true;
+      regressionDisplayName = string.Empty;
     }
     public ScatterPlotDataRowVisualProperties(string displayName)
Index: branches/symbreg-factors-2650/HeuristicLab.Encodings.LinearLinkageEncoding/3.3/Creators/ExactGroupsLinearLinkageCreator.cs
===================================================================
--- branches/symbreg-factors-2650/HeuristicLab.Encodings.LinearLinkageEncoding/3.3/Creators/ExactGroupsLinearLinkageCreator.cs	(revision 14497)
+++ branches/symbreg-factors-2650/HeuristicLab.Encodings.LinearLinkageEncoding/3.3/Creators/ExactGroupsLinearLinkageCreator.cs	(revision 14498)
@@ -56,5 +56,4 @@
 
     public static LinearLinkage Apply(IRandom random, int length, int groups) {
-      var solution = new LinearLinkage(length);
       var groupNumbers = Enumerable.Range(0, length).Select(x => x % groups).Shuffle(random);
       var grouping = Enumerable.Range(0, groups).Select(x => new List<int>()).ToList();
@@ -63,6 +62,5 @@
         grouping[g].Add(idx++);
 
-      solution.SetGroups(grouping);
-      return solution;
+      return LinearLinkage.FromGroups(length, grouping);
     }
 
Index: branches/symbreg-factors-2650/HeuristicLab.Encodings.LinearLinkageEncoding/3.3/Creators/MaxGroupSizeLinearLinkageCreator.cs
===================================================================
--- branches/symbreg-factors-2650/HeuristicLab.Encodings.LinearLinkageEncoding/3.3/Creators/MaxGroupSizeLinearLinkageCreator.cs	(revision 14498)
+++ branches/symbreg-factors-2650/HeuristicLab.Encodings.LinearLinkageEncoding/3.3/Creators/MaxGroupSizeLinearLinkageCreator.cs	(revision 14498)
@@ -0,0 +1,52 @@
+﻿using System;
+using System.Collections.Generic;
+using System.Linq;
+using HeuristicLab.Common;
+using HeuristicLab.Core;
+using HeuristicLab.Data;
+using HeuristicLab.Parameters;
+using HeuristicLab.Persistence.Default.CompositeSerializers.Storable;
+
+namespace HeuristicLab.Encodings.LinearLinkageEncoding.Creators {
+  [Item("Max Group-size Linear Linkage Creator", "Creates a random linear linkage LLE encoded solution with a given maximum number of items per group.")]
+  [StorableClass]
+  public class MaxGroupSizeLinearLinkageCreator: LinearLinkageCreator {
+
+    public IValueLookupParameter<IntValue> MaxGroupSizeParameter {
+      get { return (IValueLookupParameter<IntValue>)Parameters["MaxGroupSize"]; }
+    }
+
+    public IntValue MaxGroupSize {
+      get { return MaxGroupSizeParameter.Value; }
+      set { MaxGroupSizeParameter.Value = value; }
+    }
+
+    [StorableConstructor]
+    protected MaxGroupSizeLinearLinkageCreator(bool deserializing) : base(deserializing) { }
+    protected MaxGroupSizeLinearLinkageCreator(MaxGroupSizeLinearLinkageCreator original, Cloner cloner) : base(original, cloner) { }
+
+    public MaxGroupSizeLinearLinkageCreator() {
+      Parameters.Add(new ValueLookupParameter<IntValue>("MaxGroupSize", "The maximum number items in every group.", new IntValue(4)));
+    }
+
+    public override IDeepCloneable Clone(Cloner cloner) {
+      return new MaxGroupSizeLinearLinkageCreator(this, cloner);
+    }
+
+    public static LinearLinkage Apply(IRandom random, int length, int maxGroupSize) {
+      var groups = Enumerable.Range(0, length).Select(x => new { Item = x, Group = random.Next(length)})
+        .GroupBy(x => x.Group)
+        .SelectMany(x => 
+           x.Select((y, i) => new {SubGroup = i%maxGroupSize, y.Item})
+            .GroupBy(y=>y.SubGroup)
+            .Select(y=>
+              y.Select(z=>z.Item).ToList()));
+      return LinearLinkage.FromGroups(length, groups);
+    }
+
+    protected override LinearLinkage Create(IRandom random, int length) {
+      var maxGroupSize = MaxGroupSizeParameter.ActualValue.Value;
+      return Apply(random, length, maxGroupSize);
+    }
+  }
+}
Index: branches/symbreg-factors-2650/HeuristicLab.Encodings.LinearLinkageEncoding/3.3/Creators/MaxGroupsLinearLinkageCreator.cs
===================================================================
--- branches/symbreg-factors-2650/HeuristicLab.Encodings.LinearLinkageEncoding/3.3/Creators/MaxGroupsLinearLinkageCreator.cs	(revision 14497)
+++ branches/symbreg-factors-2650/HeuristicLab.Encodings.LinearLinkageEncoding/3.3/Creators/MaxGroupsLinearLinkageCreator.cs	(revision 14498)
@@ -55,10 +55,8 @@
 
     public static LinearLinkage Apply(IRandom random, int length, int maxGroups) {
-      var solution = new LinearLinkage(length);
       var groups = Enumerable.Range(0, length).Select(x => Tuple.Create(x, random.Next(maxGroups)))
                                               .GroupBy(x => x.Item2)
                                               .Select(x => x.Select(y => y.Item1).ToList());
-      solution.SetGroups(groups);
-      return solution;
+      return LinearLinkage.FromGroups(length, groups);
     }
 
Index: branches/symbreg-factors-2650/HeuristicLab.Encodings.LinearLinkageEncoding/3.3/Creators/RandomLinearLinkageCreator.cs
===================================================================
--- branches/symbreg-factors-2650/HeuristicLab.Encodings.LinearLinkageEncoding/3.3/Creators/RandomLinearLinkageCreator.cs	(revision 14497)
+++ branches/symbreg-factors-2650/HeuristicLab.Encodings.LinearLinkageEncoding/3.3/Creators/RandomLinearLinkageCreator.cs	(revision 14498)
@@ -41,10 +41,8 @@
 
     public static LinearLinkage Apply(IRandom random, int length) {
-      var solution = new LinearLinkage(length);
       var groups = Enumerable.Range(0, length).Select(x => Tuple.Create(x, random.Next(length)))
                                               .GroupBy(x => x.Item2)
                                               .Select(x => x.Select(y => y.Item1).ToList());
-      solution.SetGroups(groups);
-      return solution;
+      return LinearLinkage.FromGroups(length, groups);
     }
 
Index: branches/symbreg-factors-2650/HeuristicLab.Encodings.LinearLinkageEncoding/3.3/Crossovers/GreedyPartitionCrossover.cs
===================================================================
--- branches/symbreg-factors-2650/HeuristicLab.Encodings.LinearLinkageEncoding/3.3/Crossovers/GreedyPartitionCrossover.cs	(revision 14497)
+++ branches/symbreg-factors-2650/HeuristicLab.Encodings.LinearLinkageEncoding/3.3/Crossovers/GreedyPartitionCrossover.cs	(revision 14498)
@@ -44,6 +44,4 @@
     public static LinearLinkage Apply(IRandom random, ItemArray<LinearLinkage> parents) {
       var len = parents[0].Length;
-
-      var child = new LinearLinkage(len);
       var childGroup = new List<HashSet<int>>();
       var currentParent = random.Next(parents.Length);
@@ -69,6 +67,5 @@
       } while (remaining);
 
-      child.SetGroups(childGroup);
-      return child;
+      return LinearLinkage.FromGroups(len, childGroup);
     }
 
Index: branches/symbreg-factors-2650/HeuristicLab.Encodings.LinearLinkageEncoding/3.3/Crossovers/GroupCrossover.cs
===================================================================
--- branches/symbreg-factors-2650/HeuristicLab.Encodings.LinearLinkageEncoding/3.3/Crossovers/GroupCrossover.cs	(revision 14497)
+++ branches/symbreg-factors-2650/HeuristicLab.Encodings.LinearLinkageEncoding/3.3/Crossovers/GroupCrossover.cs	(revision 14498)
@@ -39,30 +39,41 @@
       return new GroupCrossover(this, cloner);
     }
-
+    
     public static LinearLinkage Apply(IRandom random, LinearLinkage p1, LinearLinkage p2) {
       var length = p1.Length;
-      var child = new LinearLinkage(length);
-      var endNodes = new HashSet<int>();
-      for (var i = 0; i < length; i++) {
-        if ((p1[i] == i && p2[i] == i)
-          || ((p1[i] == i || p2[i] == i) && random.NextDouble() < 0.5)) {
-          child[i] = i;
-          endNodes.Add(i);
+      var lleeP1 = p1.ToEndLinks();
+      var lleeP2 = p2.ToEndLinks();
+      var lleeChild = new int[length];
+      var isTransfered = new bool[length];
+
+      for (var i = p1.Length - 1; i >= 0; i--) {
+        lleeChild[i] = i;
+
+        // Step 1
+        var isEndP1 = p1[i] == i;
+        var isEndP2 = p2[i] == i;
+        if (isEndP1 & isEndP2 || (isEndP1 | isEndP2 && random.NextDouble() < 0.5)) {
+          isTransfered[i] = true;
+          continue;
+        }
+
+        // Step 2
+        var end1 = lleeP1[i];
+        var end2 = lleeP2[i];
+
+        if (isTransfered[end1] & isTransfered[end2]) {
+          var end = random.NextDouble() < 0.5 ? end1 : end2;
+          lleeChild[i] = end;
+        } else if (isTransfered[end1]) {
+          lleeChild[i] = end1;
+        } else if (isTransfered[end2]) {
+          lleeChild[i] = end2;
+        } else {
+          var next = random.NextDouble() < 0.5 ? p1[i] : p2[i];
+          var end = lleeChild[next];
+          lleeChild[i] = end;
         }
       }
-      for (var i = 0; i < length; i++) {
-        if (endNodes.Contains(i)) continue;
-        var p1End = endNodes.Contains(p1[i]);
-        var p2End = endNodes.Contains(p2[i]);
-        if ((p1End && p2End) || (!p1End && !p2End)) {
-          child[i] = random.NextDouble() < 0.5 ? p1[i] : p2[i];
-        } else if (p1End) {
-          child[i] = p1[i];
-        } else {
-          child[i] = p2[i];
-        }
-      }
-      child.LinearizeTreeStructures();
-      return child;
+      return LinearLinkage.FromEndLinks(lleeChild);
     }
 
Index: branches/symbreg-factors-2650/HeuristicLab.Encodings.LinearLinkageEncoding/3.3/Crossovers/LowestIndexFirstCrossover.cs
===================================================================
--- branches/symbreg-factors-2650/HeuristicLab.Encodings.LinearLinkageEncoding/3.3/Crossovers/LowestIndexFirstCrossover.cs	(revision 14497)
+++ branches/symbreg-factors-2650/HeuristicLab.Encodings.LinearLinkageEncoding/3.3/Crossovers/LowestIndexFirstCrossover.cs	(revision 14498)
@@ -43,5 +43,5 @@
       var len = parents[0].Length;
       var p = random.Next(parents.Length);
-      var child = new LinearLinkage(len);
+      var child = LinearLinkage.SingleElementGroups(len);
       var remaining = new SortedSet<int>(Enumerable.Range(0, len));
       do {
Index: branches/symbreg-factors-2650/HeuristicLab.Encodings.LinearLinkageEncoding/3.3/Crossovers/LowestIndexMaxCrossover.cs
===================================================================
--- branches/symbreg-factors-2650/HeuristicLab.Encodings.LinearLinkageEncoding/3.3/Crossovers/LowestIndexMaxCrossover.cs	(revision 14497)
+++ branches/symbreg-factors-2650/HeuristicLab.Encodings.LinearLinkageEncoding/3.3/Crossovers/LowestIndexMaxCrossover.cs	(revision 14498)
@@ -44,5 +44,5 @@
     public static LinearLinkage Apply(IRandom random, ItemArray<LinearLinkage> parents) {
       var len = parents[0].Length;
-      var child = new LinearLinkage(len);
+      var child = LinearLinkage.SingleElementGroups(len);
       var remaining = new SortedSet<int>(Enumerable.Range(0, len));
       do {
Index: branches/symbreg-factors-2650/HeuristicLab.Encodings.LinearLinkageEncoding/3.3/Crossovers/SinglePointCrossover.cs
===================================================================
--- branches/symbreg-factors-2650/HeuristicLab.Encodings.LinearLinkageEncoding/3.3/Crossovers/SinglePointCrossover.cs	(revision 14497)
+++ branches/symbreg-factors-2650/HeuristicLab.Encodings.LinearLinkageEncoding/3.3/Crossovers/SinglePointCrossover.cs	(revision 14498)
@@ -41,5 +41,5 @@
     public static LinearLinkage Apply(IRandom random, LinearLinkage p1, LinearLinkage p2) {
       var length = p1.Length;
-      var child = new LinearLinkage(length);
+      var child = LinearLinkage.SingleElementGroups(length);
       var bp = random.Next(length - 1);
       for (var i = 0; i <= bp; i++) child[i] = p1[i];
Index: branches/symbreg-factors-2650/HeuristicLab.Encodings.LinearLinkageEncoding/3.3/HeuristicLab.Encodings.LinearLinkageEncoding-3.3.csproj
===================================================================
--- branches/symbreg-factors-2650/HeuristicLab.Encodings.LinearLinkageEncoding/3.3/HeuristicLab.Encodings.LinearLinkageEncoding-3.3.csproj	(revision 14497)
+++ 	(revision )
@@ -1,220 +1,0 @@
-﻿<?xml version="1.0" encoding="utf-8"?>
-<Project ToolsVersion="12.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
-  <Import Project="$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props" Condition="Exists('$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props')" />
-  <PropertyGroup>
-    <Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
-    <Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
-    <ProjectGuid>{BE698769-975A-429E-828C-72BB2B6182C8}</ProjectGuid>
-    <OutputType>Library</OutputType>
-    <AppDesignerFolder>Properties</AppDesignerFolder>
-    <RootNamespace>HeuristicLab.Encodings.LinearLinkageEncoding</RootNamespace>
-    <AssemblyName>HeuristicLab.Encodings.LinearLinkageEncoding-3.3</AssemblyName>
-    <TargetFrameworkVersion>v4.5</TargetFrameworkVersion>
-    <FileAlignment>512</FileAlignment>
-  </PropertyGroup>
-  <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
-    <DebugSymbols>true</DebugSymbols>
-    <DebugType>full</DebugType>
-    <Optimize>false</Optimize>
-    <OutputPath>$(SolutionDir)\bin\</OutputPath>
-    <DefineConstants>DEBUG;TRACE</DefineConstants>
-    <ErrorReport>prompt</ErrorReport>
-    <WarningLevel>4</WarningLevel>
-    <CodeAnalysisRuleSet>AllRules.ruleset</CodeAnalysisRuleSet>
-    <Prefer32Bit>false</Prefer32Bit>
-  </PropertyGroup>
-  <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
-    <DebugType>pdbonly</DebugType>
-    <Optimize>true</Optimize>
-    <OutputPath>$(SolutionDir)\bin\</OutputPath>
-    <DefineConstants>TRACE</DefineConstants>
-    <ErrorReport>prompt</ErrorReport>
-    <WarningLevel>4</WarningLevel>
-    <TreatWarningsAsErrors>false</TreatWarningsAsErrors>
-    <DocumentationFile>
-    </DocumentationFile>
-    <CodeAnalysisRuleSet>AllRules.ruleset</CodeAnalysisRuleSet>
-    <Prefer32Bit>false</Prefer32Bit>
-  </PropertyGroup>
-  <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|x86' ">
-    <DebugSymbols>true</DebugSymbols>
-    <OutputPath>$(SolutionDir)\bin\</OutputPath>
-    <DefineConstants>DEBUG;TRACE</DefineConstants>
-    <DebugType>full</DebugType>
-    <PlatformTarget>x86</PlatformTarget>
-    <ErrorReport>prompt</ErrorReport>
-    <CodeAnalysisRuleSet>AllRules.ruleset</CodeAnalysisRuleSet>
-    <Prefer32Bit>false</Prefer32Bit>
-  </PropertyGroup>
-  <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|x86' ">
-    <OutputPath>$(SolutionDir)\bin\</OutputPath>
-    <DefineConstants>TRACE</DefineConstants>
-    <DocumentationFile>
-    </DocumentationFile>
-    <Optimize>true</Optimize>
-    <DebugType>pdbonly</DebugType>
-    <PlatformTarget>x86</PlatformTarget>
-    <ErrorReport>prompt</ErrorReport>
-    <CodeAnalysisRuleSet>AllRules.ruleset</CodeAnalysisRuleSet>
-    <Prefer32Bit>false</Prefer32Bit>
-  </PropertyGroup>
-  <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|x64' ">
-    <DebugSymbols>true</DebugSymbols>
-    <OutputPath>$(SolutionDir)\bin\</OutputPath>
-    <DefineConstants>DEBUG;TRACE</DefineConstants>
-    <DebugType>full</DebugType>
-    <PlatformTarget>x64</PlatformTarget>
-    <ErrorReport>prompt</ErrorReport>
-    <CodeAnalysisRuleSet>AllRules.ruleset</CodeAnalysisRuleSet>
-    <Prefer32Bit>false</Prefer32Bit>
-  </PropertyGroup>
-  <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|x64' ">
-    <OutputPath>$(SolutionDir)\bin\</OutputPath>
-    <DefineConstants>TRACE</DefineConstants>
-    <DocumentationFile>
-    </DocumentationFile>
-    <Optimize>true</Optimize>
-    <DebugType>pdbonly</DebugType>
-    <PlatformTarget>x64</PlatformTarget>
-    <ErrorReport>prompt</ErrorReport>
-    <CodeAnalysisRuleSet>AllRules.ruleset</CodeAnalysisRuleSet>
-    <Prefer32Bit>false</Prefer32Bit>
-  </PropertyGroup>
-  <PropertyGroup>
-    <SignAssembly>true</SignAssembly>
-  </PropertyGroup>
-  <PropertyGroup>
-    <AssemblyOriginatorKeyFile>HeuristicLab.snk</AssemblyOriginatorKeyFile>
-  </PropertyGroup>
-  <ItemGroup>
-    <ProjectReference Include="..\..\HeuristicLab.Collections\3.3\HeuristicLab.Collections-3.3.csproj">
-      <Project>{958B43BC-CC5C-4FA2-8628-2B3B01D890B6}</Project>
-      <Name>HeuristicLab.Collections-3.3</Name>
-      <Private>False</Private>
-    </ProjectReference>
-    <ProjectReference Include="..\..\HeuristicLab.Common\3.3\HeuristicLab.Common-3.3.csproj">
-      <Project>{A9AD58B9-3EF9-4CC1-97E5-8D909039FF5C}</Project>
-      <Name>HeuristicLab.Common-3.3</Name>
-      <Private>False</Private>
-    </ProjectReference>
-    <ProjectReference Include="..\..\HeuristicLab.Core\3.3\HeuristicLab.Core-3.3.csproj">
-      <Project>{C36BD924-A541-4A00-AFA8-41701378DDC5}</Project>
-      <Name>HeuristicLab.Core-3.3</Name>
-      <Private>False</Private>
-    </ProjectReference>
-    <ProjectReference Include="..\..\HeuristicLab.Data\3.3\HeuristicLab.Data-3.3.csproj">
-      <Project>{BBAB9DF5-5EF3-4BA8-ADE9-B36E82114937}</Project>
-      <Name>HeuristicLab.Data-3.3</Name>
-      <Private>False</Private>
-    </ProjectReference>
-    <ProjectReference Include="..\..\HeuristicLab.Operators\3.3\HeuristicLab.Operators-3.3.csproj">
-      <Project>{23DA7FF4-D5B8-41B6-AA96-F0561D24F3EE}</Project>
-      <Name>HeuristicLab.Operators-3.3</Name>
-      <Private>False</Private>
-    </ProjectReference>
-    <ProjectReference Include="..\..\HeuristicLab.Optimization.Operators\3.3\HeuristicLab.Optimization.Operators-3.3.csproj">
-      <Project>{25087811-F74C-4128-BC86-8324271DA13E}</Project>
-      <Name>HeuristicLab.Optimization.Operators-3.3</Name>
-      <Private>False</Private>
-    </ProjectReference>
-    <ProjectReference Include="..\..\HeuristicLab.Optimization\3.3\HeuristicLab.Optimization-3.3.csproj">
-      <Project>{14AB8D24-25BC-400C-A846-4627AA945192}</Project>
-      <Name>HeuristicLab.Optimization-3.3</Name>
-      <Private>False</Private>
-    </ProjectReference>
-    <ProjectReference Include="..\..\HeuristicLab.Parameters\3.3\HeuristicLab.Parameters-3.3.csproj">
-      <Project>{56F9106A-079F-4C61-92F6-86A84C2D84B7}</Project>
-      <Name>HeuristicLab.Parameters-3.3</Name>
-      <Private>False</Private>
-    </ProjectReference>
-    <ProjectReference Include="..\..\HeuristicLab.Persistence\3.3\HeuristicLab.Persistence-3.3.csproj">
-      <Project>{102BC7D3-0EF9-439C-8F6D-96FF0FDB8E1B}</Project>
-      <Name>HeuristicLab.Persistence-3.3</Name>
-      <Private>False</Private>
-    </ProjectReference>
-    <ProjectReference Include="..\..\HeuristicLab.PluginInfrastructure\3.3\HeuristicLab.PluginInfrastructure-3.3.csproj">
-      <Project>{94186A6A-5176-4402-AE83-886557B53CCA}</Project>
-      <Name>HeuristicLab.PluginInfrastructure-3.3</Name>
-      <Private>False</Private>
-    </ProjectReference>
-    <ProjectReference Include="..\..\HeuristicLab.Random\3.3\HeuristicLab.Random-3.3.csproj">
-      <Project>{f4539fb6-4708-40c9-be64-0a1390aea197}</Project>
-      <Name>HeuristicLab.Random-3.3</Name>
-      <Private>False</Private>
-    </ProjectReference>
-  </ItemGroup>
-  <ItemGroup>
-    <Reference Include="System" />
-    <Reference Include="System.Core" />
-    <Reference Include="System.Drawing" />
-    <Reference Include="System.Xml.Linq" />
-    <Reference Include="System.Data.DataSetExtensions" />
-    <Reference Include="Microsoft.CSharp" />
-    <Reference Include="System.Data" />
-    <Reference Include="System.Xml" />
-  </ItemGroup>
-  <ItemGroup>
-    <Compile Include="Creators\ExactGroupsLinearLinkageCreator.cs" />
-    <Compile Include="Creators\MaxGroupsLinearLinkageCreator.cs" />
-    <Compile Include="Creators\RandomLinearLinkageCreator.cs" />
-    <Compile Include="Crossovers\GreedyPartitionCrossover.cs" />
-    <Compile Include="Crossovers\GroupCrossover.cs" />
-    <Compile Include="Crossovers\LowestIndexMaxCrossover.cs" />
-    <Compile Include="Crossovers\MultiLLECrossover.cs" />
-    <Compile Include="Crossovers\SinglePointCrossover.cs" />
-    <Compile Include="Interfaces\ILinearLinkageMoveOperator.cs" />
-    <Compile Include="Interfaces\ILinearLinkageSwap2MoveOperator.cs" />
-    <Compile Include="Interfaces\ILinearLinkageCreator.cs" />
-    <Compile Include="LinearLinkage.cs" />
-    <Compile Include="LinearLinkageCreator.cs" />
-    <Compile Include="LinearLinkageEncoding.cs" />
-    <Compile Include="LinearLinkageManipulator.cs" />
-    <Compile Include="LinearLinkageCrossover.cs" />
-    <Compile Include="Manipulators\GraftManipulator.cs" />
-    <Compile Include="Manipulators\MoveItemManipulator.cs" />
-    <Compile Include="Manipulators\MergeGroupManipulator.cs" />
-    <Compile Include="Manipulators\MultiLLEManipulator.cs" />
-    <Compile Include="Moves\Swap\ExhaustiveSwap2MoveGenerator.cs" />
-    <Compile Include="Moves\Swap\StochasticSwap2MultiMoveGenerator.cs" />
-    <Compile Include="Moves\Swap\StochasticSwap2SingleMoveGenerator.cs" />
-    <Compile Include="Moves\Swap\Swap2Move.cs" />
-    <Compile Include="Moves\Swap\Swap2MoveGenerator.cs" />
-    <Compile Include="Moves\Swap\Swap2MoveMaker.cs" />
-    <Compile Include="ShakingOperators\LLEShakingOperator.cs" />
-    <None Include="HeuristicLab.snk" />
-    <None Include="Plugin.cs.frame" />
-    <Compile Include="Crossovers\LowestIndexFirstCrossover.cs" />
-    <Compile Include="Interfaces\ILinearLinkageCrossover.cs" />
-    <Compile Include="Interfaces\ILinearLinkageManipulator.cs" />
-    <Compile Include="Interfaces\ILinearLinkageOperator.cs" />
-    <Compile Include="Interfaces\ILinearLinkageShakingOperator.cs" />
-    <Compile Include="Manipulators\SplitGroupManipulator.cs" />
-    <Compile Include="Manipulators\SwapItemManipulator.cs" />
-    <Compile Include="Plugin.cs" />
-    <None Include="Properties\AssemblyInfo.cs.frame" />
-    <Compile Include="Properties\AssemblyInfo.cs" />
-  </ItemGroup>
-  <Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
-  <PropertyGroup>
-    <PreBuildEvent Condition=" '$(OS)' == 'Windows_NT' ">set Path=%25Path%25;$(ProjectDir);$(SolutionDir)
-set ProjectDir=$(ProjectDir)
-set SolutionDir=$(SolutionDir)
-set Outdir=$(Outdir)
-
-call PreBuildEvent.cmd
-    </PreBuildEvent>
-    <PreBuildEvent Condition=" '$(OS)' != 'Windows_NT' ">
-export ProjectDir=$(ProjectDir)
-export SolutionDir=$(SolutionDir)
-
-$SolutionDir/PreBuildEvent.sh
-    </PreBuildEvent>
-  </PropertyGroup>
-  <!-- To modify your build process, add your task inside one of the targets below and uncomment it. 
-       Other similar extension points exist, see Microsoft.Common.targets.
-  <Target Name="BeforeBuild">
-  </Target>
-  <Target Name="AfterBuild">
-  </Target>
-  -->
-</Project>
Index: branches/symbreg-factors-2650/HeuristicLab.Encodings.LinearLinkageEncoding/3.3/HeuristicLab.Encodings.LinearLinkageEncoding-3.4.csproj
===================================================================
--- branches/symbreg-factors-2650/HeuristicLab.Encodings.LinearLinkageEncoding/3.3/HeuristicLab.Encodings.LinearLinkageEncoding-3.4.csproj	(revision 14498)
+++ branches/symbreg-factors-2650/HeuristicLab.Encodings.LinearLinkageEncoding/3.3/HeuristicLab.Encodings.LinearLinkageEncoding-3.4.csproj	(revision 14498)
@@ -0,0 +1,221 @@
+﻿<?xml version="1.0" encoding="utf-8"?>
+<Project ToolsVersion="12.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+  <Import Project="$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props" Condition="Exists('$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props')" />
+  <PropertyGroup>
+    <Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
+    <Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
+    <ProjectGuid>{BE698769-975A-429E-828C-72BB2B6182C8}</ProjectGuid>
+    <OutputType>Library</OutputType>
+    <AppDesignerFolder>Properties</AppDesignerFolder>
+    <RootNamespace>HeuristicLab.Encodings.LinearLinkageEncoding</RootNamespace>
+    <AssemblyName>HeuristicLab.Encodings.LinearLinkageEncoding-3.4</AssemblyName>
+    <TargetFrameworkVersion>v4.5</TargetFrameworkVersion>
+    <FileAlignment>512</FileAlignment>
+  </PropertyGroup>
+  <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
+    <DebugSymbols>true</DebugSymbols>
+    <DebugType>full</DebugType>
+    <Optimize>false</Optimize>
+    <OutputPath>$(SolutionDir)\bin\</OutputPath>
+    <DefineConstants>DEBUG;TRACE</DefineConstants>
+    <ErrorReport>prompt</ErrorReport>
+    <WarningLevel>4</WarningLevel>
+    <CodeAnalysisRuleSet>AllRules.ruleset</CodeAnalysisRuleSet>
+    <Prefer32Bit>false</Prefer32Bit>
+  </PropertyGroup>
+  <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
+    <DebugType>pdbonly</DebugType>
+    <Optimize>true</Optimize>
+    <OutputPath>$(SolutionDir)\bin\</OutputPath>
+    <DefineConstants>TRACE</DefineConstants>
+    <ErrorReport>prompt</ErrorReport>
+    <WarningLevel>4</WarningLevel>
+    <TreatWarningsAsErrors>false</TreatWarningsAsErrors>
+    <DocumentationFile>
+    </DocumentationFile>
+    <CodeAnalysisRuleSet>AllRules.ruleset</CodeAnalysisRuleSet>
+    <Prefer32Bit>false</Prefer32Bit>
+  </PropertyGroup>
+  <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|x86' ">
+    <DebugSymbols>true</DebugSymbols>
+    <OutputPath>$(SolutionDir)\bin\</OutputPath>
+    <DefineConstants>DEBUG;TRACE</DefineConstants>
+    <DebugType>full</DebugType>
+    <PlatformTarget>x86</PlatformTarget>
+    <ErrorReport>prompt</ErrorReport>
+    <CodeAnalysisRuleSet>AllRules.ruleset</CodeAnalysisRuleSet>
+    <Prefer32Bit>false</Prefer32Bit>
+  </PropertyGroup>
+  <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|x86' ">
+    <OutputPath>$(SolutionDir)\bin\</OutputPath>
+    <DefineConstants>TRACE</DefineConstants>
+    <DocumentationFile>
+    </DocumentationFile>
+    <Optimize>true</Optimize>
+    <DebugType>pdbonly</DebugType>
+    <PlatformTarget>x86</PlatformTarget>
+    <ErrorReport>prompt</ErrorReport>
+    <CodeAnalysisRuleSet>AllRules.ruleset</CodeAnalysisRuleSet>
+    <Prefer32Bit>false</Prefer32Bit>
+  </PropertyGroup>
+  <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|x64' ">
+    <DebugSymbols>true</DebugSymbols>
+    <OutputPath>$(SolutionDir)\bin\</OutputPath>
+    <DefineConstants>DEBUG;TRACE</DefineConstants>
+    <DebugType>full</DebugType>
+    <PlatformTarget>x64</PlatformTarget>
+    <ErrorReport>prompt</ErrorReport>
+    <CodeAnalysisRuleSet>AllRules.ruleset</CodeAnalysisRuleSet>
+    <Prefer32Bit>false</Prefer32Bit>
+  </PropertyGroup>
+  <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|x64' ">
+    <OutputPath>$(SolutionDir)\bin\</OutputPath>
+    <DefineConstants>TRACE</DefineConstants>
+    <DocumentationFile>
+    </DocumentationFile>
+    <Optimize>true</Optimize>
+    <DebugType>pdbonly</DebugType>
+    <PlatformTarget>x64</PlatformTarget>
+    <ErrorReport>prompt</ErrorReport>
+    <CodeAnalysisRuleSet>AllRules.ruleset</CodeAnalysisRuleSet>
+    <Prefer32Bit>false</Prefer32Bit>
+  </PropertyGroup>
+  <PropertyGroup>
+    <SignAssembly>true</SignAssembly>
+  </PropertyGroup>
+  <PropertyGroup>
+    <AssemblyOriginatorKeyFile>HeuristicLab.snk</AssemblyOriginatorKeyFile>
+  </PropertyGroup>
+  <ItemGroup>
+    <ProjectReference Include="..\..\HeuristicLab.Collections\3.3\HeuristicLab.Collections-3.3.csproj">
+      <Project>{958B43BC-CC5C-4FA2-8628-2B3B01D890B6}</Project>
+      <Name>HeuristicLab.Collections-3.3</Name>
+      <Private>False</Private>
+    </ProjectReference>
+    <ProjectReference Include="..\..\HeuristicLab.Common\3.3\HeuristicLab.Common-3.3.csproj">
+      <Project>{A9AD58B9-3EF9-4CC1-97E5-8D909039FF5C}</Project>
+      <Name>HeuristicLab.Common-3.3</Name>
+      <Private>False</Private>
+    </ProjectReference>
+    <ProjectReference Include="..\..\HeuristicLab.Core\3.3\HeuristicLab.Core-3.3.csproj">
+      <Project>{C36BD924-A541-4A00-AFA8-41701378DDC5}</Project>
+      <Name>HeuristicLab.Core-3.3</Name>
+      <Private>False</Private>
+    </ProjectReference>
+    <ProjectReference Include="..\..\HeuristicLab.Data\3.3\HeuristicLab.Data-3.3.csproj">
+      <Project>{BBAB9DF5-5EF3-4BA8-ADE9-B36E82114937}</Project>
+      <Name>HeuristicLab.Data-3.3</Name>
+      <Private>False</Private>
+    </ProjectReference>
+    <ProjectReference Include="..\..\HeuristicLab.Operators\3.3\HeuristicLab.Operators-3.3.csproj">
+      <Project>{23DA7FF4-D5B8-41B6-AA96-F0561D24F3EE}</Project>
+      <Name>HeuristicLab.Operators-3.3</Name>
+      <Private>False</Private>
+    </ProjectReference>
+    <ProjectReference Include="..\..\HeuristicLab.Optimization.Operators\3.3\HeuristicLab.Optimization.Operators-3.3.csproj">
+      <Project>{25087811-F74C-4128-BC86-8324271DA13E}</Project>
+      <Name>HeuristicLab.Optimization.Operators-3.3</Name>
+      <Private>False</Private>
+    </ProjectReference>
+    <ProjectReference Include="..\..\HeuristicLab.Optimization\3.3\HeuristicLab.Optimization-3.3.csproj">
+      <Project>{14AB8D24-25BC-400C-A846-4627AA945192}</Project>
+      <Name>HeuristicLab.Optimization-3.3</Name>
+      <Private>False</Private>
+    </ProjectReference>
+    <ProjectReference Include="..\..\HeuristicLab.Parameters\3.3\HeuristicLab.Parameters-3.3.csproj">
+      <Project>{56F9106A-079F-4C61-92F6-86A84C2D84B7}</Project>
+      <Name>HeuristicLab.Parameters-3.3</Name>
+      <Private>False</Private>
+    </ProjectReference>
+    <ProjectReference Include="..\..\HeuristicLab.Persistence\3.3\HeuristicLab.Persistence-3.3.csproj">
+      <Project>{102BC7D3-0EF9-439C-8F6D-96FF0FDB8E1B}</Project>
+      <Name>HeuristicLab.Persistence-3.3</Name>
+      <Private>False</Private>
+    </ProjectReference>
+    <ProjectReference Include="..\..\HeuristicLab.PluginInfrastructure\3.3\HeuristicLab.PluginInfrastructure-3.3.csproj">
+      <Project>{94186A6A-5176-4402-AE83-886557B53CCA}</Project>
+      <Name>HeuristicLab.PluginInfrastructure-3.3</Name>
+      <Private>False</Private>
+    </ProjectReference>
+    <ProjectReference Include="..\..\HeuristicLab.Random\3.3\HeuristicLab.Random-3.3.csproj">
+      <Project>{f4539fb6-4708-40c9-be64-0a1390aea197}</Project>
+      <Name>HeuristicLab.Random-3.3</Name>
+      <Private>False</Private>
+    </ProjectReference>
+  </ItemGroup>
+  <ItemGroup>
+    <Reference Include="System" />
+    <Reference Include="System.Core" />
+    <Reference Include="System.Drawing" />
+    <Reference Include="System.Xml.Linq" />
+    <Reference Include="System.Data.DataSetExtensions" />
+    <Reference Include="Microsoft.CSharp" />
+    <Reference Include="System.Data" />
+    <Reference Include="System.Xml" />
+  </ItemGroup>
+  <ItemGroup>
+    <Compile Include="Creators\ExactGroupsLinearLinkageCreator.cs" />
+    <Compile Include="Creators\MaxGroupSizeLinearLinkageCreator.cs" />
+    <Compile Include="Creators\MaxGroupsLinearLinkageCreator.cs" />
+    <Compile Include="Creators\RandomLinearLinkageCreator.cs" />
+    <Compile Include="Crossovers\GreedyPartitionCrossover.cs" />
+    <Compile Include="Crossovers\GroupCrossover.cs" />
+    <Compile Include="Crossovers\LowestIndexMaxCrossover.cs" />
+    <Compile Include="Crossovers\MultiLLECrossover.cs" />
+    <Compile Include="Crossovers\SinglePointCrossover.cs" />
+    <Compile Include="Interfaces\ILinearLinkageMoveOperator.cs" />
+    <Compile Include="Interfaces\ILinearLinkageSwap2MoveOperator.cs" />
+    <Compile Include="Interfaces\ILinearLinkageCreator.cs" />
+    <Compile Include="LinearLinkage.cs" />
+    <Compile Include="LinearLinkageCreator.cs" />
+    <Compile Include="LinearLinkageEncoding.cs" />
+    <Compile Include="LinearLinkageManipulator.cs" />
+    <Compile Include="LinearLinkageCrossover.cs" />
+    <Compile Include="Manipulators\GraftManipulator.cs" />
+    <Compile Include="Manipulators\MoveItemManipulator.cs" />
+    <Compile Include="Manipulators\MergeGroupManipulator.cs" />
+    <Compile Include="Manipulators\MultiLLEManipulator.cs" />
+    <Compile Include="Moves\Swap\ExhaustiveSwap2MoveGenerator.cs" />
+    <Compile Include="Moves\Swap\StochasticSwap2MultiMoveGenerator.cs" />
+    <Compile Include="Moves\Swap\StochasticSwap2SingleMoveGenerator.cs" />
+    <Compile Include="Moves\Swap\Swap2Move.cs" />
+    <Compile Include="Moves\Swap\Swap2MoveGenerator.cs" />
+    <Compile Include="Moves\Swap\Swap2MoveMaker.cs" />
+    <Compile Include="ShakingOperators\LLEShakingOperator.cs" />
+    <None Include="HeuristicLab.snk" />
+    <None Include="Plugin.cs.frame" />
+    <Compile Include="Crossovers\LowestIndexFirstCrossover.cs" />
+    <Compile Include="Interfaces\ILinearLinkageCrossover.cs" />
+    <Compile Include="Interfaces\ILinearLinkageManipulator.cs" />
+    <Compile Include="Interfaces\ILinearLinkageOperator.cs" />
+    <Compile Include="Interfaces\ILinearLinkageShakingOperator.cs" />
+    <Compile Include="Manipulators\SplitGroupManipulator.cs" />
+    <Compile Include="Manipulators\SwapItemManipulator.cs" />
+    <Compile Include="Plugin.cs" />
+    <None Include="Properties\AssemblyInfo.cs.frame" />
+    <Compile Include="Properties\AssemblyInfo.cs" />
+  </ItemGroup>
+  <Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
+  <PropertyGroup>
+    <PreBuildEvent Condition=" '$(OS)' == 'Windows_NT' ">set Path=%25Path%25;$(ProjectDir);$(SolutionDir)
+set ProjectDir=$(ProjectDir)
+set SolutionDir=$(SolutionDir)
+set Outdir=$(Outdir)
+
+call PreBuildEvent.cmd
+    </PreBuildEvent>
+    <PreBuildEvent Condition=" '$(OS)' != 'Windows_NT' ">
+export ProjectDir=$(ProjectDir)
+export SolutionDir=$(SolutionDir)
+
+$SolutionDir/PreBuildEvent.sh
+    </PreBuildEvent>
+  </PropertyGroup>
+  <!-- To modify your build process, add your task inside one of the targets below and uncomment it. 
+       Other similar extension points exist, see Microsoft.Common.targets.
+  <Target Name="BeforeBuild">
+  </Target>
+  <Target Name="AfterBuild">
+  </Target>
+  -->
+</Project>
Index: branches/symbreg-factors-2650/HeuristicLab.Encodings.LinearLinkageEncoding/3.3/LinearLinkage.cs
===================================================================
--- branches/symbreg-factors-2650/HeuristicLab.Encodings.LinearLinkageEncoding/3.3/LinearLinkage.cs	(revision 14497)
+++ branches/symbreg-factors-2650/HeuristicLab.Encodings.LinearLinkageEncoding/3.3/LinearLinkage.cs	(revision 14498)
@@ -37,6 +37,65 @@
     private LinearLinkage(LinearLinkage original, Cloner cloner) : base(original, cloner) { }
     public LinearLinkage() { }
-    public LinearLinkage(int length) : base(length) { }
-    public LinearLinkage(int[] elements) : base(elements) { }
+
+    private LinearLinkage(int length) : base(length) { }
+    private LinearLinkage(int[] elements) : base(elements) { }
+
+    /// <summary>
+    /// Create a new LinearLinkage object where every element is in a seperate group.
+    /// </summary>
+    public static LinearLinkage SingleElementGroups(int length) {
+      var elements = new int[length];
+      for (var i = 0; i < length; i++) {
+        elements[i] = i;
+      }
+      return new LinearLinkage(elements);
+    }
+
+    /// <summary>
+    /// Create a new LinearLinkage object from an int[] in LLE
+    /// </summary>
+    /// <remarks>
+    /// This operation checks if the argument is a well formed LLE
+    /// and throws an ArgumentException otherwise.
+    /// </remarks>
+    /// <param name="lle">The LLE representation</param>
+    public static LinearLinkage FromForwardLinks(int[] lle) {
+      if (!Validate(lle)) {
+        throw new ArgumentException("Array is malformed and does not represent a valid LLE forward encoding.", "elements");
+      }
+      return new LinearLinkage(lle);
+    }
+
+    /// <summary>
+    /// Create a new LinearLinkage object by parsing an LLE-e representation
+    /// and modifing the underlying array so that it is in LLE representation.
+    /// </summary>
+    /// <remarks>
+    /// This operation runs in O(n) time, but requires additional memory
+    /// in form of a int[].
+    /// </remarks>
+    /// <param name="llee">The LLE-e representation</param>
+    /// <returns>LinearLinkage</returns>
+    public static LinearLinkage FromEndLinks(int[] llee) {
+      var result = new LinearLinkage(llee.Length);
+      result.SetEndLinks(llee);
+      return result;
+    }
+
+    /// <summary>
+    /// Create a new LinearLinkage object by translating
+    /// an enumeration of groups into the underlying array representation.
+    /// </summary>
+    /// <remarks>
+    /// Throws an ArgumentException when there is an element assigned to
+    /// multiple groups or elements that are not assigned to any group.
+    /// </remarks>
+    /// <param name="grouping">The grouping of the elements, each element must
+    /// be part of exactly one group.</param>
+    public static LinearLinkage FromGroups(int length, IEnumerable<IEnumerable<int>> grouping) {
+      var result = new LinearLinkage(length);
+      result.SetGroups(grouping);
+      return result;
+    }
 
     public override IDeepCloneable Clone(Cloner cloner) {
@@ -55,23 +114,42 @@
     public IEnumerable<List<int>> GetGroups() {
       var len = array.Length;
-      var remaining = new HashSet<int>(Enumerable.Range(0, len));
+      var used = new bool[len];
+      for (var i = 0; i < len; i++) {
+        if (used[i]) continue;
+        var curr = i;
+        var next = array[curr];
+        var group = new List<int> { curr };
+        while (next > curr && next < len && !used[next]) {
+          used[curr] = true;
+          curr = next;
+          next = array[next];
+          group.Add(curr);
+        }
+        if (curr != next) throw new ArgumentException("Array is malformed and does not represent a valid LLE forward encoding.");
+        used[curr] = true;
+        yield return group;
+      }
+      /*
+      var len = array.Length;
+      var used = new bool[len];
       // iterate from lowest to highest index
       for (var i = 0; i < len; i++) {
-        if (!remaining.Contains(i)) continue;
+        if (used[i]) continue;
         var group = new List<int> { i };
-        remaining.Remove(i);
+        used[i] = true;
         var next = array[i];
-        if (next != i) {
-          int prev;
-          do {
-            group.Add(next);
-            if (!remaining.Remove(next))
-              throw new ArgumentException("Array is malformed and does not represent a valid LLE forward encoding.");
-            prev = next;
-            next = array[next];
-          } while (next != prev);
+        if (next < i || next >= len) {
+          throw new ArgumentException("Array is malformed and does not represent a valid LLE forward encoding.");
+        }
+        while (next != array[next]) {
+          if (next < 0 || next >= len || used[next]) {
+            throw new ArgumentException("Array is malformed and does not represent a valid LLE forward encoding.");
+          }
+          group.Add(next);
+          used[next] = true;
+          next = array[next];
         }
         yield return group;
-      }
+      }*/
     }
 
@@ -151,17 +229,20 @@
     public void SetGroups(IEnumerable<IEnumerable<int>> grouping) {
       var len = array.Length;
-      var remaining = new HashSet<int>(Enumerable.Range(0, len));
+      var used = new bool[len];
       foreach (var group in grouping) {
         var prev = -1;
         foreach (var g in group.OrderBy(x => x)) {
+          if (g < prev || g >= len) throw new ArgumentException(string.Format("Element {0} is bigger than {1} or smaller than 0.", g, len - 1), "grouping");
           if (prev >= 0) array[prev] = g;
           prev = g;
-          if (!remaining.Remove(prev))
+          if (used[prev]) {
             throw new ArgumentException(string.Format("Element {0} is contained at least twice.", prev), "grouping");
-        }
-        if (prev >= 0) array[prev] = prev;
-      }
-      if (remaining.Count > 0)
-        throw new ArgumentException(string.Format("Elements are not assigned a group: {0}", string.Join(", ", remaining)));
+          }
+          used[prev] = true;
+        }
+        array[prev] = prev;
+      }
+      if (!used.All(x => x))
+        throw new ArgumentException(string.Format("Elements are not assigned a group: {0}", string.Join(", ", used.Select((x, i) => new { x, i }).Where(x => !x.x).Select(x => x.i))));
     }
 
@@ -175,19 +256,23 @@
     /// <returns>True if the encoding is valid.</returns>
     public bool Validate() {
+      return Validate(array);
+    }
+
+    private static bool Validate(int[] array) {
       var len = array.Length;
-      var remaining = new HashSet<int>(Enumerable.Range(0, len));
+      var used = new bool[len];
       for (var i = 0; i < len; i++) {
-        if (!remaining.Contains(i)) continue;
-        remaining.Remove(i);
-        var next = array[i];
-        if (next == i) continue;
-        int prev;
-        do {
-          if (!remaining.Remove(next)) return false;
-          prev = next;
+        if (used[i]) continue;
+        var curr = i;
+        var next = array[curr];
+        while (next > curr && next < len && !used[next]) {
+          used[curr] = true;
+          curr = next;
           next = array[next];
-        } while (next != prev);
-      }
-      return remaining.Count == 0;
+        }
+        if (curr!=next) return false;
+        used[curr] = true;
+      }
+      return true;
     }
 
@@ -216,7 +301,7 @@
     public void LinearizeTreeStructures() {
       // Step 1: Convert the array into LLE-e
-      ToLLEeInplace(array);
+      ToEndLinksInplace(array);
       // Step 2: For all groups linearize the links
-      FromLLEe(array);
+      SetEndLinks(array);
     }
 
@@ -233,15 +318,19 @@
     /// </remarks>
     /// <returns>An integer array in LLE-e representation</returns>
-    public int[] ToLLEe() {
+    public int[] ToEndLinks() {
       var result = (int[])array.Clone();
-      ToLLEeInplace(result);
+      ToEndLinksInplace(result);
       return result;
     }
 
-    private void ToLLEeInplace(int[] a) {
-      var length = a.Length;
+    private static void ToEndLinksInplace(int[] array) {
+      var length = array.Length;
       for (var i = length - 1; i >= 0; i--) {
-        if (array[i] == i) a[i] = i;
-        else a[i] = a[a[i]];
+        var next = array[i];
+        if (next > i) {
+          array[i] = array[next];
+        } else if (next < i) {
+          throw new ArgumentException("Array is malformed and does not represent a valid LLE encoding.", "array");
+        }
       }
     }
@@ -253,18 +342,23 @@
     /// <remarks>
     /// This operation runs in O(n) time, but requires additional memory
-    /// in form of a dictionary.
+    /// in form of a int[].
     /// </remarks>
     /// <param name="llee">The LLE-e representation</param>
-    public void FromLLEe(int[] llee) {
+    public void SetEndLinks(int[] llee) {
       var length = array.Length;
-      var groups = new Dictionary<int, int>();
+      if (length != llee.Length) {
+        throw new ArgumentException(string.Format("Expected length {0} but length was {1}", length, llee.Length), "llee");
+      }
+      // If we are ok with mutating llee we can avoid this clone
+      var lookup = (int[])llee.Clone();
       for (var i = length - 1; i >= 0; i--) {
-        if (llee[i] == i) {
-          array[i] = i;
-          groups[i] = i;
+        var end = llee[i];
+        if (end == i) {
+          array[i] = end;
+        } else if (end > i && end < length) {
+          array[i] = lookup[end];
+          lookup[end] = i;
         } else {
-          var g = llee[i];
-          array[i] = groups[g];
-          groups[g] = i;
+          throw new ArgumentException("Array is malformed and does not represent a valid LLE end encoding.", "llee");
         }
       }
Index: branches/symbreg-factors-2650/HeuristicLab.Encodings.LinearLinkageEncoding/3.3/Plugin.cs.frame
===================================================================
--- branches/symbreg-factors-2650/HeuristicLab.Encodings.LinearLinkageEncoding/3.3/Plugin.cs.frame	(revision 14497)
+++ branches/symbreg-factors-2650/HeuristicLab.Encodings.LinearLinkageEncoding/3.3/Plugin.cs.frame	(revision 14498)
@@ -23,6 +23,6 @@
 
 namespace HeuristicLab.Encodings.LinearLinkageEncoding {
-  [Plugin("HeuristicLab.Encodings.LinearLinkageEncoding", "Provides data structures and operators for the linear linkage encoding (LLE).", "3.3.14.$WCREV$")]
-  [PluginFile("HeuristicLab.Encodings.LinearLinkageEncoding-3.3.dll", PluginFileType.Assembly)]
+  [Plugin("HeuristicLab.Encodings.LinearLinkageEncoding", "Provides data structures and operators for the linear linkage encoding (LLE).", "3.4.14.$WCREV$")]
+  [PluginFile("HeuristicLab.Encodings.LinearLinkageEncoding-3.4.dll", PluginFileType.Assembly)]
   [PluginDependency("HeuristicLab.Collections", "3.3")]
   [PluginDependency("HeuristicLab.Common", "3.3")]
Index: branches/symbreg-factors-2650/HeuristicLab.Encodings.LinearLinkageEncoding/3.3/Properties/AssemblyInfo.cs.frame
===================================================================
--- branches/symbreg-factors-2650/HeuristicLab.Encodings.LinearLinkageEncoding/3.3/Properties/AssemblyInfo.cs.frame	(revision 14497)
+++ branches/symbreg-factors-2650/HeuristicLab.Encodings.LinearLinkageEncoding/3.3/Properties/AssemblyInfo.cs.frame	(revision 14498)
@@ -53,4 +53,4 @@
 // by using the '*' as shown below:
 // [assembly: AssemblyVersion("1.0.*")]
-[assembly: AssemblyVersion("3.3.0.0")]
-[assembly: AssemblyFileVersion("3.3.14.$WCREV$")]
+[assembly: AssemblyVersion("3.4.0.0")]
+[assembly: AssemblyFileVersion("3.4.14.$WCREV$")]
Index: branches/symbreg-factors-2650/HeuristicLab.Optimization/3.3/Termination/MultiTerminator.cs
===================================================================
--- branches/symbreg-factors-2650/HeuristicLab.Optimization/3.3/Termination/MultiTerminator.cs	(revision 14497)
+++ branches/symbreg-factors-2650/HeuristicLab.Optimization/3.3/Termination/MultiTerminator.cs	(revision 14498)
@@ -38,5 +38,5 @@
       get { return HeuristicLab.Common.Resources.VSImageLibrary.FlagRed; }
     }
-
+    
     public ILookupParameter<BoolValue> TerminateParameter {
       get { return (ILookupParameter<BoolValue>)Parameters["Terminate"]; }
Index: branches/symbreg-factors-2650/HeuristicLab.Problems.DataAnalysis.Symbolic.Views/3.4/InteractiveSymbolicDataAnalysisSolutionSimplifierView.cs
===================================================================
--- branches/symbreg-factors-2650/HeuristicLab.Problems.DataAnalysis.Symbolic.Views/3.4/InteractiveSymbolicDataAnalysisSolutionSimplifierView.cs	(revision 14497)
+++ branches/symbreg-factors-2650/HeuristicLab.Problems.DataAnalysis.Symbolic.Views/3.4/InteractiveSymbolicDataAnalysisSolutionSimplifierView.cs	(revision 14498)
@@ -112,5 +112,14 @@
       treeChart.Tree = tree;
       treeChart.Repaint();
-      bool valid = !tree.IterateNodesPostfix().Any(node => node.SubtreeCount < GetMinArity(node.Symbol) || node.SubtreeCount > node.Symbol.MaximumArity);
+      // check if all nodes have a legal arity
+      var nodes = tree.IterateNodesPostfix().ToList();
+      bool valid = !nodes.Any(node => node.SubtreeCount < GetMinArity(node.Symbol) || node.SubtreeCount > node.Symbol.MaximumArity);
+
+      if (valid) {
+        // check if all variables are contained in the dataset
+        var variables = new HashSet<string>(Content.ProblemData.Dataset.DoubleVariables);
+        valid = nodes.OfType<VariableTreeNode>().All(x => variables.Contains(x.VariableName));
+      }
+
       if (valid) {
         btnOptimizeConstants.Enabled = true;
Index: branches/symbreg-factors-2650/HeuristicLab.Problems.DataAnalysis.Views/3.4/FeatureCorrelation/FeatureCorrelationCalculator.cs
===================================================================
--- branches/symbreg-factors-2650/HeuristicLab.Problems.DataAnalysis.Views/3.4/FeatureCorrelation/FeatureCorrelationCalculator.cs	(revision 14497)
+++ branches/symbreg-factors-2650/HeuristicLab.Problems.DataAnalysis.Views/3.4/FeatureCorrelation/FeatureCorrelationCalculator.cs	(revision 14498)
@@ -50,5 +50,5 @@
 
       IList<string> doubleVariableNames = dataset.DoubleVariables.ToList();
-      OnlineCalculatorError error = OnlineCalculatorError.None;
+
       int length = doubleVariableNames.Count;
       double[,] elements = new double[length, length];
@@ -68,4 +68,5 @@
           var var2 = dataset.GetDoubleValues(doubleVariableNames[j], indices);
 
+          OnlineCalculatorError error = OnlineCalculatorError.None;
           if (bwInfo.IgnoreMissingValues) {
             var filtered = FilterNaNValues(var1, var2);
@@ -78,8 +79,8 @@
           }
           elements[j, i] = elements[i, j];
-
         });
         worker.ReportProgress((int)(((double)counter) / length * 100));
       }
+
       e.Result = elements;
       worker.ReportProgress(100);
Index: branches/symbreg-factors-2650/HeuristicLab.Problems.DataAnalysis.Views/3.4/HeuristicLab.Problems.DataAnalysis.Views-3.4.csproj
===================================================================
--- branches/symbreg-factors-2650/HeuristicLab.Problems.DataAnalysis.Views/3.4/HeuristicLab.Problems.DataAnalysis.Views-3.4.csproj	(revision 14497)
+++ branches/symbreg-factors-2650/HeuristicLab.Problems.DataAnalysis.Views/3.4/HeuristicLab.Problems.DataAnalysis.Views-3.4.csproj	(revision 14498)
@@ -252,4 +252,16 @@
     <Compile Include="Regression\RegressionFeatureCorrelationView.Designer.cs">
       <DependentUpon>RegressionFeatureCorrelationView.cs</DependentUpon>
+    </Compile>
+    <Compile Include="Regression\RegressionSolutionLineChartViewBase.cs">
+      <SubType>UserControl</SubType>
+    </Compile>
+    <Compile Include="Regression\RegressionSolutionLineChartViewBase.Designer.cs">
+      <DependentUpon>RegressionSolutionLineChartViewBase.cs</DependentUpon>
+    </Compile>
+    <Compile Include="Regression\RegressionSolutionResidualsLineChartView.cs">
+      <SubType>UserControl</SubType>
+    </Compile>
+    <Compile Include="Regression\RegressionSolutionResidualsLineChartView.Designer.cs">
+      <DependentUpon>RegressionSolutionResidualsLineChartView.cs</DependentUpon>
     </Compile>
     <Compile Include="Regression\RegressionSolutionVariableImpactsView.cs">
Index: branches/symbreg-factors-2650/HeuristicLab.Problems.DataAnalysis.Views/3.4/Regression/RegressionSolutionLineChartView.Designer.cs
===================================================================
--- branches/symbreg-factors-2650/HeuristicLab.Problems.DataAnalysis.Views/3.4/Regression/RegressionSolutionLineChartView.Designer.cs	(revision 14497)
+++ branches/symbreg-factors-2650/HeuristicLab.Problems.DataAnalysis.Views/3.4/Regression/RegressionSolutionLineChartView.Designer.cs	(revision 14498)
@@ -44,38 +44,4 @@
     /// </summary>
     private void InitializeComponent() {
-      System.Windows.Forms.DataVisualization.Charting.ChartArea chartArea1 = new System.Windows.Forms.DataVisualization.Charting.ChartArea();
-      System.Windows.Forms.DataVisualization.Charting.Legend legend1 = new System.Windows.Forms.DataVisualization.Charting.Legend();
-      this.chart = new HeuristicLab.Visualization.ChartControlsExtensions.EnhancedChart();
-      ((System.ComponentModel.ISupportInitialize)(this.chart)).BeginInit();
-      this.SuspendLayout();
-      // 
-      // chart
-      // 
-      chartArea1.Name = "ChartArea";
-      this.chart.ChartAreas.Add(chartArea1);
-      this.chart.Dock = System.Windows.Forms.DockStyle.Fill;
-      legend1.Alignment = System.Drawing.StringAlignment.Center;
-      legend1.Docking = System.Windows.Forms.DataVisualization.Charting.Docking.Top;
-      legend1.Name = "Default";
-      this.chart.Legends.Add(legend1);
-      this.chart.Location = new System.Drawing.Point(0, 0);
-      this.chart.Name = "chart";
-      this.chart.Size = new System.Drawing.Size(358, 225);
-      this.chart.TabIndex = 0;
-      this.chart.CustomizeLegend += new System.EventHandler<System.Windows.Forms.DataVisualization.Charting.CustomizeLegendEventArgs>(this.chart_CustomizeLegend);
-      this.chart.MouseDoubleClick += new System.Windows.Forms.MouseEventHandler(this.Chart_MouseDoubleClick);
-      this.chart.MouseDown += new System.Windows.Forms.MouseEventHandler(this.chart_MouseDown);
-      this.chart.MouseMove += new System.Windows.Forms.MouseEventHandler(this.chart_MouseMove);
-      // 
-      // RegressionSolutionLineChartView
-      // 
-      this.AllowDrop = true;
-      this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F);
-      this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Inherit;
-      this.Controls.Add(this.chart);
-      this.Name = "RegressionSolutionLineChartView";
-      this.Size = new System.Drawing.Size(358, 225);
-      ((System.ComponentModel.ISupportInitialize)(this.chart)).EndInit();
-      this.ResumeLayout(false);
 
     }
@@ -83,5 +49,4 @@
     #endregion
 
-    private HeuristicLab.Visualization.ChartControlsExtensions.EnhancedChart chart;
   }
 }
Index: branches/symbreg-factors-2650/HeuristicLab.Problems.DataAnalysis.Views/3.4/Regression/RegressionSolutionLineChartView.cs
===================================================================
--- branches/symbreg-factors-2650/HeuristicLab.Problems.DataAnalysis.Views/3.4/Regression/RegressionSolutionLineChartView.cs	(revision 14497)
+++ branches/symbreg-factors-2650/HeuristicLab.Problems.DataAnalysis.Views/3.4/Regression/RegressionSolutionLineChartView.cs	(revision 14498)
@@ -19,306 +19,35 @@
  */
 #endregion
+
 using System;
-using System.Collections.Generic;
-using System.Drawing;
 using System.Linq;
-using System.Windows.Forms;
 using System.Windows.Forms.DataVisualization.Charting;
 using HeuristicLab.MainForm;
-using HeuristicLab.Visualization.ChartControlsExtensions;
+
 
 namespace HeuristicLab.Problems.DataAnalysis.Views {
   [View("Line Chart")]
   [Content(typeof(IRegressionSolution))]
-  public partial class RegressionSolutionLineChartView : DataAnalysisSolutionEvaluationView {
-    private const string TARGETVARIABLE_SERIES_NAME = "Target Variable";
-    private const string ESTIMATEDVALUES_TRAINING_SERIES_NAME = "Estimated Values (training)";
-    private const string ESTIMATEDVALUES_TEST_SERIES_NAME = "Estimated Values (test)";
-    private const string ESTIMATEDVALUES_ALL_SERIES_NAME = "Estimated Values (all samples)";
+  public partial class RegressionSolutionLineChartView : RegressionSolutionLineChartViewBase {
 
-    public new IRegressionSolution Content {
-      get { return (IRegressionSolution)base.Content; }
-      set { base.Content = value; }
-    }
 
     public RegressionSolutionLineChartView()
       : base() {
       InitializeComponent();
-      //configure axis
-      this.chart.CustomizeAllChartAreas();
-      this.chart.ChartAreas[0].CursorX.IsUserSelectionEnabled = true;
-      this.chart.ChartAreas[0].AxisX.ScaleView.Zoomable = true;
-      this.chart.ChartAreas[0].AxisX.IsStartedFromZero = true;
-      this.chart.ChartAreas[0].CursorX.Interval = 1;
-
-      this.chart.ChartAreas[0].CursorY.IsUserSelectionEnabled = true;
-      this.chart.ChartAreas[0].AxisY.ScaleView.Zoomable = true;
-      this.chart.ChartAreas[0].CursorY.Interval = 0;
     }
 
-    protected virtual void GetTrainingSeries(out int[] x, out double[] y) {
-      x = Content.ProblemData.TrainingIndices.ToArray();
+    protected override void GetTrainingSeries(out int[] idx, out double[] y) {
+      idx = Content.ProblemData.TrainingIndices.ToArray();
       y = Content.EstimatedTrainingValues.ToArray();
     }
 
-    protected virtual void GetTestSeries(out int[] x, out double[] y) {
-      x = Content.ProblemData.TestIndices.ToArray();
+    protected override void GetTestSeries(out int[] idx, out double[] y) {
+      idx = Content.ProblemData.TestIndices.ToArray();
       y = Content.EstimatedTestValues.ToArray();
     }
 
-    protected virtual void GetAllValuesSeries(out int[] x, out double[] y) {
-      x = Enumerable.Range(0, Content.ProblemData.Dataset.Rows).Except(Content.ProblemData.TrainingIndices).Except(Content.ProblemData.TestIndices).ToArray();
-      var tmp = Content.EstimatedValues.ToArray();
-      y = x.Select(index => tmp[index]).ToArray();
-    }
-
-    private void RedrawChart() {
-      this.chart.Series.Clear();
-      if (Content != null) {
-        this.chart.ChartAreas[0].AxisX.Minimum = 0;
-        this.chart.ChartAreas[0].AxisX.Maximum = Content.ProblemData.Dataset.Rows - 1;
-
-        this.chart.Series.Add(TARGETVARIABLE_SERIES_NAME);
-        this.chart.Series[TARGETVARIABLE_SERIES_NAME].LegendText = TARGETVARIABLE_SERIES_NAME;
-        this.chart.Series[TARGETVARIABLE_SERIES_NAME].ChartType = SeriesChartType.FastLine;
-        this.chart.Series[TARGETVARIABLE_SERIES_NAME].Points.DataBindXY(Enumerable.Range(0, Content.ProblemData.Dataset.Rows).ToArray(),
-          Content.ProblemData.Dataset.GetDoubleValues(Content.ProblemData.TargetVariable).ToArray());
-        // training series
-        this.chart.Series.Add(ESTIMATEDVALUES_TRAINING_SERIES_NAME);
-        this.chart.Series[ESTIMATEDVALUES_TRAINING_SERIES_NAME].LegendText = ESTIMATEDVALUES_TRAINING_SERIES_NAME;
-        this.chart.Series[ESTIMATEDVALUES_TRAINING_SERIES_NAME].ChartType = SeriesChartType.FastLine;
-        this.chart.Series[ESTIMATEDVALUES_TRAINING_SERIES_NAME].EmptyPointStyle.Color = this.chart.Series[ESTIMATEDVALUES_TRAINING_SERIES_NAME].Color;
-        int[] trainingIdx;
-        double[] trainingY;
-        GetTrainingSeries(out trainingIdx, out trainingY);
-        this.chart.Series[ESTIMATEDVALUES_TRAINING_SERIES_NAME].Points.DataBindXY(trainingIdx, trainingY);
-        this.InsertEmptyPoints(this.chart.Series[ESTIMATEDVALUES_TRAINING_SERIES_NAME]);
-        this.chart.Series[ESTIMATEDVALUES_TRAINING_SERIES_NAME].Tag = Content;
-
-        // test series
-        this.chart.Series.Add(ESTIMATEDVALUES_TEST_SERIES_NAME);
-        this.chart.Series[ESTIMATEDVALUES_TEST_SERIES_NAME].LegendText = ESTIMATEDVALUES_TEST_SERIES_NAME;
-        this.chart.Series[ESTIMATEDVALUES_TEST_SERIES_NAME].ChartType = SeriesChartType.FastLine;
-        int[] testIdx;
-        double[] testY;
-        GetTestSeries(out testIdx, out testY);
-        this.chart.Series[ESTIMATEDVALUES_TEST_SERIES_NAME].Points.DataBindXY(testIdx, testY);
-        this.InsertEmptyPoints(this.chart.Series[ESTIMATEDVALUES_TEST_SERIES_NAME]);
-        this.chart.Series[ESTIMATEDVALUES_TEST_SERIES_NAME].Tag = Content;
-
-        // series of remaining points
-        int[] allIdx;
-        double[] allEstimatedValues;
-        GetAllValuesSeries(out allIdx, out allEstimatedValues);
-
-        this.chart.Series.Add(ESTIMATEDVALUES_ALL_SERIES_NAME);
-        this.chart.Series[ESTIMATEDVALUES_ALL_SERIES_NAME].LegendText = ESTIMATEDVALUES_ALL_SERIES_NAME;
-        this.chart.Series[ESTIMATEDVALUES_ALL_SERIES_NAME].ChartType = SeriesChartType.FastLine;
-        if (allEstimatedValues.Length > 0) {
-          this.chart.Series[ESTIMATEDVALUES_ALL_SERIES_NAME].Points.DataBindXY(allIdx, allEstimatedValues);
-          this.InsertEmptyPoints(this.chart.Series[ESTIMATEDVALUES_ALL_SERIES_NAME]);
-        }
-        this.chart.Series[ESTIMATEDVALUES_ALL_SERIES_NAME].Tag = Content;
-        this.ToggleSeriesData(this.chart.Series[ESTIMATEDVALUES_ALL_SERIES_NAME]);
-
-        // set the y-axis
-        var axisY = this.chart.ChartAreas[0].AxisY;
-        axisY.Title = Content.ProblemData.TargetVariable;
-        double min = double.MaxValue, max = double.MinValue;
-        foreach (var point in chart.Series.SelectMany(x => x.Points)) {
-          if (!point.YValues.Any() || double.IsInfinity(point.YValues[0]) || double.IsNaN(point.YValues[0]))
-            continue;
-          var y = point.YValues[0];
-          if (y < min)
-            min = y;
-          if (y > max)
-            max = y;
-        }
-
-        double axisMin, axisMax, axisInterval;
-        ChartUtil.CalculateOptimalAxisInterval(min, max, out axisMin, out axisMax, out axisInterval);
-        axisY.Minimum = axisMin;
-        axisY.Maximum = axisMax;
-        axisY.Interval = axisInterval;
-
-        UpdateCursorInterval();
-        this.UpdateStripLines();
-      }
-    }
-
-    private void InsertEmptyPoints(Series series) {
-      int i = 0;
-      while (i < series.Points.Count - 1) {
-        if (series.Points[i].IsEmpty) {
-          ++i;
-          continue;
-        }
-
-        var p1 = series.Points[i];
-        var p2 = series.Points[i + 1];
-        // check for consecutive indices
-        if ((int)p2.XValue - (int)p1.XValue != 1) {
-          // insert an empty point between p1 and p2 so that the line will be invisible (transparent)
-          var p = new DataPoint((int)((p1.XValue + p2.XValue) / 2), 0.0) { IsEmpty = true };
-          series.Points.Insert(i + 1, p);
-        }
-        ++i;
-      }
-    }
-
-    private void UpdateCursorInterval() {
-      var estimatedValues = this.chart.Series[ESTIMATEDVALUES_TRAINING_SERIES_NAME].Points.Select(x => x.YValues[0]).DefaultIfEmpty(1.0);
-      var targetValues = this.chart.Series[TARGETVARIABLE_SERIES_NAME].Points.Select(x => x.YValues[0]).DefaultIfEmpty(1.0);
-      double estimatedValuesRange = estimatedValues.Max() - estimatedValues.Min();
-      double targetValuesRange = targetValues.Max() - targetValues.Min();
-      double interestingValuesRange = Math.Min(Math.Max(targetValuesRange, 1.0), Math.Max(estimatedValuesRange, 1.0));
-      double digits = (int)Math.Log10(interestingValuesRange) - 3;
-      double yZoomInterval = Math.Max(Math.Pow(10, digits), 10E-5);
-      this.chart.ChartAreas[0].CursorY.Interval = yZoomInterval;
-    }
-
-    #region events
-    protected override void RegisterContentEvents() {
-      base.RegisterContentEvents();
-      Content.ModelChanged += new EventHandler(Content_ModelChanged);
-      Content.ProblemDataChanged += new EventHandler(Content_ProblemDataChanged);
-    }
-    protected override void DeregisterContentEvents() {
-      base.DeregisterContentEvents();
-      Content.ModelChanged -= new EventHandler(Content_ModelChanged);
-      Content.ProblemDataChanged -= new EventHandler(Content_ProblemDataChanged);
-    }
-
-    protected override void OnContentChanged() {
-      base.OnContentChanged();
-      RedrawChart();
-    }
-    private void Content_ProblemDataChanged(object sender, EventArgs e) {
-      RedrawChart();
-    }
-    private void Content_ModelChanged(object sender, EventArgs e) {
-      RedrawChart();
-    }
-
-
-
-    private void Chart_MouseDoubleClick(object sender, MouseEventArgs e) {
-      HitTestResult result = chart.HitTest(e.X, e.Y);
-      if (result.ChartArea != null && (result.ChartElementType == ChartElementType.PlottingArea ||
-                                       result.ChartElementType == ChartElementType.Gridlines) ||
-                                       result.ChartElementType == ChartElementType.StripLines) {
-        foreach (var axis in result.ChartArea.Axes)
-          axis.ScaleView.ZoomReset(int.MaxValue);
-      }
-    }
-    #endregion
-
-    private void UpdateStripLines() {
-      this.chart.ChartAreas[0].AxisX.StripLines.Clear();
-
-      int[] attr = new int[Content.ProblemData.Dataset.Rows + 1]; // add a virtual last row that is again empty to simplify loop further down
-      foreach (var row in Content.ProblemData.TrainingIndices) {
-        attr[row] += 1;
-      }
-      foreach (var row in Content.ProblemData.TestIndices) {
-        attr[row] += 2;
-      }
-      int start = 0;
-      int curAttr = attr[start];
-      for (int row = 0; row < attr.Length; row++) {
-        if (attr[row] != curAttr) {
-          switch (curAttr) {
-            case 0: break;
-            case 1:
-              this.CreateAndAddStripLine("Training", start, row, Color.FromArgb(40, Color.Green), Color.Transparent);
-              break;
-            case 2:
-              this.CreateAndAddStripLine("Test", start, row, Color.FromArgb(40, Color.Red), Color.Transparent);
-              break;
-            case 3:
-              this.CreateAndAddStripLine("Training and Test", start, row, Color.FromArgb(40, Color.Green), Color.FromArgb(40, Color.Red), ChartHatchStyle.WideUpwardDiagonal);
-              break;
-            default:
-              // should not happen
-              break;
-          }
-          curAttr = attr[row];
-          start = row;
-        }
-      }
-    }
-
-    private void CreateAndAddStripLine(string title, int start, int end, Color color, Color secondColor, ChartHatchStyle hatchStyle = ChartHatchStyle.None) {
-      StripLine stripLine = new StripLine();
-      stripLine.BackColor = color;
-      stripLine.BackSecondaryColor = secondColor;
-      stripLine.BackHatchStyle = hatchStyle;
-      stripLine.Text = title;
-      stripLine.Font = new Font("Times New Roman", 12, FontStyle.Bold);
-      // strip range is [start .. end] inclusive, but we evaluate [start..end[ (end is exclusive)
-      // the strip should be by one longer (starting at start - 0.5 and ending at end + 0.5)
-      stripLine.StripWidth = end - start;
-      stripLine.IntervalOffset = start - 0.5; // start slightly to the left of the first point to clearly indicate the first point in the partition
-      this.chart.ChartAreas[0].AxisX.StripLines.Add(stripLine);
-    }
-
-    private void ToggleSeriesData(Series series) {
-      if (series.Points.Count > 0) {  //checks if series is shown
-        if (this.chart.Series.Any(s => s != series && s.Points.Count > 0)) {
-          ClearPointsQuick(series.Points);
-        }
-      } else if (Content != null) {
-
-        int[] indices = null;
-        double[] predictedValues = null;
-        switch (series.Name) {
-          case ESTIMATEDVALUES_ALL_SERIES_NAME:
-            GetAllValuesSeries(out indices, out predictedValues);
-            break;
-          case ESTIMATEDVALUES_TRAINING_SERIES_NAME:
-            GetTrainingSeries(out indices, out predictedValues);
-            break;
-          case ESTIMATEDVALUES_TEST_SERIES_NAME:
-            GetTestSeries(out indices, out predictedValues);
-            break;
-        }
-        if (predictedValues.Length > 0) {
-          series.Points.DataBindXY(indices, predictedValues);
-          this.InsertEmptyPoints(series);
-        }
-        chart.Legends[series.Legend].ForeColor = Color.Black;
-        UpdateCursorInterval();
-        chart.Refresh();
-      }
-    }
-
-    // workaround as per http://stackoverflow.com/questions/5744930/datapointcollection-clear-performance
-    private static void ClearPointsQuick(DataPointCollection points) {
-      points.SuspendUpdates();
-      while (points.Count > 0)
-        points.RemoveAt(points.Count - 1);
-      points.ResumeUpdates();
-    }
-
-    private void chart_MouseMove(object sender, MouseEventArgs e) {
-      HitTestResult result = chart.HitTest(e.X, e.Y);
-      if (result.ChartElementType == ChartElementType.LegendItem && result.Series.Name != TARGETVARIABLE_SERIES_NAME)
-        Cursor = Cursors.Hand;
-      else
-        Cursor = Cursors.Default;
-    }
-    private void chart_MouseDown(object sender, MouseEventArgs e) {
-      HitTestResult result = chart.HitTest(e.X, e.Y);
-      if (result.ChartElementType == ChartElementType.LegendItem && result.Series.Name != TARGETVARIABLE_SERIES_NAME) {
-        ToggleSeriesData(result.Series);
-      }
-    }
-
-    private void chart_CustomizeLegend(object sender, CustomizeLegendEventArgs e) {
-      if (chart.Series.Count != 4) return;
-      e.LegendItems[0].Cells[1].ForeColor = this.chart.Series[TARGETVARIABLE_SERIES_NAME].Points.Count == 0 ? Color.Gray : Color.Black;
-      e.LegendItems[1].Cells[1].ForeColor = this.chart.Series[ESTIMATEDVALUES_TRAINING_SERIES_NAME].Points.Count == 0 ? Color.Gray : Color.Black;
-      e.LegendItems[2].Cells[1].ForeColor = this.chart.Series[ESTIMATEDVALUES_TEST_SERIES_NAME].Points.Count == 0 ? Color.Gray : Color.Black;
-      e.LegendItems[3].Cells[1].ForeColor = this.chart.Series[ESTIMATEDVALUES_ALL_SERIES_NAME].Points.Count == 0 ? Color.Gray : Color.Black;
+    protected override void GetAllValuesSeries(out int[] idx, out double[] y) {
+      idx = Content.ProblemData.AllIndices.ToArray();
+      y = Content.EstimatedValues.ToArray();
     }
   }
Index: branches/symbreg-factors-2650/HeuristicLab.Problems.DataAnalysis.Views/3.4/Regression/RegressionSolutionLineChartViewBase.Designer.cs
===================================================================
--- branches/symbreg-factors-2650/HeuristicLab.Problems.DataAnalysis.Views/3.4/Regression/RegressionSolutionLineChartViewBase.Designer.cs	(revision 14498)
+++ branches/symbreg-factors-2650/HeuristicLab.Problems.DataAnalysis.Views/3.4/Regression/RegressionSolutionLineChartViewBase.Designer.cs	(revision 14498)
@@ -0,0 +1,87 @@
+﻿#region License Information
+/* HeuristicLab
+ * Copyright (C) 2002-2016 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
+namespace HeuristicLab.Problems.DataAnalysis.Views {
+  partial class RegressionSolutionLineChartViewBase {
+    /// <summary> 
+    /// Required designer variable.
+    /// </summary>
+    private System.ComponentModel.IContainer components = null;
+
+    /// <summary> 
+    /// Clean up any resources being used.
+    /// </summary>
+    /// <param name="disposing">true if managed resources should be disposed; otherwise, false.</param>
+    protected override void Dispose(bool disposing) {
+      if (disposing && (components != null)) {
+        components.Dispose();
+      }
+      base.Dispose(disposing);
+    }
+
+    #region Component Designer generated code
+
+    /// <summary> 
+    /// Required method for Designer support - do not modify 
+    /// the contents of this method with the code editor.
+    /// </summary>
+    private void InitializeComponent() {
+      System.Windows.Forms.DataVisualization.Charting.ChartArea chartArea1 = new System.Windows.Forms.DataVisualization.Charting.ChartArea();
+      System.Windows.Forms.DataVisualization.Charting.Legend legend1 = new System.Windows.Forms.DataVisualization.Charting.Legend();
+      this.chart = new HeuristicLab.Visualization.ChartControlsExtensions.EnhancedChart();
+      ((System.ComponentModel.ISupportInitialize)(this.chart)).BeginInit();
+      this.SuspendLayout();
+      // 
+      // chart
+      // 
+      chartArea1.Name = "ChartArea";
+      this.chart.ChartAreas.Add(chartArea1);
+      this.chart.Dock = System.Windows.Forms.DockStyle.Fill;
+      legend1.Alignment = System.Drawing.StringAlignment.Center;
+      legend1.Docking = System.Windows.Forms.DataVisualization.Charting.Docking.Top;
+      legend1.Name = "Default";
+      this.chart.Legends.Add(legend1);
+      this.chart.Location = new System.Drawing.Point(0, 0);
+      this.chart.Name = "chart";
+      this.chart.Size = new System.Drawing.Size(358, 225);
+      this.chart.TabIndex = 0;
+      this.chart.CustomizeLegend += new System.EventHandler<System.Windows.Forms.DataVisualization.Charting.CustomizeLegendEventArgs>(this.chart_CustomizeLegend);
+      this.chart.MouseDoubleClick += new System.Windows.Forms.MouseEventHandler(this.Chart_MouseDoubleClick);
+      this.chart.MouseDown += new System.Windows.Forms.MouseEventHandler(this.chart_MouseDown);
+      this.chart.MouseMove += new System.Windows.Forms.MouseEventHandler(this.chart_MouseMove);
+      // 
+      // RegressionSolutionLineChartView
+      // 
+      this.AllowDrop = true;
+      this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F);
+      this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Inherit;
+      this.Controls.Add(this.chart);
+      this.Name = "RegressionSolutionLineChartView";
+      this.Size = new System.Drawing.Size(358, 225);
+      ((System.ComponentModel.ISupportInitialize)(this.chart)).EndInit();
+      this.ResumeLayout(false);
+
+    }
+
+    #endregion
+
+    protected HeuristicLab.Visualization.ChartControlsExtensions.EnhancedChart chart;
+  }
+}
Index: branches/symbreg-factors-2650/HeuristicLab.Problems.DataAnalysis.Views/3.4/Regression/RegressionSolutionLineChartViewBase.cs
===================================================================
--- branches/symbreg-factors-2650/HeuristicLab.Problems.DataAnalysis.Views/3.4/Regression/RegressionSolutionLineChartViewBase.cs	(revision 14498)
+++ branches/symbreg-factors-2650/HeuristicLab.Problems.DataAnalysis.Views/3.4/Regression/RegressionSolutionLineChartViewBase.cs	(revision 14498)
@@ -0,0 +1,315 @@
+﻿#region License Information
+/* HeuristicLab
+ * Copyright (C) 2002-2016 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;
+using System.Collections.Generic;
+using System.Drawing;
+using System.Linq;
+using System.Windows.Forms;
+using System.Windows.Forms.DataVisualization.Charting;
+using HeuristicLab.MainForm;
+using HeuristicLab.Visualization.ChartControlsExtensions;
+
+namespace HeuristicLab.Problems.DataAnalysis.Views {
+  [View("Line Chart")]
+  [Content(typeof(IRegressionSolution))]
+  public abstract partial class RegressionSolutionLineChartViewBase : DataAnalysisSolutionEvaluationView {
+    protected const string TARGETVARIABLE_SERIES_NAME = "Target Variable";
+    protected const string ESTIMATEDVALUES_TRAINING_SERIES_NAME = "Estimated Values (training)";
+    protected const string ESTIMATEDVALUES_TEST_SERIES_NAME = "Estimated Values (test)";
+    protected const string ESTIMATEDVALUES_ALL_SERIES_NAME = "Estimated Values (all samples)";
+
+    public new IRegressionSolution Content {
+      get { return (IRegressionSolution)base.Content; }
+      set { base.Content = value; }
+    }
+
+    protected RegressionSolutionLineChartViewBase()
+      : base() {
+      InitializeComponent();
+      //configure axis
+      this.chart.CustomizeAllChartAreas();
+      this.chart.ChartAreas[0].CursorX.IsUserSelectionEnabled = true;
+      this.chart.ChartAreas[0].AxisX.ScaleView.Zoomable = true;
+      this.chart.ChartAreas[0].AxisX.IsStartedFromZero = true;
+      this.chart.ChartAreas[0].CursorX.Interval = 1;
+
+      this.chart.ChartAreas[0].CursorY.IsUserSelectionEnabled = true;
+      this.chart.ChartAreas[0].AxisY.ScaleView.Zoomable = true;
+      this.chart.ChartAreas[0].CursorY.Interval = 0;
+    }
+
+    protected abstract void GetTrainingSeries(out int[] idx, out double[] y);
+
+    protected abstract void GetTestSeries(out int[] x, out double[] y);
+
+    protected abstract void GetAllValuesSeries(out int[] x, out double[] y);
+
+    protected virtual void RedrawChart() {
+      this.chart.Series.Clear();
+      if (Content != null) {
+        this.chart.ChartAreas[0].AxisX.Minimum = 0;
+        this.chart.ChartAreas[0].AxisX.Maximum = Content.ProblemData.Dataset.Rows - 1;
+
+        this.chart.Series.Add(TARGETVARIABLE_SERIES_NAME);
+        this.chart.Series[TARGETVARIABLE_SERIES_NAME].LegendText = TARGETVARIABLE_SERIES_NAME;
+        this.chart.Series[TARGETVARIABLE_SERIES_NAME].ChartType = SeriesChartType.FastLine;
+        this.chart.Series[TARGETVARIABLE_SERIES_NAME].Points.DataBindXY(Enumerable.Range(0, Content.ProblemData.Dataset.Rows).ToArray(),
+          Content.ProblemData.Dataset.GetDoubleValues(Content.ProblemData.TargetVariable).ToArray());
+        // training series
+        this.chart.Series.Add(ESTIMATEDVALUES_TRAINING_SERIES_NAME);
+        this.chart.Series[ESTIMATEDVALUES_TRAINING_SERIES_NAME].LegendText = ESTIMATEDVALUES_TRAINING_SERIES_NAME;
+        this.chart.Series[ESTIMATEDVALUES_TRAINING_SERIES_NAME].ChartType = SeriesChartType.FastLine;
+        this.chart.Series[ESTIMATEDVALUES_TRAINING_SERIES_NAME].EmptyPointStyle.Color = this.chart.Series[ESTIMATEDVALUES_TRAINING_SERIES_NAME].Color;
+        int[] trainingIdx;
+        double[] trainingY;
+        GetTrainingSeries(out trainingIdx, out trainingY);
+        this.chart.Series[ESTIMATEDVALUES_TRAINING_SERIES_NAME].Points.DataBindXY(trainingIdx, trainingY);
+        this.InsertEmptyPoints(this.chart.Series[ESTIMATEDVALUES_TRAINING_SERIES_NAME]);
+        this.chart.Series[ESTIMATEDVALUES_TRAINING_SERIES_NAME].Tag = Content;
+
+        // test series
+        this.chart.Series.Add(ESTIMATEDVALUES_TEST_SERIES_NAME);
+        this.chart.Series[ESTIMATEDVALUES_TEST_SERIES_NAME].LegendText = ESTIMATEDVALUES_TEST_SERIES_NAME;
+        this.chart.Series[ESTIMATEDVALUES_TEST_SERIES_NAME].ChartType = SeriesChartType.FastLine;
+        int[] testIdx;
+        double[] testY;
+        GetTestSeries(out testIdx, out testY);
+        this.chart.Series[ESTIMATEDVALUES_TEST_SERIES_NAME].Points.DataBindXY(testIdx, testY);
+        this.InsertEmptyPoints(this.chart.Series[ESTIMATEDVALUES_TEST_SERIES_NAME]);
+        this.chart.Series[ESTIMATEDVALUES_TEST_SERIES_NAME].Tag = Content;
+
+        // series of remaining points
+        int[] allIdx;
+        double[] allEstimatedValues;
+        GetAllValuesSeries(out allIdx, out allEstimatedValues);
+
+        this.chart.Series.Add(ESTIMATEDVALUES_ALL_SERIES_NAME);
+        this.chart.Series[ESTIMATEDVALUES_ALL_SERIES_NAME].LegendText = ESTIMATEDVALUES_ALL_SERIES_NAME;
+        this.chart.Series[ESTIMATEDVALUES_ALL_SERIES_NAME].ChartType = SeriesChartType.FastLine;
+        if (allEstimatedValues.Length > 0) {
+          this.chart.Series[ESTIMATEDVALUES_ALL_SERIES_NAME].Points.DataBindXY(allIdx, allEstimatedValues);
+          this.InsertEmptyPoints(this.chart.Series[ESTIMATEDVALUES_ALL_SERIES_NAME]);
+        }
+        this.chart.Series[ESTIMATEDVALUES_ALL_SERIES_NAME].Tag = Content;
+        this.ToggleSeriesData(this.chart.Series[ESTIMATEDVALUES_ALL_SERIES_NAME]);
+
+        // set the y-axis
+        var axisY = this.chart.ChartAreas[0].AxisY;
+        axisY.Title = Content.ProblemData.TargetVariable;
+        double min = double.MaxValue, max = double.MinValue;
+        foreach (var point in chart.Series.SelectMany(x => x.Points)) {
+          if (!point.YValues.Any() || double.IsInfinity(point.YValues[0]) || double.IsNaN(point.YValues[0]))
+            continue;
+          var y = point.YValues[0];
+          if (y < min)
+            min = y;
+          if (y > max)
+            max = y;
+        }
+
+        double axisMin, axisMax, axisInterval;
+        ChartUtil.CalculateOptimalAxisInterval(min, max, out axisMin, out axisMax, out axisInterval);
+        axisY.Minimum = axisMin;
+        axisY.Maximum = axisMax;
+        axisY.Interval = axisInterval;
+
+        UpdateCursorInterval();
+        this.UpdateStripLines();
+      }
+    }
+
+    private void InsertEmptyPoints(Series series) {
+      int i = 0;
+      while (i < series.Points.Count - 1) {
+        if (series.Points[i].IsEmpty) {
+          ++i;
+          continue;
+        }
+
+        var p1 = series.Points[i];
+        var p2 = series.Points[i + 1];
+        // check for consecutive indices
+        if ((int)p2.XValue - (int)p1.XValue != 1) {
+          // insert an empty point between p1 and p2 so that the line will be invisible (transparent)
+          var p = new DataPoint((int)((p1.XValue + p2.XValue) / 2), 0.0) { IsEmpty = true };
+          series.Points.Insert(i + 1, p);
+        }
+        ++i;
+      }
+    }
+
+    private void UpdateCursorInterval() {
+      var estimatedValues = this.chart.Series[ESTIMATEDVALUES_TRAINING_SERIES_NAME].Points.Select(x => x.YValues[0]).DefaultIfEmpty(1.0);
+      var targetValues = this.chart.Series[TARGETVARIABLE_SERIES_NAME].Points.Select(x => x.YValues[0]).DefaultIfEmpty(1.0);
+      double estimatedValuesRange = estimatedValues.Max() - estimatedValues.Min();
+      double targetValuesRange = targetValues.Max() - targetValues.Min();
+      double interestingValuesRange = Math.Min(Math.Max(targetValuesRange, 1.0), Math.Max(estimatedValuesRange, 1.0));
+      double digits = (int)Math.Log10(interestingValuesRange) - 3;
+      double yZoomInterval = Math.Max(Math.Pow(10, digits), 10E-5);
+      this.chart.ChartAreas[0].CursorY.Interval = yZoomInterval;
+    }
+
+    #region events
+    protected override void RegisterContentEvents() {
+      base.RegisterContentEvents();
+      Content.ModelChanged += new EventHandler(Content_ModelChanged);
+      Content.ProblemDataChanged += new EventHandler(Content_ProblemDataChanged);
+    }
+    protected override void DeregisterContentEvents() {
+      base.DeregisterContentEvents();
+      Content.ModelChanged -= new EventHandler(Content_ModelChanged);
+      Content.ProblemDataChanged -= new EventHandler(Content_ProblemDataChanged);
+    }
+
+    protected override void OnContentChanged() {
+      base.OnContentChanged();
+      RedrawChart();
+    }
+    private void Content_ProblemDataChanged(object sender, EventArgs e) {
+      RedrawChart();
+    }
+    private void Content_ModelChanged(object sender, EventArgs e) {
+      RedrawChart();
+    }
+
+
+
+    private void Chart_MouseDoubleClick(object sender, MouseEventArgs e) {
+      HitTestResult result = chart.HitTest(e.X, e.Y);
+      if (result.ChartArea != null && (result.ChartElementType == ChartElementType.PlottingArea ||
+                                       result.ChartElementType == ChartElementType.Gridlines) ||
+                                       result.ChartElementType == ChartElementType.StripLines) {
+        foreach (var axis in result.ChartArea.Axes)
+          axis.ScaleView.ZoomReset(int.MaxValue);
+      }
+    }
+    #endregion
+
+    private void UpdateStripLines() {
+      this.chart.ChartAreas[0].AxisX.StripLines.Clear();
+
+      int[] attr = new int[Content.ProblemData.Dataset.Rows + 1]; // add a virtual last row that is again empty to simplify loop further down
+      foreach (var row in Content.ProblemData.TrainingIndices) {
+        attr[row] += 1;
+      }
+      foreach (var row in Content.ProblemData.TestIndices) {
+        attr[row] += 2;
+      }
+      int start = 0;
+      int curAttr = attr[start];
+      for (int row = 0; row < attr.Length; row++) {
+        if (attr[row] != curAttr) {
+          switch (curAttr) {
+            case 0: break;
+            case 1:
+              this.CreateAndAddStripLine("Training", start, row, Color.FromArgb(40, Color.Green), Color.Transparent);
+              break;
+            case 2:
+              this.CreateAndAddStripLine("Test", start, row, Color.FromArgb(40, Color.Red), Color.Transparent);
+              break;
+            case 3:
+              this.CreateAndAddStripLine("Training and Test", start, row, Color.FromArgb(40, Color.Green), Color.FromArgb(40, Color.Red), ChartHatchStyle.WideUpwardDiagonal);
+              break;
+            default:
+              // should not happen
+              break;
+          }
+          curAttr = attr[row];
+          start = row;
+        }
+      }
+    }
+
+    private void CreateAndAddStripLine(string title, int start, int end, Color color, Color secondColor, ChartHatchStyle hatchStyle = ChartHatchStyle.None) {
+      StripLine stripLine = new StripLine();
+      stripLine.BackColor = color;
+      stripLine.BackSecondaryColor = secondColor;
+      stripLine.BackHatchStyle = hatchStyle;
+      stripLine.Text = title;
+      stripLine.Font = new Font("Times New Roman", 12, FontStyle.Bold);
+      // strip range is [start .. end] inclusive, but we evaluate [start..end[ (end is exclusive)
+      // the strip should be by one longer (starting at start - 0.5 and ending at end + 0.5)
+      stripLine.StripWidth = end - start;
+      stripLine.IntervalOffset = start - 0.5; // start slightly to the left of the first point to clearly indicate the first point in the partition
+      this.chart.ChartAreas[0].AxisX.StripLines.Add(stripLine);
+    }
+
+    private void ToggleSeriesData(Series series) {
+      if (series.Points.Count > 0) {  //checks if series is shown
+        if (this.chart.Series.Any(s => s != series && s.Points.Count > 0)) {
+          ClearPointsQuick(series.Points);
+        }
+      } else if (Content != null) {
+
+        int[] indices = null;
+        double[] predictedValues = null;
+        switch (series.Name) {
+          case ESTIMATEDVALUES_ALL_SERIES_NAME:
+            GetAllValuesSeries(out indices, out predictedValues);
+            break;
+          case ESTIMATEDVALUES_TRAINING_SERIES_NAME:
+            GetTrainingSeries(out indices, out predictedValues);
+            break;
+          case ESTIMATEDVALUES_TEST_SERIES_NAME:
+            GetTestSeries(out indices, out predictedValues);
+            break;
+        }
+        if (predictedValues.Length > 0) {
+          series.Points.DataBindXY(indices, predictedValues);
+          this.InsertEmptyPoints(series);
+        }
+        chart.Legends[series.Legend].ForeColor = Color.Black;
+        UpdateCursorInterval();
+        chart.Refresh();
+      }
+    }
+
+    // workaround as per http://stackoverflow.com/questions/5744930/datapointcollection-clear-performance
+    private static void ClearPointsQuick(DataPointCollection points) {
+      points.SuspendUpdates();
+      while (points.Count > 0)
+        points.RemoveAt(points.Count - 1);
+      points.ResumeUpdates();
+    }
+
+    private void chart_MouseMove(object sender, MouseEventArgs e) {
+      HitTestResult result = chart.HitTest(e.X, e.Y);
+      if (result.ChartElementType == ChartElementType.LegendItem && result.Series.Name != TARGETVARIABLE_SERIES_NAME)
+        Cursor = Cursors.Hand;
+      else
+        Cursor = Cursors.Default;
+    }
+    private void chart_MouseDown(object sender, MouseEventArgs e) {
+      HitTestResult result = chart.HitTest(e.X, e.Y);
+      if (result.ChartElementType == ChartElementType.LegendItem && result.Series.Name != TARGETVARIABLE_SERIES_NAME) {
+        ToggleSeriesData(result.Series);
+      }
+    }
+
+    private void chart_CustomizeLegend(object sender, CustomizeLegendEventArgs e) {
+      if (chart.Series.Count != 4) return;
+      e.LegendItems[0].Cells[1].ForeColor = this.chart.Series[TARGETVARIABLE_SERIES_NAME].Points.Count == 0 ? Color.Gray : Color.Black;
+      e.LegendItems[1].Cells[1].ForeColor = this.chart.Series[ESTIMATEDVALUES_TRAINING_SERIES_NAME].Points.Count == 0 ? Color.Gray : Color.Black;
+      e.LegendItems[2].Cells[1].ForeColor = this.chart.Series[ESTIMATEDVALUES_TEST_SERIES_NAME].Points.Count == 0 ? Color.Gray : Color.Black;
+      e.LegendItems[3].Cells[1].ForeColor = this.chart.Series[ESTIMATEDVALUES_ALL_SERIES_NAME].Points.Count == 0 ? Color.Gray : Color.Black;
+    }
+  }
+}
Index: branches/symbreg-factors-2650/HeuristicLab.Problems.DataAnalysis.Views/3.4/Regression/RegressionSolutionResidualsLineChartView.Designer.cs
===================================================================
--- branches/symbreg-factors-2650/HeuristicLab.Problems.DataAnalysis.Views/3.4/Regression/RegressionSolutionResidualsLineChartView.Designer.cs	(revision 14498)
+++ branches/symbreg-factors-2650/HeuristicLab.Problems.DataAnalysis.Views/3.4/Regression/RegressionSolutionResidualsLineChartView.Designer.cs	(revision 14498)
@@ -0,0 +1,52 @@
+﻿#region License Information
+/* HeuristicLab
+ * Copyright (C) 2002-2016 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
+namespace HeuristicLab.Problems.DataAnalysis.Views {
+  partial class RegressionSolutionResidualsLineChartView {
+    /// <summary> 
+    /// Required designer variable.
+    /// </summary>
+    private System.ComponentModel.IContainer components = null;
+
+    /// <summary> 
+    /// Clean up any resources being used.
+    /// </summary>
+    /// <param name="disposing">true if managed resources should be disposed; otherwise, false.</param>
+    protected override void Dispose(bool disposing) {
+      if (disposing && (components != null)) {
+        components.Dispose();
+      }
+      base.Dispose(disposing);
+    }
+
+    #region Component Designer generated code
+
+    /// <summary> 
+    /// Required method for Designer support - do not modify 
+    /// the contents of this method with the code editor.
+    /// </summary>
+    private void InitializeComponent() {
+
+    }
+
+    #endregion
+
+  }
+}
Index: branches/symbreg-factors-2650/HeuristicLab.Problems.DataAnalysis.Views/3.4/Regression/RegressionSolutionResidualsLineChartView.cs
===================================================================
--- branches/symbreg-factors-2650/HeuristicLab.Problems.DataAnalysis.Views/3.4/Regression/RegressionSolutionResidualsLineChartView.cs	(revision 14498)
+++ branches/symbreg-factors-2650/HeuristicLab.Problems.DataAnalysis.Views/3.4/Regression/RegressionSolutionResidualsLineChartView.cs	(revision 14498)
@@ -0,0 +1,94 @@
+﻿#region License Information
+/* HeuristicLab
+ * Copyright (C) 2002-2016 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;
+using System.Linq;
+using System.Windows.Forms.DataVisualization.Charting;
+using HeuristicLab.MainForm;
+
+
+namespace HeuristicLab.Problems.DataAnalysis.Views {
+  [View("Residuals Line Chart")]
+  [Content(typeof(IRegressionSolution))]
+  public partial class RegressionSolutionResidualsLineChartView : RegressionSolutionLineChartViewBase, IDataAnalysisSolutionEvaluationView {
+
+
+    public RegressionSolutionResidualsLineChartView()
+      : base() {
+      InitializeComponent();
+    }
+
+    protected override void GetTrainingSeries(out int[] idx, out double[] y) {
+      idx = Content.ProblemData.TrainingIndices.ToArray();
+      y = Content.EstimatedTrainingValues.ToArray();
+      CalcResiduals(idx, y);
+    }
+
+    private void CalcResiduals(int[] idx, double[] x) {
+      var problemData = Content.ProblemData;
+      var target = problemData.Dataset.GetDoubleValues(problemData.TargetVariable, idx).ToArray();
+      for (int i = 0; i < idx.Length; i++) {
+        x[i] -= target[i];
+      }
+    }
+
+    protected override void GetTestSeries(out int[] idx, out double[] y) {
+      idx = Content.ProblemData.TestIndices.ToArray();
+      y = Content.EstimatedTestValues.ToArray();
+      CalcResiduals(idx, y);
+    }
+
+    protected override void GetAllValuesSeries(out int[] idx, out double[] y) {
+      idx = Content.ProblemData.AllIndices.ToArray();
+      y = Content.EstimatedValues.ToArray();
+      CalcResiduals(idx, y);
+    }
+
+    protected override void RedrawChart() {
+      base.RedrawChart();
+      UpdateSeriesStyle();
+    }
+
+    private void UpdateSeriesStyle() {
+      if (InvokeRequired) Invoke((Action)UpdateSeriesStyle);
+      else {
+        if (Content == null) return;
+        double[] res;
+        int[] idx;
+        GetTrainingSeries(out idx, out res);
+        base.chart.Series[RegressionSolutionLineChartView.ESTIMATEDVALUES_TRAINING_SERIES_NAME].YAxisType = AxisType.Secondary;
+        base.chart.Series[RegressionSolutionLineChartView.ESTIMATEDVALUES_TRAINING_SERIES_NAME].ChartType = SeriesChartType.RangeColumn;
+        base.chart.Series[RegressionSolutionLineChartView.ESTIMATEDVALUES_TRAINING_SERIES_NAME].Points.DataBindXY(idx, res.Select(_ => 0.0).ToArray(), res);
+
+        GetTestSeries(out idx, out res);
+        base.chart.Series[RegressionSolutionLineChartView.ESTIMATEDVALUES_TEST_SERIES_NAME].YAxisType = AxisType.Secondary;
+        base.chart.Series[RegressionSolutionLineChartView.ESTIMATEDVALUES_TEST_SERIES_NAME].ChartType = SeriesChartType.RangeColumn;
+        base.chart.Series[RegressionSolutionLineChartView.ESTIMATEDVALUES_TEST_SERIES_NAME].Points.DataBindXY(idx, res.Select(_ => 0.0).ToArray(), res);
+
+        GetAllValuesSeries(out idx, out res);
+        base.chart.Series[RegressionSolutionLineChartView.ESTIMATEDVALUES_ALL_SERIES_NAME].YAxisType = AxisType.Secondary;
+        base.chart.Series[RegressionSolutionLineChartView.ESTIMATEDVALUES_ALL_SERIES_NAME].ChartType = SeriesChartType.RangeColumn;
+        base.chart.Series[RegressionSolutionLineChartView.ESTIMATEDVALUES_ALL_SERIES_NAME].Points.DataBindXY(idx, res.Select(_ => 0.0).ToArray(), res);
+      }
+    }
+
+  }
+}
Index: branches/symbreg-factors-2650/HeuristicLab.Problems.DataAnalysis.Views/3.4/Regression/RegressionSolutionTargetResponseGradientView.cs
===================================================================
--- branches/symbreg-factors-2650/HeuristicLab.Problems.DataAnalysis.Views/3.4/Regression/RegressionSolutionTargetResponseGradientView.cs	(revision 14497)
+++ branches/symbreg-factors-2650/HeuristicLab.Problems.DataAnalysis.Views/3.4/Regression/RegressionSolutionTargetResponseGradientView.cs	(revision 14498)
@@ -113,6 +113,12 @@
       limitView.Content.Upper = axisMax;
 
-      // create dataset
-      var allowedInputVariables = Content.ProblemData.AllowedInputVariables;
+      // create dataset of problemData input variables and model input variables
+      // necessary workaround to have the variables in the occuring order
+      var inputvariables =
+        new HashSet<string>(Content.ProblemData.AllowedInputVariables.Union(Content.Model.VariablesUsedForPrediction));
+      var allowedInputVariables =
+        Content.ProblemData.Dataset.VariableNames.Where(v => inputvariables.Contains(v)).ToList();
+
+
       var doubleVariables = allowedInputVariables.Where(problemData.Dataset.VariableHasType<double>);
       var doubleVariableValues = (IEnumerable<IList>)doubleVariables.Select(x => new List<double> { problemData.Dataset.GetDoubleValues(x, problemData.TrainingIndices).Median() });
Index: branches/symbreg-factors-2650/HeuristicLab.Problems.DataAnalysis.Views/3.4/TimeSeriesPrognosis/TimeSeriesPrognosisLineChartView.cs
===================================================================
--- branches/symbreg-factors-2650/HeuristicLab.Problems.DataAnalysis.Views/3.4/TimeSeriesPrognosis/TimeSeriesPrognosisLineChartView.cs	(revision 14497)
+++ branches/symbreg-factors-2650/HeuristicLab.Problems.DataAnalysis.Views/3.4/TimeSeriesPrognosis/TimeSeriesPrognosisLineChartView.cs	(revision 14498)
@@ -40,13 +40,18 @@
     }
 
-    protected override void GetTestSeries(out int[] x, out double[] y) {
+    protected override void GetTrainingSeries(out int[] idx, out double[] y) {
+      idx = Content.ProblemData.TrainingIndices.ToArray();
+      y = Content.EstimatedTrainingValues.ToArray();
+    }
+
+    protected override void GetTestSeries(out int[] idx, out double[] y) {
       // treat the whole test partition as prognosis horizon
-      x = Content.ProblemData.TestIndices.ToArray();
+      idx = Content.ProblemData.TestIndices.ToArray();
       y = Content.PrognosedTestValues.ToArray();
     }
 
-    protected override void GetAllValuesSeries(out int[] x, out double[] y) {
+    protected override void GetAllValuesSeries(out int[] idx, out double[] y) {
       // not supported
-      x = new int[0];
+      idx = new int[0];
       y = new double[0];
     }
Index: branches/symbreg-factors-2650/HeuristicLab.Problems.DataAnalysis/3.4/Implementation/Regression/RegressionSolutionVariableImpactsCalculator.cs
===================================================================
--- branches/symbreg-factors-2650/HeuristicLab.Problems.DataAnalysis/3.4/Implementation/Regression/RegressionSolutionVariableImpactsCalculator.cs	(revision 14497)
+++ branches/symbreg-factors-2650/HeuristicLab.Problems.DataAnalysis/3.4/Implementation/Regression/RegressionSolutionVariableImpactsCalculator.cs	(revision 14498)
@@ -122,10 +122,12 @@
       }
 
-
       var impacts = new Dictionary<string, double>();
       var modifiableDataset = ((Dataset)dataset).ToModifiable();
 
+      var inputvariables = new HashSet<string>(problemData.AllowedInputVariables.Union(solution.Model.VariablesUsedForPrediction));
+      var allowedInputVariables = dataset.VariableNames.Where(v => inputvariables.Contains(v)).ToList();
+
       // calculate impacts for double variables
-      foreach (var inputVariable in problemData.AllowedInputVariables.Where(problemData.Dataset.VariableHasType<double>)) {
+      foreach (var inputVariable in allowedInputVariables.Where(problemData.Dataset.VariableHasType<double>)) {
         var newEstimates = EvaluateModelWithReplacedVariable(solution.Model, inputVariable, modifiableDataset, rows, replacementMethod);
         var newR2 = OnlinePearsonsRCalculator.Calculate(targetValues, newEstimates, out error);
@@ -137,5 +139,5 @@
       }
       // calculate impacts for factor variables
-      foreach (var inputVariable in problemData.AllowedInputVariables.Where(problemData.Dataset.VariableHasType<string>)) {
+      foreach (var inputVariable in allowedInputVariables.Where(problemData.Dataset.VariableHasType<string>)) {
         var smallestImpact = double.PositiveInfinity;
         foreach (var repl in problemData.Dataset.GetStringValues(inputVariable, rows).Distinct()) {
Index: branches/symbreg-factors-2650/HeuristicLab.Problems.DataAnalysis/3.4/OnlineCalculators/ClassificationPerformanceMeasuresCalculator.cs
===================================================================
--- branches/symbreg-factors-2650/HeuristicLab.Problems.DataAnalysis/3.4/OnlineCalculators/ClassificationPerformanceMeasuresCalculator.cs	(revision 14497)
+++ branches/symbreg-factors-2650/HeuristicLab.Problems.DataAnalysis/3.4/OnlineCalculators/ClassificationPerformanceMeasuresCalculator.cs	(revision 14498)
@@ -33,5 +33,6 @@
     }
 
-    protected ClassificationPerformanceMeasuresCalculator(ClassificationPerformanceMeasuresCalculator original, Cloner cloner) {
+    protected ClassificationPerformanceMeasuresCalculator(ClassificationPerformanceMeasuresCalculator original, Cloner cloner)
+      : base(original, cloner) {
       positiveClassName = original.positiveClassName;
       positiveClassValue = original.positiveClassValue;
@@ -41,4 +42,7 @@
       falseNegativeCount = original.falseNegativeCount;
       errorState = original.errorState;
+    }
+    public override IDeepCloneable Clone(Cloner cloner) {
+      return new ClassificationPerformanceMeasuresCalculator(this, cloner);
     }
 
@@ -147,8 +151,4 @@
       errorState = ErrorState;
     }
-
-    public override IDeepCloneable Clone(Cloner cloner) {
-      return new ClassificationPerformanceMeasuresCalculator(this, cloner);
-    }
   }
 }
Index: branches/symbreg-factors-2650/HeuristicLab.Problems.DataAnalysis/3.4/OnlineCalculators/OnlineBoundedMeanSquaredErrorCalculator.cs
===================================================================
--- branches/symbreg-factors-2650/HeuristicLab.Problems.DataAnalysis/3.4/OnlineCalculators/OnlineBoundedMeanSquaredErrorCalculator.cs	(revision 14497)
+++ branches/symbreg-factors-2650/HeuristicLab.Problems.DataAnalysis/3.4/OnlineCalculators/OnlineBoundedMeanSquaredErrorCalculator.cs	(revision 14498)
@@ -45,5 +45,6 @@
     }
 
-    protected OnlineBoundedMeanSquaredErrorCalculator(OnlineBoundedMeanSquaredErrorCalculator original, Cloner cloner) {
+    protected OnlineBoundedMeanSquaredErrorCalculator(OnlineBoundedMeanSquaredErrorCalculator original, Cloner cloner)
+      : base(original, cloner) {
       LowerBound = original.LowerBound;
       UpperBound = original.UpperBound;
@@ -51,4 +52,7 @@
       errorSum = original.errorSum;
       errorState = original.ErrorState;
+    }
+    public override IDeepCloneable Clone(Cloner cloner) {
+      return new OnlineBoundedMeanSquaredErrorCalculator(this, cloner);
     }
 
@@ -105,9 +109,4 @@
       }
     }
-
-    // IDeepCloneable interface members
-    public override IDeepCloneable Clone(Cloner cloner) {
-      return new OnlineBoundedMeanSquaredErrorCalculator(this, cloner);
-    }
   }
 }
Index: branches/symbreg-factors-2650/HeuristicLab.Problems.DataAnalysis/3.4/OnlineCalculators/OnlineCovarianceCalculator.cs
===================================================================
--- branches/symbreg-factors-2650/HeuristicLab.Problems.DataAnalysis/3.4/OnlineCalculators/OnlineCovarianceCalculator.cs	(revision 14497)
+++ branches/symbreg-factors-2650/HeuristicLab.Problems.DataAnalysis/3.4/OnlineCalculators/OnlineCovarianceCalculator.cs	(revision 14498)
@@ -39,10 +39,15 @@
     }
 
-    protected OnlineCovarianceCalculator(OnlineCovarianceCalculator other, Cloner cloner) {
-      Cn = other.Cn;
-      xMean = other.xMean;
-      yMean = other.yMean;
-      n = other.n;
-      errorState = other.errorState;
+    protected OnlineCovarianceCalculator(OnlineCovarianceCalculator original, Cloner cloner)
+      : base(original, cloner) {
+      Cn = original.Cn;
+      xMean = original.xMean;
+      yMean = original.yMean;
+      n = original.n;
+      errorState = original.errorState;
+    }
+
+    public override IDeepCloneable Clone(Cloner cloner) {
+      return new OnlineCovarianceCalculator(this, cloner);
     }
 
@@ -103,8 +108,4 @@
       }
     }
-
-    public override IDeepCloneable Clone(Cloner cloner) {
-      return new OnlineCovarianceCalculator(this, cloner);
-    }
   }
 }
Index: branches/symbreg-factors-2650/HeuristicLab.Problems.DataAnalysis/3.4/OnlineCalculators/OnlineDirectionalSymmetryCalculator.cs
===================================================================
--- branches/symbreg-factors-2650/HeuristicLab.Problems.DataAnalysis/3.4/OnlineCalculators/OnlineDirectionalSymmetryCalculator.cs	(revision 14497)
+++ branches/symbreg-factors-2650/HeuristicLab.Problems.DataAnalysis/3.4/OnlineCalculators/OnlineDirectionalSymmetryCalculator.cs	(revision 14498)
@@ -41,8 +41,13 @@
     }
 
-    protected OnlineDirectionalSymmetryCalculator(OnlineDirectionalSymmetryCalculator other, Cloner cloner = null) {
-      n = other.n;
-      nCorrect = other.nCorrect;
-      errorState = other.errorState;
+    protected OnlineDirectionalSymmetryCalculator(OnlineDirectionalSymmetryCalculator original, Cloner cloner = null)
+      : base(original, cloner) {
+      n = original.n;
+      nCorrect = original.nCorrect;
+      errorState = original.errorState;
+    }
+
+    public override IDeepCloneable Clone(Cloner cloner) {
+      return new OnlineDirectionalSymmetryCalculator(this, cloner);
     }
 
@@ -122,8 +127,4 @@
       }
     }
-
-    public override IDeepCloneable Clone(Cloner cloner) {
-      return new OnlineDirectionalSymmetryCalculator(this, cloner);
-    }
   }
 }
Index: branches/symbreg-factors-2650/HeuristicLab.Problems.DataAnalysis/3.4/OnlineCalculators/OnlineLinearScalingParameterCalculator.cs
===================================================================
--- branches/symbreg-factors-2650/HeuristicLab.Problems.DataAnalysis/3.4/OnlineCalculators/OnlineLinearScalingParameterCalculator.cs	(revision 14497)
+++ branches/symbreg-factors-2650/HeuristicLab.Problems.DataAnalysis/3.4/OnlineCalculators/OnlineLinearScalingParameterCalculator.cs	(revision 14498)
@@ -55,7 +55,7 @@
     }
 
-    private OnlineMeanAndVarianceCalculator targetMeanCalculator;
-    private OnlineMeanAndVarianceCalculator originalMeanAndVarianceCalculator;
-    private OnlineCovarianceCalculator originalTargetCovarianceCalculator;
+    private readonly OnlineMeanAndVarianceCalculator targetMeanCalculator;
+    private readonly OnlineMeanAndVarianceCalculator originalMeanAndVarianceCalculator;
+    private readonly OnlineCovarianceCalculator originalTargetCovarianceCalculator;
 
     public OnlineLinearScalingParameterCalculator() {
@@ -66,9 +66,13 @@
     }
 
-    protected OnlineLinearScalingParameterCalculator(OnlineLinearScalingParameterCalculator other, Cloner cloner) {
-      targetMeanCalculator = (OnlineMeanAndVarianceCalculator)other.targetMeanCalculator.Clone(cloner);
-      originalMeanAndVarianceCalculator = (OnlineMeanAndVarianceCalculator)other.originalMeanAndVarianceCalculator.Clone(cloner);
-      originalTargetCovarianceCalculator = (OnlineCovarianceCalculator)other.originalTargetCovarianceCalculator.Clone(cloner);
+    protected OnlineLinearScalingParameterCalculator(OnlineLinearScalingParameterCalculator original, Cloner cloner)
+      : base(original, cloner) {
+      targetMeanCalculator = cloner.Clone(original.targetMeanCalculator);
+      originalMeanAndVarianceCalculator = cloner.Clone(original.originalMeanAndVarianceCalculator);
+      originalTargetCovarianceCalculator = cloner.Clone(original.originalTargetCovarianceCalculator);
       // do not reset the calculators here
+    }
+    public override IDeepCloneable Clone(Cloner cloner) {
+      return new OnlineLinearScalingParameterCalculator(this, cloner);
     }
 
@@ -125,8 +129,4 @@
       }
     }
-
-    public override IDeepCloneable Clone(Cloner cloner) {
-      return new OnlineLinearScalingParameterCalculator(this, cloner);
-    }
   }
 }
Index: branches/symbreg-factors-2650/HeuristicLab.Problems.DataAnalysis/3.4/OnlineCalculators/OnlineMaxAbsoluteErrorCalculator.cs
===================================================================
--- branches/symbreg-factors-2650/HeuristicLab.Problems.DataAnalysis/3.4/OnlineCalculators/OnlineMaxAbsoluteErrorCalculator.cs	(revision 14497)
+++ branches/symbreg-factors-2650/HeuristicLab.Problems.DataAnalysis/3.4/OnlineCalculators/OnlineMaxAbsoluteErrorCalculator.cs	(revision 14498)
@@ -39,8 +39,12 @@
     }
 
-    protected OnlineMaxAbsoluteErrorCalculator(OnlineMaxAbsoluteErrorCalculator other, Cloner cloner = null) {
-      mae = other.mae;
-      n = other.n;
-      errorState = other.errorState;
+    protected OnlineMaxAbsoluteErrorCalculator(OnlineMaxAbsoluteErrorCalculator original, Cloner cloner = null)
+      : base(original, cloner) {
+      mae = original.mae;
+      n = original.n;
+      errorState = original.errorState;
+    }
+    public override IDeepCloneable Clone(Cloner cloner) {
+      return new OnlineMaxAbsoluteErrorCalculator(this, cloner);
     }
 
@@ -95,8 +99,4 @@
       }
     }
-
-    public override IDeepCloneable Clone(Cloner cloner) {
-      return new OnlineMaxAbsoluteErrorCalculator(this, cloner);
-    }
   }
 }
Index: branches/symbreg-factors-2650/HeuristicLab.Problems.DataAnalysis/3.4/OnlineCalculators/OnlineMeanAbsoluteErrorCalculator.cs
===================================================================
--- branches/symbreg-factors-2650/HeuristicLab.Problems.DataAnalysis/3.4/OnlineCalculators/OnlineMeanAbsoluteErrorCalculator.cs	(revision 14497)
+++ branches/symbreg-factors-2650/HeuristicLab.Problems.DataAnalysis/3.4/OnlineCalculators/OnlineMeanAbsoluteErrorCalculator.cs	(revision 14498)
@@ -39,8 +39,12 @@
     }
 
-    protected OnlineMeanAbsoluteErrorCalculator(OnlineMeanAbsoluteErrorCalculator other, Cloner cloner = null) {
-      sae = other.sae;
-      n = other.n;
-      errorState = other.errorState;
+    protected OnlineMeanAbsoluteErrorCalculator(OnlineMeanAbsoluteErrorCalculator original, Cloner cloner = null)
+      : base(original, cloner) {
+      sae = original.sae;
+      n = original.n;
+      errorState = original.errorState;
+    }
+    public override IDeepCloneable Clone(Cloner cloner) {
+      return new OnlineMeanAbsoluteErrorCalculator(this, cloner);
     }
 
@@ -94,8 +98,4 @@
       }
     }
-
-    public override IDeepCloneable Clone(Cloner cloner) {
-      return new OnlineMeanAbsoluteErrorCalculator(this, cloner);
-    }
   }
 }
Index: branches/symbreg-factors-2650/HeuristicLab.Problems.DataAnalysis/3.4/OnlineCalculators/OnlineMeanAbsolutePercentageErrorCalculator.cs
===================================================================
--- branches/symbreg-factors-2650/HeuristicLab.Problems.DataAnalysis/3.4/OnlineCalculators/OnlineMeanAbsolutePercentageErrorCalculator.cs	(revision 14497)
+++ branches/symbreg-factors-2650/HeuristicLab.Problems.DataAnalysis/3.4/OnlineCalculators/OnlineMeanAbsolutePercentageErrorCalculator.cs	(revision 14498)
@@ -39,8 +39,13 @@
     }
 
-    protected OnlineMeanAbsolutePercentageErrorCalculator(OnlineMeanAbsolutePercentageErrorCalculator other, Cloner cloner = null) {
-      sre = other.sre;
-      n = other.n;
-      errorState = other.errorState;
+    protected OnlineMeanAbsolutePercentageErrorCalculator(OnlineMeanAbsolutePercentageErrorCalculator original, Cloner cloner = null)
+      : base(original, cloner) {
+      sre = original.sre;
+      n = original.n;
+      errorState = original.errorState;
+    }
+
+    public override IDeepCloneable Clone(Cloner cloner) {
+      return new OnlineMeanAbsolutePercentageErrorCalculator(this, cloner);
     }
 
@@ -95,8 +100,4 @@
       }
     }
-
-    public override IDeepCloneable Clone(Cloner cloner) {
-      return new OnlineMeanAbsolutePercentageErrorCalculator(this, cloner);
-    }
   }
 }
Index: branches/symbreg-factors-2650/HeuristicLab.Problems.DataAnalysis/3.4/OnlineCalculators/OnlineMeanAndVarianceCalculator.cs
===================================================================
--- branches/symbreg-factors-2650/HeuristicLab.Problems.DataAnalysis/3.4/OnlineCalculators/OnlineMeanAndVarianceCalculator.cs	(revision 14497)
+++ branches/symbreg-factors-2650/HeuristicLab.Problems.DataAnalysis/3.4/OnlineCalculators/OnlineMeanAndVarianceCalculator.cs	(revision 14498)
@@ -67,12 +67,16 @@
     }
 
-    protected OnlineMeanAndVarianceCalculator(OnlineMeanAndVarianceCalculator other, Cloner cloner = null) {
-      m_oldS = other.m_oldS;
-      m_oldM = other.m_oldM;
-      m_newS = other.m_newS;
-      m_newM = other.m_newM;
-      n = other.n;
-      errorState = other.errorState;
-      varianceErrorState = other.varianceErrorState;
+    protected OnlineMeanAndVarianceCalculator(OnlineMeanAndVarianceCalculator original, Cloner cloner = null)
+      : base(original, cloner) {
+      m_oldS = original.m_oldS;
+      m_oldM = original.m_oldM;
+      m_newS = original.m_newS;
+      m_newM = original.m_newM;
+      n = original.n;
+      errorState = original.errorState;
+      varianceErrorState = original.varianceErrorState;
+    }
+    public override IDeepCloneable Clone(Cloner cloner) {
+      return new OnlineMeanAndVarianceCalculator(this, cloner);
     }
 
@@ -117,8 +121,4 @@
       varianceErrorState = meanAndVarianceCalculator.VarianceErrorState;
     }
-
-    public override IDeepCloneable Clone(Cloner cloner) {
-      return new OnlineMeanAndVarianceCalculator(this, cloner);
-    }
   }
 }
Index: branches/symbreg-factors-2650/HeuristicLab.Problems.DataAnalysis/3.4/OnlineCalculators/OnlineMeanErrorCalculator.cs
===================================================================
--- branches/symbreg-factors-2650/HeuristicLab.Problems.DataAnalysis/3.4/OnlineCalculators/OnlineMeanErrorCalculator.cs	(revision 14497)
+++ branches/symbreg-factors-2650/HeuristicLab.Problems.DataAnalysis/3.4/OnlineCalculators/OnlineMeanErrorCalculator.cs	(revision 14498)
@@ -37,6 +37,10 @@
     }
 
-    protected OnlineMeanErrorCalculator(OnlineMeanErrorCalculator other, Cloner cloner) {
-      meanAndVarianceCalculator = (OnlineMeanAndVarianceCalculator)other.meanAndVarianceCalculator.Clone(cloner);
+    protected OnlineMeanErrorCalculator(OnlineMeanErrorCalculator original, Cloner cloner)
+      : base(original, cloner) {
+      meanAndVarianceCalculator = cloner.Clone(original.meanAndVarianceCalculator);
+    }
+    public override IDeepCloneable Clone(Cloner cloner) {
+      return new OnlineMeanErrorCalculator(this, cloner);
     }
 
@@ -79,8 +83,4 @@
       }
     }
-
-    public override IDeepCloneable Clone(Cloner cloner) {
-      return new OnlineMeanErrorCalculator(this, cloner);
-    }
   }
 }
Index: branches/symbreg-factors-2650/HeuristicLab.Problems.DataAnalysis/3.4/OnlineCalculators/OnlineMeanSquaredErrorCalculator.cs
===================================================================
--- branches/symbreg-factors-2650/HeuristicLab.Problems.DataAnalysis/3.4/OnlineCalculators/OnlineMeanSquaredErrorCalculator.cs	(revision 14497)
+++ branches/symbreg-factors-2650/HeuristicLab.Problems.DataAnalysis/3.4/OnlineCalculators/OnlineMeanSquaredErrorCalculator.cs	(revision 14498)
@@ -39,8 +39,12 @@
     }
 
-    protected OnlineMeanSquaredErrorCalculator(OnlineMeanSquaredErrorCalculator other, Cloner cloner = null) {
-      sse = other.sse;
-      n = other.n;
-      errorState = other.errorState;
+    protected OnlineMeanSquaredErrorCalculator(OnlineMeanSquaredErrorCalculator original, Cloner cloner)
+      : base(original, cloner) {
+      sse = original.sse;
+      n = original.n;
+      errorState = original.errorState;
+    }
+    public override IDeepCloneable Clone(Cloner cloner) {
+      return new OnlineMeanSquaredErrorCalculator(this, cloner);
     }
 
@@ -94,8 +98,4 @@
       }
     }
-
-    public override IDeepCloneable Clone(Cloner cloner) {
-      return new OnlineMeanSquaredErrorCalculator(this, cloner);
-    }
   }
 }
Index: branches/symbreg-factors-2650/HeuristicLab.Problems.DataAnalysis/3.4/OnlineCalculators/OnlineNormalizedMeanSquaredErrorCalculator.cs
===================================================================
--- branches/symbreg-factors-2650/HeuristicLab.Problems.DataAnalysis/3.4/OnlineCalculators/OnlineNormalizedMeanSquaredErrorCalculator.cs	(revision 14497)
+++ branches/symbreg-factors-2650/HeuristicLab.Problems.DataAnalysis/3.4/OnlineCalculators/OnlineNormalizedMeanSquaredErrorCalculator.cs	(revision 14498)
@@ -43,7 +43,11 @@
     }
 
-    protected OnlineNormalizedMeanSquaredErrorCalculator(OnlineNormalizedMeanSquaredErrorCalculator other, Cloner cloner) {
-      meanSquaredErrorCalculator = (OnlineMeanAndVarianceCalculator)other.meanSquaredErrorCalculator.Clone(cloner);
-      originalVarianceCalculator = (OnlineMeanAndVarianceCalculator)other.originalVarianceCalculator.Clone(cloner);
+    protected OnlineNormalizedMeanSquaredErrorCalculator(OnlineNormalizedMeanSquaredErrorCalculator original, Cloner cloner)
+      : base(original, cloner) {
+      meanSquaredErrorCalculator = cloner.Clone(original.meanSquaredErrorCalculator);
+      originalVarianceCalculator = cloner.Clone(original.originalVarianceCalculator);
+    }
+    public override IDeepCloneable Clone(Cloner cloner) {
+      return new OnlineNormalizedMeanSquaredErrorCalculator(this, cloner);
     }
 
@@ -99,7 +103,5 @@
     }
 
-    public override IDeepCloneable Clone(Cloner cloner) {
-      return new OnlineNormalizedMeanSquaredErrorCalculator(this, cloner);
-    }
+
   }
 }
Index: branches/symbreg-factors-2650/HeuristicLab.Problems.DataAnalysis/3.4/OnlineCalculators/OnlinePearsonsRCalculator.cs
===================================================================
--- branches/symbreg-factors-2650/HeuristicLab.Problems.DataAnalysis/3.4/OnlineCalculators/OnlinePearsonsRCalculator.cs	(revision 14497)
+++ branches/symbreg-factors-2650/HeuristicLab.Problems.DataAnalysis/3.4/OnlineCalculators/OnlinePearsonsRCalculator.cs	(revision 14498)
@@ -47,8 +47,12 @@
     public OnlinePearsonsRCalculator() { }
 
-    protected OnlinePearsonsRCalculator(OnlinePearsonsRCalculator other, Cloner cloner) {
-      covCalculator = (OnlineCovarianceCalculator)other.covCalculator.Clone(cloner);
-      sxCalculator = (OnlineMeanAndVarianceCalculator)other.sxCalculator.Clone(cloner);
-      syCalculator = (OnlineMeanAndVarianceCalculator)other.syCalculator.Clone(cloner);
+    protected OnlinePearsonsRCalculator(OnlinePearsonsRCalculator original, Cloner cloner)
+      : base(original, cloner) {
+      covCalculator = cloner.Clone(original.covCalculator);
+      sxCalculator = cloner.Clone(original.sxCalculator);
+      syCalculator = cloner.Clone(original.syCalculator);
+    }
+    public override IDeepCloneable Clone(Cloner cloner) {
+      return new OnlinePearsonsRCalculator(this, cloner);
     }
 
@@ -97,8 +101,4 @@
       }
     }
-
-    public override IDeepCloneable Clone(Cloner cloner) {
-      return new OnlinePearsonsRCalculator(this, cloner);
-    }
   }
 }
Index: branches/symbreg-factors-2650/HeuristicLab.Problems.DataAnalysis/3.4/OnlineCalculators/OnlinePearsonsRSquaredCalculator.cs
===================================================================
--- branches/symbreg-factors-2650/HeuristicLab.Problems.DataAnalysis/3.4/OnlineCalculators/OnlinePearsonsRSquaredCalculator.cs	(revision 14497)
+++ branches/symbreg-factors-2650/HeuristicLab.Problems.DataAnalysis/3.4/OnlineCalculators/OnlinePearsonsRSquaredCalculator.cs	(revision 14498)
@@ -38,6 +38,10 @@
     public OnlinePearsonsRSquaredCalculator() { }
 
-    protected OnlinePearsonsRSquaredCalculator(OnlinePearsonsRSquaredCalculator other, Cloner cloner) {
-      this.rCalculator = (OnlinePearsonsRCalculator)other.rCalculator.Clone(cloner);
+    protected OnlinePearsonsRSquaredCalculator(OnlinePearsonsRSquaredCalculator original, Cloner cloner)
+      : base(original, cloner) {
+      rCalculator = cloner.Clone(original.rCalculator);
+    }
+    public override IDeepCloneable Clone(Cloner cloner) {
+      return new OnlinePearsonsRSquaredCalculator(this, cloner);
     }
 
@@ -64,7 +68,5 @@
     }
 
-    public override IDeepCloneable Clone(Cloner cloner) {
-      return new OnlinePearsonsRSquaredCalculator(this, cloner);
-    }
+
   }
 }
Index: branches/symbreg-factors-2650/HeuristicLab.Problems.DataAnalysis/3.4/OnlineCalculators/OnlineTheilsUStatisticCalculator.cs
===================================================================
--- branches/symbreg-factors-2650/HeuristicLab.Problems.DataAnalysis/3.4/OnlineCalculators/OnlineTheilsUStatisticCalculator.cs	(revision 14497)
+++ branches/symbreg-factors-2650/HeuristicLab.Problems.DataAnalysis/3.4/OnlineCalculators/OnlineTheilsUStatisticCalculator.cs	(revision 14498)
@@ -26,6 +26,6 @@
 namespace HeuristicLab.Problems.DataAnalysis {
   public class OnlineTheilsUStatisticCalculator : DeepCloneable, IOnlineTimeSeriesCalculator {
-    private OnlineMeanAndVarianceCalculator squaredErrorMeanCalculator;
-    private OnlineMeanAndVarianceCalculator unbiasedEstimatorMeanCalculator;
+    private readonly OnlineMeanAndVarianceCalculator squaredErrorMeanCalculator;
+    private readonly OnlineMeanAndVarianceCalculator unbiasedEstimatorMeanCalculator;
 
     public double TheilsUStatistic {
@@ -46,7 +46,11 @@
     }
 
-    protected OnlineTheilsUStatisticCalculator(OnlineTheilsUStatisticCalculator other, Cloner cloner) {
-      squaredErrorMeanCalculator = (OnlineMeanAndVarianceCalculator)other.squaredErrorMeanCalculator.Clone(cloner);
-      unbiasedEstimatorMeanCalculator = (OnlineMeanAndVarianceCalculator)other.unbiasedEstimatorMeanCalculator.Clone(cloner);
+    protected OnlineTheilsUStatisticCalculator(OnlineTheilsUStatisticCalculator original, Cloner cloner)
+      : base(original, cloner) {
+      squaredErrorMeanCalculator = cloner.Clone(original.squaredErrorMeanCalculator);
+      unbiasedEstimatorMeanCalculator = cloner.Clone(original.unbiasedEstimatorMeanCalculator);
+    }
+    public override IDeepCloneable Clone(Cloner cloner) {
+      return new OnlineTheilsUStatisticCalculator(this, cloner);
     }
 
@@ -131,8 +135,4 @@
       }
     }
-
-    public override IDeepCloneable Clone(Cloner cloner) {
-      return new OnlineTheilsUStatisticCalculator(this, cloner);
-    }
   }
 }
Index: branches/symbreg-factors-2650/HeuristicLab.Problems.DataAnalysis/3.4/OnlineCalculators/OnlineWeightedDirectionalSymmetryCalculator.cs
===================================================================
--- branches/symbreg-factors-2650/HeuristicLab.Problems.DataAnalysis/3.4/OnlineCalculators/OnlineWeightedDirectionalSymmetryCalculator.cs	(revision 14497)
+++ branches/symbreg-factors-2650/HeuristicLab.Problems.DataAnalysis/3.4/OnlineCalculators/OnlineWeightedDirectionalSymmetryCalculator.cs	(revision 14498)
@@ -42,9 +42,14 @@
     }
 
-    protected OnlineWeightedDirectionalSymmetryCalculator(OnlineWeightedDirectionalSymmetryCalculator other, Cloner cloner) {
-      n = other.n;
-      correctSum = other.correctSum;
-      incorrectSum = other.incorrectSum;
-      errorState = other.errorState;
+    protected OnlineWeightedDirectionalSymmetryCalculator(OnlineWeightedDirectionalSymmetryCalculator original, Cloner cloner)
+      : base(original, cloner) {
+      n = original.n;
+      correctSum = original.correctSum;
+      incorrectSum = original.incorrectSum;
+      errorState = original.errorState;
+    }
+
+    public override IDeepCloneable Clone(Cloner cloner) {
+      return new OnlineWeightedDirectionalSymmetryCalculator(this, cloner);
     }
 
@@ -125,8 +130,4 @@
       }
     }
-
-    public override IDeepCloneable Clone(Cloner cloner) {
-      return new OnlineWeightedDirectionalSymmetryCalculator(this, cloner);
-    }
   }
 }
Index: branches/symbreg-factors-2650/HeuristicLab.Problems.Instances.VehicleRouting/3.4/HeuristicLab.Problems.Instances.VehicleRouting-3.4.csproj
===================================================================
--- branches/symbreg-factors-2650/HeuristicLab.Problems.Instances.VehicleRouting/3.4/HeuristicLab.Problems.Instances.VehicleRouting-3.4.csproj	(revision 14497)
+++ branches/symbreg-factors-2650/HeuristicLab.Problems.Instances.VehicleRouting/3.4/HeuristicLab.Problems.Instances.VehicleRouting-3.4.csproj	(revision 14498)
@@ -158,4 +158,5 @@
     <EmbeddedResource Include="Data\CordeauMDTW.opt.zip" />
     <EmbeddedResource Include="Data\Homberger.opt.zip" />
+    <EmbeddedResource Include="Data\Solomon.opt.zip" />
     <None Include="Plugin.cs.frame" />
     <Compile Include="Plugin.cs" />
Index: branches/symbreg-factors-2650/HeuristicLab.Problems.Instances.VehicleRouting/3.4/SolomonFormat/SolomonFormatInstanceProvider.cs
===================================================================
--- branches/symbreg-factors-2650/HeuristicLab.Problems.Instances.VehicleRouting/3.4/SolomonFormat/SolomonFormatInstanceProvider.cs	(revision 14497)
+++ branches/symbreg-factors-2650/HeuristicLab.Problems.Instances.VehicleRouting/3.4/SolomonFormat/SolomonFormatInstanceProvider.cs	(revision 14498)
@@ -21,5 +21,4 @@
 
 using System;
-using System.Collections.Generic;
 using System.IO;
 using System.Linq;
@@ -64,16 +63,19 @@
         string date = ExtractValue(reader.ReadLine());
         string reference = ExtractValue(reader.ReadLine());
-        reader.ReadLine(); // Solution
-
-        var routesQuery =
-          from line in reader.ReadAllLines()
-          where !string.IsNullOrEmpty(line)
-          let tokens = ExtractValue(line).Split(new[] { ' ' }, StringSplitOptions.RemoveEmptyEntries)
-          let stops = tokens.Select(int.Parse).Select(s => s - 1)
-          select stops;
-
-        var routes = routesQuery.Select(s => s.ToArray()).ToArray();
-
-        instance.BestKnownTour = routes;
+        switch (reader.ReadLine().Trim()) { // "Solution" or "Distance"
+          case "Solution":
+            var routesQuery = from line in reader.ReadAllLines()
+                              where !string.IsNullOrEmpty(line)
+                              let tokens = ExtractValue(line).Split(new[] { ' ' }, StringSplitOptions.RemoveEmptyEntries)
+                              let stops = tokens.Select(int.Parse).Select(s => s - 1)
+                              select stops;
+            var routes = routesQuery.Select(s => s.ToArray()).ToArray();
+            instance.BestKnownTour = routes;
+            break;
+          case "Distance":
+            double quality = double.Parse(reader.ReadLine());
+            instance.BestKnownQuality = quality;
+            break;
+        }
       }
     }
Index: branches/symbreg-factors-2650/HeuristicLab.Problems.Programmable/3.3/HeuristicLab.Problems.Programmable-3.3.csproj
===================================================================
--- branches/symbreg-factors-2650/HeuristicLab.Problems.Programmable/3.3/HeuristicLab.Problems.Programmable-3.3.csproj	(revision 14497)
+++ branches/symbreg-factors-2650/HeuristicLab.Problems.Programmable/3.3/HeuristicLab.Problems.Programmable-3.3.csproj	(revision 14498)
@@ -149,7 +149,7 @@
       <Name>HeuristicLab.Encodings.IntegerVectorEncoding-3.3</Name>
     </ProjectReference>
-    <ProjectReference Include="..\..\HeuristicLab.Encodings.LinearLinkageEncoding\3.3\HeuristicLab.Encodings.LinearLinkageEncoding-3.3.csproj">
+    <ProjectReference Include="..\..\HeuristicLab.Encodings.LinearLinkageEncoding\3.3\HeuristicLab.Encodings.LinearLinkageEncoding-3.4.csproj">
       <Project>{be698769-975a-429e-828c-72bb2b6182c8}</Project>
-      <Name>HeuristicLab.Encodings.LinearLinkageEncoding-3.3</Name>
+      <Name>HeuristicLab.Encodings.LinearLinkageEncoding-3.4</Name>
       <Private>False</Private>
     </ProjectReference>
Index: branches/symbreg-factors-2650/HeuristicLab.Problems.VehicleRouting/3.4/ProblemInstances/VRPProblemInstance.cs
===================================================================
--- branches/symbreg-factors-2650/HeuristicLab.Problems.VehicleRouting/3.4/ProblemInstances/VRPProblemInstance.cs	(revision 14497)
+++ branches/symbreg-factors-2650/HeuristicLab.Problems.VehicleRouting/3.4/ProblemInstances/VRPProblemInstance.cs	(revision 14498)
@@ -190,6 +190,5 @@
     public virtual double GetDistance(int start, int end, IVRPEncoding solution) {
       if (distanceMatrix == null && UseDistanceMatrix.Value) {
-        if (DistanceMatrix == null) DistanceMatrix = CreateDistanceMatrix();
-        distanceMatrix = DistanceMatrix;
+        distanceMatrix = DistanceMatrix ?? CreateDistanceMatrix();
       }
 
Index: branches/symbreg-factors-2650/HeuristicLab.Problems.VehicleRouting/3.4/VehicleRoutingProblem.cs
===================================================================
--- branches/symbreg-factors-2650/HeuristicLab.Problems.VehicleRouting/3.4/VehicleRoutingProblem.cs	(revision 14497)
+++ branches/symbreg-factors-2650/HeuristicLab.Problems.VehicleRouting/3.4/VehicleRoutingProblem.cs	(revision 14498)
@@ -198,6 +198,4 @@
         BestKnownQuality = new DoubleValue(ProblemInstance.Evaluate(BestKnownSolution.Solution).Quality);
         BestKnownSolution.Quality = BestKnownQuality;
-      } else {
-        BestKnownQuality = null;
       }
     }
@@ -208,4 +206,5 @@
 
     void ProblemInstance_EvaluationChanged(object sender, EventArgs e) {
+      BestKnownQuality = null;
       EvalBestKnownSolution();
     }
Index: branches/symbreg-factors-2650/HeuristicLab.Tests/HeuristicLab-3.3/Samples/GAGroupingProblemSampleTest.cs
===================================================================
--- branches/symbreg-factors-2650/HeuristicLab.Tests/HeuristicLab-3.3/Samples/GAGroupingProblemSampleTest.cs	(revision 14497)
+++ branches/symbreg-factors-2650/HeuristicLab.Tests/HeuristicLab-3.3/Samples/GAGroupingProblemSampleTest.cs	(revision 14498)
@@ -49,13 +49,13 @@
     public bool Maximization { get { return false; } }
 
-    private bool[,] allowedTogether;
+    private bool[,] adjacencyMatrix;
       
     public override void Initialize() {
       var encoding = new LinearLinkageEncoding(""lle"", length: ProblemSize);
-      allowedTogether = new bool[encoding.Length, encoding.Length];
+      adjacencyMatrix = new bool[encoding.Length, encoding.Length];
       var random = new System.Random(13);
       for (var i = 0; i < encoding.Length - 1; i++)
         for (var j = i + 1; j < encoding.Length; j++)
-          allowedTogether[i, j] = allowedTogether[j, i] = random.Next(2) == 0;
+          adjacencyMatrix[i, j] = adjacencyMatrix[j, i] = random.Next(2) == 0;
       
       Encoding = encoding;
@@ -68,8 +68,9 @@
         for (var j = 0; j < groups[i].Count; j++)
           for (var k = j + 1; k < groups[i].Count; k++)
-            if (!allowedTogether[groups[i][j], groups[i][k]]) penalty++;
+            if (!adjacencyMatrix[groups[i][j], groups[i][k]]) penalty++;
       }
-      if (penalty > 0) return penalty + ProblemSize;
-      else return groups.Count;
+      var result = groups.Count;
+      if (penalty > 0) result += penalty + ProblemSize;
+      return result;
     }
 
@@ -105,7 +106,7 @@
       ga.SetSeedRandomly.Value = false;
       SamplesUtils.RunAlgorithm(ga);
-      Assert.AreEqual(26, SamplesUtils.GetDoubleResult(ga, "BestQuality"));
-      Assert.AreEqual(27.58, SamplesUtils.GetDoubleResult(ga, "CurrentAverageQuality"));
-      Assert.AreEqual(105, SamplesUtils.GetDoubleResult(ga, "CurrentWorstQuality"));
+      Assert.AreEqual(127, SamplesUtils.GetDoubleResult(ga, "BestQuality"));
+      Assert.AreEqual(129,38, SamplesUtils.GetDoubleResult(ga, "CurrentAverageQuality"));
+      Assert.AreEqual(132, SamplesUtils.GetDoubleResult(ga, "CurrentWorstQuality"));
       Assert.AreEqual(99100, SamplesUtils.GetIntResult(ga, "EvaluatedSolutions"));
     }
@@ -121,6 +122,6 @@
       #endregion
       #region Algorithm Configuration
-      ga.Name = "Genetic Algorithm - Grouping Problem";
-      ga.Description = "A genetic algorithm which solves a grouping problem using the linear linkage encoding.";
+      ga.Name = "Genetic Algorithm - Graph Coloring";
+      ga.Description = "A genetic algorithm which solves a graph coloring problem using the linear linkage encoding.";
       ga.Problem = problem;
       SamplesUtils.ConfigureGeneticAlgorithmParameters<TournamentSelector, MultiLinearLinkageCrossover, MultiLinearLinkageManipulator>(
Index: branches/symbreg-factors-2650/HeuristicLab.Tests/HeuristicLab.Encodings.LinearLinkageEncoding-3.4/Auxiliary.cs
===================================================================
--- branches/symbreg-factors-2650/HeuristicLab.Tests/HeuristicLab.Encodings.LinearLinkageEncoding-3.4/Auxiliary.cs	(revision 14498)
+++ branches/symbreg-factors-2650/HeuristicLab.Tests/HeuristicLab.Encodings.LinearLinkageEncoding-3.4/Auxiliary.cs	(revision 14498)
@@ -0,0 +1,37 @@
+﻿#region License Information
+/* HeuristicLab
+ * Copyright (C) 2002-2016 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
+
+namespace HeuristicLab.Encodings.LinearLinkageEncoding.Tests {
+  public static class Auxiliary {
+    public static bool LinearLinkageIsEqualByPosition(LinearLinkage p1, LinearLinkage p2) {
+      bool equal = (p1.Length == p2.Length);
+      if (equal) {
+        for (int i = 0; i < p1.Length; i++) {
+          if (!p1[i].Equals(p2[i])) {
+            equal = false;
+            break;
+          }
+        }
+      }
+      return equal;
+    }
+  }
+}
Index: branches/symbreg-factors-2650/HeuristicLab.Tests/HeuristicLab.Encodings.LinearLinkageEncoding-3.4/ConversionsTest.cs
===================================================================
--- branches/symbreg-factors-2650/HeuristicLab.Tests/HeuristicLab.Encodings.LinearLinkageEncoding-3.4/ConversionsTest.cs	(revision 14498)
+++ branches/symbreg-factors-2650/HeuristicLab.Tests/HeuristicLab.Encodings.LinearLinkageEncoding-3.4/ConversionsTest.cs	(revision 14498)
@@ -0,0 +1,98 @@
+﻿using System;
+using Microsoft.VisualStudio.TestTools.UnitTesting;
+
+namespace HeuristicLab.Encodings.LinearLinkageEncoding.Tests {
+  [TestClass()]
+  public class ConversionsTest {
+    private readonly int[][] validForwardEncoding = new[]{
+      new int[0], new[] {0},
+      new[] {0, 1}, new[] {1, 1},
+      new[] {0, 1, 2}, new[] {1, 1, 2}, new[] {2, 1, 2},
+      new[] {0, 2, 2}, new[] {1, 2, 2},
+      new[] {0, 1, 2, 3}, new[] {1, 1, 2, 3}, new[] {2, 1, 2, 3}, new[] {3, 1, 2, 3},
+      new[] {0, 1, 3, 3}, new[] {1, 2, 2, 3}, new[] {2, 1, 3, 3}, new[] {3, 2, 2, 3},
+      new[] {0, 2, 2, 3}, new[] {1, 3, 2, 3},
+      new[] {0, 2, 3, 3}
+    };
+    private readonly int[][] invalidForwardEncoding = new[]{
+      new [] {-1}, new [] {1}, new [] {1, 0},
+      new [] {0, 0, 0}, new [] {0, 0, 1}, new [] {0, 0, 2},
+      new [] {0, 1, 0},
+      new [] {0, 2, 0}, new [] {0, 2, 1},
+      new [] {1, 0, 0}, new [] {1, 0, 1}, new [] {1, 0, 2},
+      new [] {1, 1, 0}, new [] {1, 1, 1},
+      new [] {1, 2, 0}, new [] {1, 2, 1},
+      new [] {2, 0, 0}, new [] {2, 0, 1}, new [] {2, 0, 2},
+      new [] {2, 1, 0}, new [] {2, 1, 1},
+      new [] {2, 2, 0}, new [] {2, 2, 1}, new [] {2, 2, 2},
+    };
+    private readonly int[][] invalidEndEncoding = new[]{
+      new [] {-1}, new [] {1}, new [] {1, 0},
+      new [] {0, 0, 1}, new [] {0, 0, 2},
+      new [] {0, 1, 0},
+      new [] {0, 2, 0}, new [] {0, 2, 1},
+      new [] {1, 0, 0}, new [] {1, 0, 1}, new [] {1, 0, 2},
+      new [] {1, 1, 0}, new [] {1, 1, 1},
+      new [] {1, 2, 0}, new [] {1, 2, 1},
+      new [] {2, 0, 0}, new [] {2, 0, 1}, new [] {2, 0, 2},
+      new [] {2, 1, 0}, new [] {2, 1, 1},
+      new [] {2, 2, 0}, new [] {2, 2, 1},
+    };
+
+    [TestMethod()]
+    [TestCategory("Encodings.LinearLinkage")]
+    [TestProperty("Time", "short")]
+    public void EndLinksRoundtripTest() {
+      foreach (var values in validForwardEncoding) {
+        var expected = LinearLinkage.FromForwardLinks(values);
+        var llee = expected.ToEndLinks();
+        var actual = LinearLinkage.FromEndLinks(llee);
+        Assert.IsTrue(Auxiliary.LinearLinkageIsEqualByPosition(expected, actual),
+          "[{0}] did not roundtrip successfully!", string.Join(", ", values));
+      }
+    }
+
+    [TestMethod()]
+    [TestCategory("Encodings.LinearLinkage")]
+    [TestProperty("Time", "short")]
+    public void GroupsRoundtripTest() {
+      foreach (var values in validForwardEncoding) {
+        var expected = LinearLinkage.FromForwardLinks(values);
+        var groups = expected.GetGroups();
+        var actual = LinearLinkage.FromGroups(expected.Length, groups);
+        Assert.IsTrue(Auxiliary.LinearLinkageIsEqualByPosition(expected, actual),
+          "[{0}] did not roundtrip successfully!", string.Join(", ", values));
+      }
+    }
+
+    [TestMethod()]
+    [TestCategory("Encodings.LinearLinkage")]
+    [TestProperty("Time", "short")]
+    public void InvalidForwardLinksTest() {
+      foreach (var values in invalidForwardEncoding) {
+        var isValid = true;
+        try {
+          var lle = LinearLinkage.FromForwardLinks(values);
+        } catch (ArgumentException e) {
+          isValid = false;
+        }
+        Assert.IsFalse(isValid, "[{0}] is invalid and should throw ArgumentException!", string.Join(", ", values));
+      }
+    }
+
+    [TestMethod()]
+    [TestCategory("Encodings.LinearLinkage")]
+    [TestProperty("Time", "short")]
+    public void InvalidEndLinksTest() {
+      foreach (var values in invalidEndEncoding) {
+        var isValid = true;
+        try {
+          var lle = LinearLinkage.FromEndLinks(values);
+        } catch (ArgumentException e) {
+          isValid = false;
+        }
+        Assert.IsFalse(isValid, "{0} should be invalid", string.Join(", ", values));
+      }
+    }
+  }
+}
Index: branches/symbreg-factors-2650/HeuristicLab.Tests/HeuristicLab.Encodings.LinearLinkageEncoding-3.4/GroupCrossoverTest.cs
===================================================================
--- branches/symbreg-factors-2650/HeuristicLab.Tests/HeuristicLab.Encodings.LinearLinkageEncoding-3.4/GroupCrossoverTest.cs	(revision 14498)
+++ branches/symbreg-factors-2650/HeuristicLab.Tests/HeuristicLab.Encodings.LinearLinkageEncoding-3.4/GroupCrossoverTest.cs	(revision 14498)
@@ -0,0 +1,53 @@
+﻿using System;
+using HeuristicLab.Random;
+using HeuristicLab.Tests;
+using Microsoft.VisualStudio.TestTools.UnitTesting;
+
+namespace HeuristicLab.Encodings.LinearLinkageEncoding.Tests {
+  [TestClass()]
+  public class GroupCrossoverTest {
+    [TestMethod()]
+    [TestCategory("Encodings.LinearLinkage")]
+    [TestProperty("Time", "short")]
+    public void EqualParentsTest() {
+      var random = new FastRandom(0);
+      var parent = LinearLinkage.SingleElementGroups(10);
+      var child = GroupCrossover.Apply(random, parent, parent);
+      Assert.IsTrue(Auxiliary.LinearLinkageIsEqualByPosition(parent, child));
+
+      parent = RandomLinearLinkageCreator.Apply(random, 10);
+      child = GroupCrossover.Apply(random, parent, parent);
+      Assert.IsTrue(Auxiliary.LinearLinkageIsEqualByPosition(parent, child));
+    }
+
+    // Example from paper:
+    // Multi-objective Genetic Algorithms for grouping problems. Korkmaz, E.E. Applied Intelligence (2010) 33: 179. 
+    [TestMethod()]
+    [TestCategory("Encodings.LinearLinkage")]
+    [TestProperty("Time", "short")]
+    public void ExampleFromPaperTest() {
+      var parent1 = LinearLinkage.FromEndLinks(new[] { 3, 4, 3, 3, 4 });
+
+      var parent2 = LinearLinkage.FromEndLinks(new[] { 2, 2, 2, 4, 4 });
+
+      CheckGroupCrossover(parent1, parent2, new[] { 3, 4, 2, 3, 4 }, new[] { 0.0, 0.0, 0.0, 0.0 }); // (i)
+      CheckGroupCrossover(parent1, parent2, new[] { 2, 4, 2, 3, 4 }, new[] { 0.0, 0.0, 0.0, 0.9 }); // (iv)
+      CheckGroupCrossover(parent1, parent2, new[] { 3, 2, 2, 3, 4 }, new[] { 0.0, 0.0, 0.9, 0.0 }); // (iii)
+      CheckGroupCrossover(parent1, parent2, new[] { 2, 2, 2, 3, 4 }, new[] { 0.0, 0.0, 0.9, 0.9 }); // (ii)
+      CheckGroupCrossover(parent1, parent2, new[] { 3, 4, 3, 3, 4 }, new[] { 0.0, 0.9 });
+      CheckGroupCrossover(parent1, parent2, new[] { 2, 4, 2, 4, 4 }, new[] { 0.9, 0.0, 0.0 });
+      CheckGroupCrossover(parent1, parent2, new[] { 2, 2, 2, 4, 4 }, new[] { 0.9, 0.0, 0.9 });
+      CheckGroupCrossover(parent1, parent2, new[] { 4, 4, 4, 4, 4 }, new[] { 0.9, 0.9, 0.0, 0.0 });
+      CheckGroupCrossover(parent1, parent2, new[] { 4, 4, 4, 4, 4 }, new[] { 0.9, 0.9, 0.0, 0.9 });
+      CheckGroupCrossover(parent1, parent2, new[] { 2, 4, 2, 4, 4 }, new[] { 0.9, 0.9, 0.9, 0.0 });
+      CheckGroupCrossover(parent1, parent2, new[] { 4, 4, 2, 4, 4 }, new[] { 0.9, 0.9, 0.9, 0.9 });
+    }
+
+    private void CheckGroupCrossover(LinearLinkage parent1, LinearLinkage parent2, int[] expectedllee, double[] randomNumbers) {
+      var expected = LinearLinkage.FromEndLinks(expectedllee);
+      var random = new TestRandom() { DoubleNumbers = randomNumbers };
+      var child = GroupCrossover.Apply(random, parent1, parent2);
+      Assert.IsTrue(Auxiliary.LinearLinkageIsEqualByPosition(expected, child), "Expected [{0}] but was [{1}]!", string.Join(", ", expected), string.Join(", ", child));
+    }
+  }
+}
Index: branches/symbreg-factors-2650/HeuristicLab.Tests/HeuristicLab.Tests.csproj
===================================================================
--- branches/symbreg-factors-2650/HeuristicLab.Tests/HeuristicLab.Tests.csproj	(revision 14497)
+++ branches/symbreg-factors-2650/HeuristicLab.Tests/HeuristicLab.Tests.csproj	(revision 14498)
@@ -198,8 +198,7 @@
       <HintPath>..\bin\HeuristicLab.Encodings.IntegerVectorEncoding-3.3.dll</HintPath>
     </Reference>
-    <Reference Include="HeuristicLab.Encodings.LinearLinkageEncoding-3.3, Version=3.3.0.0, Culture=neutral, PublicKeyToken=ba48961d6f65dcec, processorArchitecture=MSIL">
-      <SpecificVersion>False</SpecificVersion>
-      <HintPath>..\bin\HeuristicLab.Encodings.LinearLinkageEncoding-3.3.dll</HintPath>
-      <Private>False</Private>
+    <Reference Include="HeuristicLab.Encodings.LinearLinkageEncoding-3.4, Version=3.4.0.0, Culture=neutral, PublicKeyToken=ba48961d6f65dcec, processorArchitecture=MSIL">
+      <SpecificVersion>False</SpecificVersion>
+      <HintPath>..\bin\HeuristicLab.Encodings.LinearLinkageEncoding-3.4.dll</HintPath>
     </Reference>
     <Reference Include="HeuristicLab.Encodings.PermutationEncoding-3.3">
@@ -510,4 +509,7 @@
     <Compile Include="HeuristicLab.Encodings.IntegerVectorEncoding-3.3\SinglePointCrossoverTest.cs" />
     <Compile Include="HeuristicLab.Encodings.IntegerVectorEncoding-3.3\UniformOnePositionManipulatorTest.cs" />
+    <Compile Include="HeuristicLab.Encodings.LinearLinkageEncoding-3.4\Auxiliary.cs" />
+    <Compile Include="HeuristicLab.Encodings.LinearLinkageEncoding-3.4\ConversionsTest.cs" />
+    <Compile Include="HeuristicLab.Encodings.LinearLinkageEncoding-3.4\GroupCrossoverTest.cs" />
     <Compile Include="HeuristicLab.Encodings.PermutationEncoding-3.3\Auxiliary.cs" />
     <Compile Include="HeuristicLab.Encodings.PermutationEncoding-3.3\CosaCrossoverTest.cs" />
