Index: branches/2521_ProblemRefactoring/HeuristicLab.Data/3.3/ValueTypeMatrix.cs
===================================================================
--- branches/2521_ProblemRefactoring/HeuristicLab.Data/3.3/ValueTypeMatrix.cs	(revision 17250)
+++ branches/2521_ProblemRefactoring/HeuristicLab.Data/3.3/ValueTypeMatrix.cs	(revision 17251)
@@ -190,5 +190,6 @@
 
     public virtual ValueTypeMatrix<T> AsReadOnly() {
-      ValueTypeMatrix<T> readOnlyValueTypeMatrix = (ValueTypeMatrix<T>)this.Clone();
+      if (readOnly) return this;
+      var readOnlyValueTypeMatrix = (ValueTypeMatrix<T>)this.Clone();
       readOnlyValueTypeMatrix.readOnly = true;
       return readOnlyValueTypeMatrix;
Index: branches/2521_ProblemRefactoring/HeuristicLab.Optimizer/3.3/StartPage.cs
===================================================================
--- branches/2521_ProblemRefactoring/HeuristicLab.Optimizer/3.3/StartPage.cs	(revision 17250)
+++ branches/2521_ProblemRefactoring/HeuristicLab.Optimizer/3.3/StartPage.cs	(revision 17251)
@@ -22,4 +22,5 @@
 using System;
 using System.Collections.Generic;
+using System.Drawing;
 using System.IO;
 using System.Linq;
@@ -110,5 +111,4 @@
         }
 
-      } catch {
       } finally {
         OnAllSamplesLoaded();
@@ -120,5 +120,10 @@
       using (var stream = assembly.GetManifestResourceStream(name)) {
         var serializer = new ProtoBufSerializer();
-        var item = (NamedItem)serializer.Deserialize(stream, false);
+        NamedItem item;
+        try {
+          item = (NamedItem)serializer.Deserialize(stream, false);
+        } catch {
+          item = new ErrorMessage(name, "Sample failed to load!");
+        }
         OnSampleLoaded(item, group, 1.0 / count);
       }
@@ -197,4 +202,16 @@
       Properties.Settings.Default.Save();
     }
+
+    [Item("Error Message", "")]
+    class ErrorMessage : NamedItem {
+      public override Image ItemImage => Common.Resources.VSImageLibrary.Error;
+
+      protected ErrorMessage(ErrorMessage original, Cloner cloner) : base(original, cloner) { }
+      public ErrorMessage(string error, string description) : base(error, description) { }
+
+      public override IDeepCloneable Clone(Cloner cloner) {
+        return new ErrorMessage(this, cloner);
+      }
+    }
   }
 }
Index: branches/2521_ProblemRefactoring/HeuristicLab.Problems.Instances.TSPLIB/3.3/TSPLIBTSPInstanceProvider.cs
===================================================================
--- branches/2521_ProblemRefactoring/HeuristicLab.Problems.Instances.TSPLIB/3.3/TSPLIBTSPInstanceProvider.cs	(revision 17250)
+++ branches/2521_ProblemRefactoring/HeuristicLab.Problems.Instances.TSPLIB/3.3/TSPLIBTSPInstanceProvider.cs	(revision 17251)
@@ -96,4 +96,73 @@
     }
 
+    public override bool CanExportData => true;
+
+    public override void ExportData(TSPData instance, string path) {
+      using (var writer = new StreamWriter(File.OpenWrite(path))) {
+        writer.WriteLine("NAME: " + instance.Name);
+        writer.WriteLine("TYPE: TSP");
+        writer.WriteLine("COMMENT: " + instance.Description.Replace(Environment.NewLine, " \\\\ " ));
+        writer.WriteLine("DIMENSION: " + instance.Dimension);
+
+        if (instance.DistanceMeasure == DistanceMeasure.Euclidean) {
+          // TSPLIB only knows rounded euclidean distance
+          instance.Distances = instance.GetDistanceMatrix();
+          instance.DistanceMeasure = DistanceMeasure.Direct;
+        }
+
+        if (instance.DistanceMeasure == DistanceMeasure.Direct) {
+          writer.WriteLine("EDGE_WEIGHT_TYPE: EXPLICIT");
+          writer.WriteLine("EDGE_WEIGHT_FORMAT: UPPER_ROW");
+          if (instance.Coordinates != null && instance.Coordinates.GetLength(1) == 2) {
+            writer.WriteLine("DISPLAY_DATA_TYPE: TWOD_DISPLAY");
+          }
+        } else {
+          writer.Write("EDGE_WEIGHT_TYPE: ");
+          switch (instance.DistanceMeasure) {
+            case DistanceMeasure.RoundedEuclidean:
+              writer.WriteLine("EUC_2D");
+              break;
+            case DistanceMeasure.UpperEuclidean:
+              writer.WriteLine("CEIL_2D");
+              break;
+            case DistanceMeasure.Att:
+              writer.WriteLine("ATT");
+              break;
+            case DistanceMeasure.Geo:
+              writer.WriteLine("GEO");
+              break;
+            case DistanceMeasure.Manhattan:
+              writer.WriteLine("MAN_2D");
+              break;
+            case DistanceMeasure.Maximum:
+              writer.WriteLine("MAX_2D");
+              break;
+            default: throw new InvalidOperationException("Unknown distance measure: " + instance.DistanceMeasure);
+          }
+          writer.WriteLine("DISPLAY_DATA_TYPE: COORD_DISPLAY");
+        }
+
+        if (instance.DistanceMeasure == DistanceMeasure.Direct) {
+          writer.WriteLine("EDGE_WEIGHT_SECTION");
+          for (var i = 0; i < instance.Distances.GetLength(0) - 1; i++) {
+            for (var j = i + 1; j < instance.Distances.GetLength(1); j++) {
+              writer.Write(instance.Distances[i, j] + " ");
+            }
+            writer.WriteLine();
+          }
+        }
+
+        if (instance.Coordinates != null && instance.Coordinates.GetLength(1) == 2) {
+          if (instance.DistanceMeasure == DistanceMeasure.Direct)
+            writer.WriteLine("DISPLAY_DATA_SECTION");
+          else writer.WriteLine("NODE_COORD_SECTION");
+          for (var i = 1; i <= instance.Coordinates.GetLength(0); i++) {
+            writer.WriteLine(i + " " + instance.Coordinates[i - 1, 0] + " " + instance.Coordinates[i - 1, 1]);
+          }
+        }
+        writer.WriteLine("EOF");
+        writer.Flush();
+      }
+    }
   }
 }
Index: branches/2521_ProblemRefactoring/HeuristicLab.Problems.TravelingSalesman.Views/3.3/CoordinatesTSPDataView.Designer.cs
===================================================================
--- branches/2521_ProblemRefactoring/HeuristicLab.Problems.TravelingSalesman.Views/3.3/CoordinatesTSPDataView.Designer.cs	(revision 17251)
+++ branches/2521_ProblemRefactoring/HeuristicLab.Problems.TravelingSalesman.Views/3.3/CoordinatesTSPDataView.Designer.cs	(revision 17251)
@@ -0,0 +1,116 @@
+﻿namespace HeuristicLab.Problems.TravelingSalesman.Views {
+  partial class CoordinatesTSPDataView {
+    /// <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() {
+      this.coordinatesSplitContainer = new System.Windows.Forms.SplitContainer();
+      this.coordinatesMatrixView = new HeuristicLab.Data.Views.StringConvertibleMatrixView();
+      this.coordinatesPictureBox = new System.Windows.Forms.PictureBox();
+      ((System.ComponentModel.ISupportInitialize)(this.errorProvider)).BeginInit();
+      ((System.ComponentModel.ISupportInitialize)(this.coordinatesSplitContainer)).BeginInit();
+      this.coordinatesSplitContainer.Panel1.SuspendLayout();
+      this.coordinatesSplitContainer.Panel2.SuspendLayout();
+      this.coordinatesSplitContainer.SuspendLayout();
+      ((System.ComponentModel.ISupportInitialize)(this.coordinatesPictureBox)).BeginInit();
+      this.SuspendLayout();
+      // 
+      // nameTextBox
+      // 
+      this.errorProvider.SetIconAlignment(this.nameTextBox, System.Windows.Forms.ErrorIconAlignment.MiddleLeft);
+      this.errorProvider.SetIconPadding(this.nameTextBox, 2);
+      this.nameTextBox.Size = new System.Drawing.Size(688, 20);
+      // 
+      // infoLabel
+      // 
+      this.infoLabel.Location = new System.Drawing.Point(752, 3);
+      // 
+      // coordinatesSplitContainer
+      // 
+      this.coordinatesSplitContainer.Anchor = ((System.Windows.Forms.AnchorStyles)((((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom) 
+            | System.Windows.Forms.AnchorStyles.Left) 
+            | System.Windows.Forms.AnchorStyles.Right)));
+      this.coordinatesSplitContainer.Location = new System.Drawing.Point(0, 26);
+      this.coordinatesSplitContainer.Name = "coordinatesSplitContainer";
+      // 
+      // coordinatesSplitContainer.Panel1
+      // 
+      this.coordinatesSplitContainer.Panel1.Controls.Add(this.coordinatesMatrixView);
+      // 
+      // coordinatesSplitContainer.Panel2
+      // 
+      this.coordinatesSplitContainer.Panel2.Controls.Add(this.coordinatesPictureBox);
+      this.coordinatesSplitContainer.Size = new System.Drawing.Size(771, 570);
+      this.coordinatesSplitContainer.SplitterDistance = 256;
+      this.coordinatesSplitContainer.TabIndex = 1;
+      // 
+      // coordinatesMatrixView
+      // 
+      this.coordinatesMatrixView.Caption = "StringConvertibleMatrix View";
+      this.coordinatesMatrixView.Content = null;
+      this.coordinatesMatrixView.Dock = System.Windows.Forms.DockStyle.Fill;
+      this.coordinatesMatrixView.Location = new System.Drawing.Point(0, 0);
+      this.coordinatesMatrixView.Name = "coordinatesMatrixView";
+      this.coordinatesMatrixView.ReadOnly = false;
+      this.coordinatesMatrixView.ShowRowsAndColumnsTextBox = true;
+      this.coordinatesMatrixView.ShowStatisticalInformation = true;
+      this.coordinatesMatrixView.Size = new System.Drawing.Size(256, 570);
+      this.coordinatesMatrixView.TabIndex = 1;
+      // 
+      // coordinatesPictureBox
+      // 
+      this.coordinatesPictureBox.Dock = System.Windows.Forms.DockStyle.Fill;
+      this.coordinatesPictureBox.Location = new System.Drawing.Point(0, 0);
+      this.coordinatesPictureBox.Name = "coordinatesPictureBox";
+      this.coordinatesPictureBox.Size = new System.Drawing.Size(511, 570);
+      this.coordinatesPictureBox.TabIndex = 0;
+      this.coordinatesPictureBox.TabStop = false;
+      // 
+      // CoordinatesTSPDataView
+      // 
+      this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F);
+      this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
+      this.Controls.Add(this.coordinatesSplitContainer);
+      this.Name = "CoordinatesTSPDataView";
+      this.Size = new System.Drawing.Size(771, 596);
+      this.Controls.SetChildIndex(this.coordinatesSplitContainer, 0);
+      this.Controls.SetChildIndex(this.nameLabel, 0);
+      this.Controls.SetChildIndex(this.nameTextBox, 0);
+      this.Controls.SetChildIndex(this.infoLabel, 0);
+      ((System.ComponentModel.ISupportInitialize)(this.errorProvider)).EndInit();
+      this.coordinatesSplitContainer.Panel1.ResumeLayout(false);
+      this.coordinatesSplitContainer.Panel2.ResumeLayout(false);
+      ((System.ComponentModel.ISupportInitialize)(this.coordinatesSplitContainer)).EndInit();
+      this.coordinatesSplitContainer.ResumeLayout(false);
+      ((System.ComponentModel.ISupportInitialize)(this.coordinatesPictureBox)).EndInit();
+      this.ResumeLayout(false);
+      this.PerformLayout();
+
+    }
+
+    #endregion
+
+    protected System.Windows.Forms.SplitContainer coordinatesSplitContainer;
+    protected Data.Views.StringConvertibleMatrixView coordinatesMatrixView;
+    protected System.Windows.Forms.PictureBox coordinatesPictureBox;
+  }
+}
Index: branches/2521_ProblemRefactoring/HeuristicLab.Problems.TravelingSalesman.Views/3.3/CoordinatesTSPDataView.cs
===================================================================
--- branches/2521_ProblemRefactoring/HeuristicLab.Problems.TravelingSalesman.Views/3.3/CoordinatesTSPDataView.cs	(revision 17251)
+++ branches/2521_ProblemRefactoring/HeuristicLab.Problems.TravelingSalesman.Views/3.3/CoordinatesTSPDataView.cs	(revision 17251)
@@ -0,0 +1,101 @@
+﻿#region License Information
+/* HeuristicLab
+ * Copyright (C) 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.Drawing;
+using System.Windows.Forms;
+using HeuristicLab.Core.Views;
+using HeuristicLab.Data;
+using HeuristicLab.MainForm;
+using HeuristicLab.MainForm.WindowsForms;
+
+namespace HeuristicLab.Problems.TravelingSalesman.Views {
+  [View("Matrix TSP Data View")]
+  [Content(typeof(CoordinatesTSPData), IsDefaultView = true)]
+  public partial class CoordinatesTSPDataView : NamedItemView {
+
+    public new CoordinatesTSPData Content {
+      get { return (CoordinatesTSPData)base.Content; }
+      set { base.Content = value; }
+    }
+
+    public CoordinatesTSPDataView() {
+      InitializeComponent();
+    }
+
+    protected override void OnContentChanged() {
+      base.OnContentChanged();
+      if (Content == null) {
+        coordinatesMatrixView.Content = null;
+        coordinatesPictureBox.Image = null;
+      } else {
+        coordinatesMatrixView.Content = Content.Coordinates;
+        GenerateImage();
+      }
+    }
+
+    protected override void SetEnabledStateOfControls() {
+      base.SetEnabledStateOfControls();
+      coordinatesMatrixView.Enabled = !ReadOnly && !Locked && Content != null;
+    }
+
+    protected virtual void GenerateImage() {
+      if (coordinatesPictureBox.Width > 0 && coordinatesPictureBox.Height > 0) {
+        DoubleMatrix coordinates = Content.Coordinates;
+        var xAxis = Content is GeoTSPData ? 1 : 0;
+        var yAxis = 1 - xAxis;
+        var bitmap = new Bitmap(coordinatesPictureBox.Width, coordinatesPictureBox.Height);
+
+        if (coordinates.Rows > 0 && coordinates.Columns == 2) {
+          double xMin = double.MaxValue, yMin = double.MaxValue, xMax = double.MinValue, yMax = double.MinValue;
+          for (int i = 0; i < coordinates.Rows; i++) {
+            if (xMin > coordinates[i, xAxis]) xMin = coordinates[i, xAxis];
+            if (yMin > coordinates[i, yAxis]) yMin = coordinates[i, yAxis];
+            if (xMax < coordinates[i, xAxis]) xMax = coordinates[i, xAxis];
+            if (yMax < coordinates[i, yAxis]) yMax = coordinates[i, yAxis];
+          }
+
+          int border = 20;
+          double xStep = xMax != xMin ? (coordinatesPictureBox.Width - 2 * border) / (xMax - xMin) : 1;
+          double yStep = yMax != yMin ? (coordinatesPictureBox.Height - 2 * border) / (yMax - yMin) : 1;
+
+          Point[] points = new Point[coordinates.Rows];
+          for (int i = 0; i < coordinates.Rows; i++)
+            points[i] = new Point(border + ((int)((coordinates[i, xAxis] - xMin) * xStep)),
+                                  bitmap.Height - (border + ((int)((coordinates[i, yAxis] - yMin) * yStep))));
+
+          using (Graphics graphics = Graphics.FromImage(bitmap)) {
+            for (int i = 0; i < points.Length; i++)
+              graphics.FillRectangle(Brushes.Red, points[i].X - 2, points[i].Y - 2, 6, 6);
+          }
+        } else {
+          using (Graphics graphics = Graphics.FromImage(bitmap)) {
+            graphics.Clear(Color.White);
+            Font font = new Font(FontFamily.GenericSansSerif, 12, FontStyle.Regular);
+            string text = "No coordinates defined or in wrong format.";
+            SizeF strSize = graphics.MeasureString(text, font);
+            graphics.DrawString(text, font, Brushes.Black, (float)(coordinatesPictureBox.Width - strSize.Width) / 2.0f, (float)(coordinatesPictureBox.Height - strSize.Height) / 2.0f);
+          }
+        }
+        coordinatesPictureBox.Image = bitmap;
+      }
+    }
+  }
+}
Index: branches/2521_ProblemRefactoring/HeuristicLab.Problems.TravelingSalesman.Views/3.3/EuclideanTSPDataView.Designer.cs
===================================================================
--- branches/2521_ProblemRefactoring/HeuristicLab.Problems.TravelingSalesman.Views/3.3/EuclideanTSPDataView.Designer.cs	(revision 17251)
+++ branches/2521_ProblemRefactoring/HeuristicLab.Problems.TravelingSalesman.Views/3.3/EuclideanTSPDataView.Designer.cs	(revision 17251)
@@ -0,0 +1,92 @@
+﻿namespace HeuristicLab.Problems.TravelingSalesman.Views {
+  partial class EuclideanTSPDataView {
+    /// <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() {
+      this.roundingModeLabel = new System.Windows.Forms.Label();
+      this.roundingModeComboBox = new System.Windows.Forms.ComboBox();
+      ((System.ComponentModel.ISupportInitialize)(this.coordinatesSplitContainer)).BeginInit();
+      this.coordinatesSplitContainer.Panel1.SuspendLayout();
+      this.coordinatesSplitContainer.Panel2.SuspendLayout();
+      this.coordinatesSplitContainer.SuspendLayout();
+      ((System.ComponentModel.ISupportInitialize)(this.coordinatesPictureBox)).BeginInit();
+      this.SuspendLayout();
+      // 
+      // coordinatesSplitContainer
+      // 
+      // 
+      // coordinatesSplitContainer.Panel1
+      // 
+      this.coordinatesSplitContainer.Panel1.Controls.Add(this.roundingModeComboBox);
+      this.coordinatesSplitContainer.Panel1.Controls.Add(this.roundingModeLabel);
+      // 
+      // coordinatesMatrixView
+      // 
+      this.coordinatesMatrixView.Anchor = ((System.Windows.Forms.AnchorStyles)((((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom) 
+            | System.Windows.Forms.AnchorStyles.Left) 
+            | System.Windows.Forms.AnchorStyles.Right)));
+      this.coordinatesMatrixView.Dock = System.Windows.Forms.DockStyle.None;
+      this.coordinatesMatrixView.Location = new System.Drawing.Point(0, 30);
+      this.coordinatesMatrixView.Size = new System.Drawing.Size(256, 598);
+      // 
+      // roundingModeLabel
+      // 
+      this.roundingModeLabel.AutoSize = true;
+      this.roundingModeLabel.Location = new System.Drawing.Point(3, 6);
+      this.roundingModeLabel.Name = "roundingModeLabel";
+      this.roundingModeLabel.Size = new System.Drawing.Size(101, 13);
+      this.roundingModeLabel.TabIndex = 2;
+      this.roundingModeLabel.Text = "Distance Rounding:";
+      // 
+      // roundingModeComboBox
+      // 
+      this.roundingModeComboBox.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left) 
+            | System.Windows.Forms.AnchorStyles.Right)));
+      this.roundingModeComboBox.DropDownStyle = System.Windows.Forms.ComboBoxStyle.DropDownList;
+      this.roundingModeComboBox.FormattingEnabled = true;
+      this.roundingModeComboBox.Location = new System.Drawing.Point(110, 3);
+      this.roundingModeComboBox.Name = "roundingModeComboBox";
+      this.roundingModeComboBox.Size = new System.Drawing.Size(146, 21);
+      this.roundingModeComboBox.TabIndex = 3;
+      // 
+      // EuclideanTSPDataView
+      // 
+      this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F);
+      this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
+      this.Name = "EuclideanTSPDataView";
+      this.coordinatesSplitContainer.Panel1.ResumeLayout(false);
+      this.coordinatesSplitContainer.Panel1.PerformLayout();
+      this.coordinatesSplitContainer.Panel2.ResumeLayout(false);
+      ((System.ComponentModel.ISupportInitialize)(this.coordinatesSplitContainer)).EndInit();
+      this.coordinatesSplitContainer.ResumeLayout(false);
+      ((System.ComponentModel.ISupportInitialize)(this.coordinatesPictureBox)).EndInit();
+      this.ResumeLayout(false);
+
+    }
+
+    #endregion
+
+    private System.Windows.Forms.ComboBox roundingModeComboBox;
+    private System.Windows.Forms.Label roundingModeLabel;
+  }
+}
Index: branches/2521_ProblemRefactoring/HeuristicLab.Problems.TravelingSalesman.Views/3.3/EuclideanTSPDataView.cs
===================================================================
--- branches/2521_ProblemRefactoring/HeuristicLab.Problems.TravelingSalesman.Views/3.3/EuclideanTSPDataView.cs	(revision 17251)
+++ branches/2521_ProblemRefactoring/HeuristicLab.Problems.TravelingSalesman.Views/3.3/EuclideanTSPDataView.cs	(revision 17251)
@@ -0,0 +1,56 @@
+﻿#region License Information
+/* HeuristicLab
+ * Copyright (C) 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 HeuristicLab.MainForm;
+using static HeuristicLab.Problems.TravelingSalesman.EuclideanTSPData;
+
+namespace HeuristicLab.Problems.TravelingSalesman.Views {
+  [View("Euclidean TSP Data View")]
+  [Content(typeof(EuclideanTSPData), IsDefaultView = true)]
+  public partial class EuclideanTSPDataView : CoordinatesTSPDataView {
+
+    public new EuclideanTSPData Content {
+      get { return (EuclideanTSPData)base.Content; }
+      set { base.Content = value; }
+    }
+
+    public EuclideanTSPDataView() {
+      InitializeComponent();
+      foreach (var e in Enum.GetValues(typeof(DistanceRounding)))
+        roundingModeComboBox.Items.Add(e);
+    }
+
+    protected override void OnContentChanged() {
+      base.OnContentChanged();
+      if (Content == null) {
+        roundingModeComboBox.SelectedIndex = -1;
+      } else {
+        roundingModeComboBox.SelectedItem = Content.Rounding;
+      }
+    }
+
+    protected override void SetEnabledStateOfControls() {
+      base.SetEnabledStateOfControls();
+      roundingModeComboBox.Enabled = false;
+    }
+  }
+}
Index: branches/2521_ProblemRefactoring/HeuristicLab.Problems.TravelingSalesman.Views/3.3/HeuristicLab.Problems.TravelingSalesman.Views-3.3.csproj
===================================================================
--- branches/2521_ProblemRefactoring/HeuristicLab.Problems.TravelingSalesman.Views/3.3/HeuristicLab.Problems.TravelingSalesman.Views-3.3.csproj	(revision 17250)
+++ branches/2521_ProblemRefactoring/HeuristicLab.Problems.TravelingSalesman.Views/3.3/HeuristicLab.Problems.TravelingSalesman.Views-3.3.csproj	(revision 17251)
@@ -123,4 +123,16 @@
   </ItemGroup>
   <ItemGroup>
+    <Compile Include="CoordinatesTSPDataView.cs">
+      <SubType>UserControl</SubType>
+    </Compile>
+    <Compile Include="CoordinatesTSPDataView.Designer.cs">
+      <DependentUpon>CoordinatesTSPDataView.cs</DependentUpon>
+    </Compile>
+    <Compile Include="EuclideanTSPDataView.cs">
+      <SubType>UserControl</SubType>
+    </Compile>
+    <Compile Include="EuclideanTSPDataView.Designer.cs">
+      <DependentUpon>EuclideanTSPDataView.cs</DependentUpon>
+    </Compile>
     <Compile Include="MatrixTSPDataView.cs">
       <SubType>UserControl</SubType>
@@ -235,12 +247,4 @@
       <Private>False</Private>
     </ProjectReference>
-  </ItemGroup>
-  <ItemGroup>
-    <EmbeddedResource Include="MatrixTSPDataView.resx">
-      <DependentUpon>MatrixTSPDataView.cs</DependentUpon>
-    </EmbeddedResource>
-    <EmbeddedResource Include="TSPSolutionView.resx">
-      <DependentUpon>TSPSolutionView.cs</DependentUpon>
-    </EmbeddedResource>
   </ItemGroup>
   <Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
Index: branches/2521_ProblemRefactoring/HeuristicLab.Problems.TravelingSalesman.Views/3.3/MatrixTSPDataView.Designer.cs
===================================================================
--- branches/2521_ProblemRefactoring/HeuristicLab.Problems.TravelingSalesman.Views/3.3/MatrixTSPDataView.Designer.cs	(revision 17250)
+++ branches/2521_ProblemRefactoring/HeuristicLab.Problems.TravelingSalesman.Views/3.3/MatrixTSPDataView.Designer.cs	(revision 17251)
@@ -26,11 +26,10 @@
       this.tabControl = new System.Windows.Forms.TabControl();
       this.distancesTabPage = new System.Windows.Forms.TabPage();
-      this.setMatrixButton = new System.Windows.Forms.Button();
+      this.distanceMatrixView = new HeuristicLab.Data.Views.StringConvertibleMatrixView();
       this.coordinatesTabPage = new System.Windows.Forms.TabPage();
-      this.distanceMatrixView = new HeuristicLab.Data.Views.StringConvertibleMatrixView();
       this.coordinatesSplitContainer = new System.Windows.Forms.SplitContainer();
-      this.setCoordinatesButton = new System.Windows.Forms.Button();
       this.coordinatesMatrixView = new HeuristicLab.Data.Views.StringConvertibleMatrixView();
       this.coordinatesPictureBox = new System.Windows.Forms.PictureBox();
+      ((System.ComponentModel.ISupportInitialize)(this.errorProvider)).BeginInit();
       this.tabControl.SuspendLayout();
       this.distancesTabPage.SuspendLayout();
@@ -43,37 +42,50 @@
       this.SuspendLayout();
       // 
+      // nameTextBox
+      // 
+      this.errorProvider.SetIconAlignment(this.nameTextBox, System.Windows.Forms.ErrorIconAlignment.MiddleLeft);
+      this.errorProvider.SetIconPadding(this.nameTextBox, 2);
+      this.nameTextBox.Size = new System.Drawing.Size(688, 20);
+      // 
+      // infoLabel
+      // 
+      this.infoLabel.Location = new System.Drawing.Point(752, 3);
+      // 
       // tabControl
       // 
+      this.tabControl.Anchor = ((System.Windows.Forms.AnchorStyles)((((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom) 
+            | System.Windows.Forms.AnchorStyles.Left) 
+            | System.Windows.Forms.AnchorStyles.Right)));
       this.tabControl.Controls.Add(this.distancesTabPage);
       this.tabControl.Controls.Add(this.coordinatesTabPage);
-      this.tabControl.Dock = System.Windows.Forms.DockStyle.Fill;
-      this.tabControl.Location = new System.Drawing.Point(0, 0);
+      this.tabControl.Location = new System.Drawing.Point(0, 26);
       this.tabControl.Name = "tabControl";
       this.tabControl.SelectedIndex = 0;
-      this.tabControl.Size = new System.Drawing.Size(771, 596);
+      this.tabControl.Size = new System.Drawing.Size(771, 570);
       this.tabControl.TabIndex = 1;
       // 
       // distancesTabPage
       // 
-      this.distancesTabPage.Controls.Add(this.setMatrixButton);
       this.distancesTabPage.Controls.Add(this.distanceMatrixView);
       this.distancesTabPage.Location = new System.Drawing.Point(4, 22);
       this.distancesTabPage.Name = "distancesTabPage";
       this.distancesTabPage.Padding = new System.Windows.Forms.Padding(3);
-      this.distancesTabPage.Size = new System.Drawing.Size(763, 570);
+      this.distancesTabPage.Size = new System.Drawing.Size(763, 544);
       this.distancesTabPage.TabIndex = 0;
       this.distancesTabPage.Text = "Distances";
       this.distancesTabPage.UseVisualStyleBackColor = true;
       // 
-      // setMatrixButton
+      // distanceMatrixView
       // 
-      this.setMatrixButton.Location = new System.Drawing.Point(6, 6);
-      this.setMatrixButton.Name = "setMatrixButton";
-      this.setMatrixButton.Size = new System.Drawing.Size(26, 23);
-      this.setMatrixButton.TabIndex = 1;
-      this.setMatrixButton.Text = "Set";
-      this.setMatrixButton.TextImageRelation = System.Windows.Forms.TextImageRelation.ImageBeforeText;
-      this.setMatrixButton.UseVisualStyleBackColor = true;
-      this.setMatrixButton.Click += new System.EventHandler(this.SetMatrixButton_Click);
+      this.distanceMatrixView.Caption = "StringConvertibleMatrix View";
+      this.distanceMatrixView.Content = null;
+      this.distanceMatrixView.Dock = System.Windows.Forms.DockStyle.Fill;
+      this.distanceMatrixView.Location = new System.Drawing.Point(3, 3);
+      this.distanceMatrixView.Name = "distanceMatrixView";
+      this.distanceMatrixView.ReadOnly = false;
+      this.distanceMatrixView.ShowRowsAndColumnsTextBox = true;
+      this.distanceMatrixView.ShowStatisticalInformation = true;
+      this.distanceMatrixView.Size = new System.Drawing.Size(757, 538);
+      this.distanceMatrixView.TabIndex = 0;
       // 
       // coordinatesTabPage
@@ -88,19 +100,4 @@
       this.coordinatesTabPage.UseVisualStyleBackColor = true;
       // 
-      // distanceMatrixView
-      // 
-      this.distanceMatrixView.Anchor = ((System.Windows.Forms.AnchorStyles)((((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom) 
-            | System.Windows.Forms.AnchorStyles.Left) 
-            | System.Windows.Forms.AnchorStyles.Right)));
-      this.distanceMatrixView.Caption = "StringConvertibleMatrix View";
-      this.distanceMatrixView.Content = null;
-      this.distanceMatrixView.Location = new System.Drawing.Point(6, 35);
-      this.distanceMatrixView.Name = "distanceMatrixView";
-      this.distanceMatrixView.ReadOnly = false;
-      this.distanceMatrixView.ShowRowsAndColumnsTextBox = true;
-      this.distanceMatrixView.ShowStatisticalInformation = true;
-      this.distanceMatrixView.Size = new System.Drawing.Size(751, 529);
-      this.distanceMatrixView.TabIndex = 0;
-      // 
       // coordinatesSplitContainer
       // 
@@ -111,5 +108,4 @@
       // coordinatesSplitContainer.Panel1
       // 
-      this.coordinatesSplitContainer.Panel1.Controls.Add(this.setCoordinatesButton);
       this.coordinatesSplitContainer.Panel1.Controls.Add(this.coordinatesMatrixView);
       // 
@@ -121,28 +117,15 @@
       this.coordinatesSplitContainer.TabIndex = 0;
       // 
-      // setCoordinatesButton
-      // 
-      this.setCoordinatesButton.Location = new System.Drawing.Point(3, 3);
-      this.setCoordinatesButton.Name = "setCoordinatesButton";
-      this.setCoordinatesButton.Size = new System.Drawing.Size(26, 23);
-      this.setCoordinatesButton.TabIndex = 2;
-      this.setCoordinatesButton.Text = "Set";
-      this.setCoordinatesButton.TextImageRelation = System.Windows.Forms.TextImageRelation.ImageBeforeText;
-      this.setCoordinatesButton.UseVisualStyleBackColor = true;
-      this.setCoordinatesButton.Click += new System.EventHandler(this.SetCoordinatesButton_Click);
-      // 
       // coordinatesMatrixView
       // 
-      this.coordinatesMatrixView.Anchor = ((System.Windows.Forms.AnchorStyles)((((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom) 
-            | System.Windows.Forms.AnchorStyles.Left) 
-            | System.Windows.Forms.AnchorStyles.Right)));
       this.coordinatesMatrixView.Caption = "StringConvertibleMatrix View";
       this.coordinatesMatrixView.Content = null;
-      this.coordinatesMatrixView.Location = new System.Drawing.Point(0, 32);
+      this.coordinatesMatrixView.Dock = System.Windows.Forms.DockStyle.Fill;
+      this.coordinatesMatrixView.Location = new System.Drawing.Point(0, 0);
       this.coordinatesMatrixView.Name = "coordinatesMatrixView";
       this.coordinatesMatrixView.ReadOnly = false;
       this.coordinatesMatrixView.ShowRowsAndColumnsTextBox = true;
       this.coordinatesMatrixView.ShowStatisticalInformation = true;
-      this.coordinatesMatrixView.Size = new System.Drawing.Size(249, 532);
+      this.coordinatesMatrixView.Size = new System.Drawing.Size(252, 564);
       this.coordinatesMatrixView.TabIndex = 1;
       // 
@@ -163,4 +146,9 @@
       this.Name = "MatrixTSPDataView";
       this.Size = new System.Drawing.Size(771, 596);
+      this.Controls.SetChildIndex(this.tabControl, 0);
+      this.Controls.SetChildIndex(this.nameLabel, 0);
+      this.Controls.SetChildIndex(this.nameTextBox, 0);
+      this.Controls.SetChildIndex(this.infoLabel, 0);
+      ((System.ComponentModel.ISupportInitialize)(this.errorProvider)).EndInit();
       this.tabControl.ResumeLayout(false);
       this.distancesTabPage.ResumeLayout(false);
@@ -172,4 +160,5 @@
       ((System.ComponentModel.ISupportInitialize)(this.coordinatesPictureBox)).EndInit();
       this.ResumeLayout(false);
+      this.PerformLayout();
 
     }
@@ -183,7 +172,5 @@
     private Data.Views.StringConvertibleMatrixView coordinatesMatrixView;
     private System.Windows.Forms.TabPage distancesTabPage;
-    private System.Windows.Forms.Button setMatrixButton;
     private System.Windows.Forms.PictureBox coordinatesPictureBox;
-    private System.Windows.Forms.Button setCoordinatesButton;
   }
 }
Index: branches/2521_ProblemRefactoring/HeuristicLab.Problems.TravelingSalesman.Views/3.3/MatrixTSPDataView.cs
===================================================================
--- branches/2521_ProblemRefactoring/HeuristicLab.Problems.TravelingSalesman.Views/3.3/MatrixTSPDataView.cs	(revision 17250)
+++ branches/2521_ProblemRefactoring/HeuristicLab.Problems.TravelingSalesman.Views/3.3/MatrixTSPDataView.cs	(revision 17251)
@@ -20,9 +20,6 @@
 #endregion
 
-using System;
-using System.ComponentModel;
 using System.Drawing;
 using System.Windows.Forms;
-using HeuristicLab.Common.Resources;
 using HeuristicLab.Core.Views;
 using HeuristicLab.Data;
@@ -33,5 +30,5 @@
   [View("Matrix TSP Data View")]
   [Content(typeof(MatrixTSPData), IsDefaultView = true)]
-  public partial class MatrixTSPDataView : ItemView {
+  public partial class MatrixTSPDataView : NamedItemView {
 
     public new MatrixTSPData Content {
@@ -42,53 +39,5 @@
     public MatrixTSPDataView() {
       InitializeComponent();
-      setMatrixButton.Text = string.Empty;
-      setMatrixButton.Image = VSImageLibrary.Edit;
-      setCoordinatesButton.Text = string.Empty;
-      setCoordinatesButton.Image = VSImageLibrary.Edit;
     }
-
-    #region Content Events
-    protected override void RegisterContentEvents() {
-      base.RegisterContentEvents();
-      Content.PropertyChanged += ContentOnPropertyChanged;
-      if (Content.DisplayCoordinates != null) {
-        Content.DisplayCoordinates.Reset += ContentDisplayCoordinatesOnChanged;
-        Content.DisplayCoordinates.ItemChanged += ContentDisplayCoordinatesOnChanged;
-      }
-    }
-
-    protected override void DeregisterContentEvents() {
-      base.DeregisterContentEvents();
-      Content.PropertyChanged -= ContentOnPropertyChanged;
-      if (Content.DisplayCoordinates != null) {
-        Content.DisplayCoordinates.Reset -= ContentDisplayCoordinatesOnChanged;
-        Content.DisplayCoordinates.ItemChanged -= ContentDisplayCoordinatesOnChanged;
-      }
-    }
-
-    private void ContentOnPropertyChanged(object sender, PropertyChangedEventArgs e) {
-      switch (e.PropertyName) {
-        case nameof(Content.Matrix):
-          distanceMatrixView.Content = Content.Matrix;
-          break;
-        case nameof(Content.DisplayCoordinates):
-          if (coordinatesMatrixView.Content != null) {
-            coordinatesMatrixView.Content.Reset -= ContentDisplayCoordinatesOnChanged;
-            coordinatesMatrixView.Content.ItemChanged -= ContentDisplayCoordinatesOnChanged;
-          }
-          if (Content.DisplayCoordinates != null) {
-            Content.DisplayCoordinates.Reset += ContentDisplayCoordinatesOnChanged;
-            Content.DisplayCoordinates.ItemChanged += ContentDisplayCoordinatesOnChanged;
-          }
-          coordinatesMatrixView.Content = Content.DisplayCoordinates;
-          GenerateImage();
-          break;
-      }
-    }
-
-    private void ContentDisplayCoordinatesOnChanged(object sender, EventArgs e) {
-      GenerateImage();
-    }
-    #endregion
 
     protected override void OnContentChanged() {
@@ -107,6 +56,4 @@
     protected override void SetEnabledStateOfControls() {
       base.SetEnabledStateOfControls();
-      setMatrixButton.Enabled = !ReadOnly && !Locked && Content != null;
-      setCoordinatesButton.Enabled = !ReadOnly && !Locked && Content != null;
       distanceMatrixView.Enabled = !ReadOnly && !Locked && Content != null;
       coordinatesMatrixView.Enabled = !ReadOnly && !Locked && Content != null;
@@ -152,17 +99,4 @@
       }
     }
-
-    private void SetCoordinatesButton_Click(object sender, EventArgs e) {
-      if (Content.DisplayCoordinates != null) {
-        Content.DisplayCoordinates.Reset -= ContentDisplayCoordinatesOnChanged;
-        Content.DisplayCoordinates.ItemChanged -= ContentDisplayCoordinatesOnChanged;
-      }
-      var items = Math.Max(Content.Matrix.Rows, 1);
-      Content.DisplayCoordinates = new DoubleMatrix(items, 2);
-    }
-
-    private void SetMatrixButton_Click(object sender, EventArgs e) {
-      MessageBox.Show("Not yet implemented");
-    }
   }
 }
Index: branches/2521_ProblemRefactoring/HeuristicLab.Problems.TravelingSalesman.Views/3.3/MatrixTSPDataView.resx
===================================================================
--- branches/2521_ProblemRefactoring/HeuristicLab.Problems.TravelingSalesman.Views/3.3/MatrixTSPDataView.resx	(revision 17250)
+++ 	(revision )
@@ -1,120 +1,0 @@
-﻿<?xml version="1.0" encoding="utf-8"?>
-<root>
-  <!-- 
-    Microsoft ResX Schema 
-    
-    Version 2.0
-    
-    The primary goals of this format is to allow a simple XML format 
-    that is mostly human readable. The generation and parsing of the 
-    various data types are done through the TypeConverter classes 
-    associated with the data types.
-    
-    Example:
-    
-    ... ado.net/XML headers & schema ...
-    <resheader name="resmimetype">text/microsoft-resx</resheader>
-    <resheader name="version">2.0</resheader>
-    <resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>
-    <resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>
-    <data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data>
-    <data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data>
-    <data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64">
-        <value>[base64 mime encoded serialized .NET Framework object]</value>
-    </data>
-    <data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
-        <value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>
-        <comment>This is a comment</comment>
-    </data>
-                
-    There are any number of "resheader" rows that contain simple 
-    name/value pairs.
-    
-    Each data row contains a name, and value. The row also contains a 
-    type or mimetype. Type corresponds to a .NET class that support 
-    text/value conversion through the TypeConverter architecture. 
-    Classes that don't support this are serialized and stored with the 
-    mimetype set.
-    
-    The mimetype is used for serialized objects, and tells the 
-    ResXResourceReader how to depersist the object. This is currently not 
-    extensible. For a given mimetype the value must be set accordingly:
-    
-    Note - application/x-microsoft.net.object.binary.base64 is the format 
-    that the ResXResourceWriter will generate, however the reader can 
-    read any of the formats listed below.
-    
-    mimetype: application/x-microsoft.net.object.binary.base64
-    value   : The object must be serialized with 
-            : System.Runtime.Serialization.Formatters.Binary.BinaryFormatter
-            : and then encoded with base64 encoding.
-    
-    mimetype: application/x-microsoft.net.object.soap.base64
-    value   : The object must be serialized with 
-            : System.Runtime.Serialization.Formatters.Soap.SoapFormatter
-            : and then encoded with base64 encoding.
-
-    mimetype: application/x-microsoft.net.object.bytearray.base64
-    value   : The object must be serialized into a byte array 
-            : using a System.ComponentModel.TypeConverter
-            : and then encoded with base64 encoding.
-    -->
-  <xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
-    <xsd:import namespace="http://www.w3.org/XML/1998/namespace" />
-    <xsd:element name="root" msdata:IsDataSet="true">
-      <xsd:complexType>
-        <xsd:choice maxOccurs="unbounded">
-          <xsd:element name="metadata">
-            <xsd:complexType>
-              <xsd:sequence>
-                <xsd:element name="value" type="xsd:string" minOccurs="0" />
-              </xsd:sequence>
-              <xsd:attribute name="name" use="required" type="xsd:string" />
-              <xsd:attribute name="type" type="xsd:string" />
-              <xsd:attribute name="mimetype" type="xsd:string" />
-              <xsd:attribute ref="xml:space" />
-            </xsd:complexType>
-          </xsd:element>
-          <xsd:element name="assembly">
-            <xsd:complexType>
-              <xsd:attribute name="alias" type="xsd:string" />
-              <xsd:attribute name="name" type="xsd:string" />
-            </xsd:complexType>
-          </xsd:element>
-          <xsd:element name="data">
-            <xsd:complexType>
-              <xsd:sequence>
-                <xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
-                <xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
-              </xsd:sequence>
-              <xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1" />
-              <xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
-              <xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
-              <xsd:attribute ref="xml:space" />
-            </xsd:complexType>
-          </xsd:element>
-          <xsd:element name="resheader">
-            <xsd:complexType>
-              <xsd:sequence>
-                <xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
-              </xsd:sequence>
-              <xsd:attribute name="name" type="xsd:string" use="required" />
-            </xsd:complexType>
-          </xsd:element>
-        </xsd:choice>
-      </xsd:complexType>
-    </xsd:element>
-  </xsd:schema>
-  <resheader name="resmimetype">
-    <value>text/microsoft-resx</value>
-  </resheader>
-  <resheader name="version">
-    <value>2.0</value>
-  </resheader>
-  <resheader name="reader">
-    <value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
-  </resheader>
-  <resheader name="writer">
-    <value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
-  </resheader>
-</root>
Index: branches/2521_ProblemRefactoring/HeuristicLab.Problems.TravelingSalesman.Views/3.3/TSPSolutionView.resx
===================================================================
--- branches/2521_ProblemRefactoring/HeuristicLab.Problems.TravelingSalesman.Views/3.3/TSPSolutionView.resx	(revision 17250)
+++ 	(revision )
@@ -1,120 +1,0 @@
-﻿<?xml version="1.0" encoding="utf-8"?>
-<root>
-  <!-- 
-    Microsoft ResX Schema 
-    
-    Version 2.0
-    
-    The primary goals of this format is to allow a simple XML format 
-    that is mostly human readable. The generation and parsing of the 
-    various data types are done through the TypeConverter classes 
-    associated with the data types.
-    
-    Example:
-    
-    ... ado.net/XML headers & schema ...
-    <resheader name="resmimetype">text/microsoft-resx</resheader>
-    <resheader name="version">2.0</resheader>
-    <resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>
-    <resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>
-    <data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data>
-    <data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data>
-    <data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64">
-        <value>[base64 mime encoded serialized .NET Framework object]</value>
-    </data>
-    <data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
-        <value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>
-        <comment>This is a comment</comment>
-    </data>
-                
-    There are any number of "resheader" rows that contain simple 
-    name/value pairs.
-    
-    Each data row contains a name, and value. The row also contains a 
-    type or mimetype. Type corresponds to a .NET class that support 
-    text/value conversion through the TypeConverter architecture. 
-    Classes that don't support this are serialized and stored with the 
-    mimetype set.
-    
-    The mimetype is used for serialized objects, and tells the 
-    ResXResourceReader how to depersist the object. This is currently not 
-    extensible. For a given mimetype the value must be set accordingly:
-    
-    Note - application/x-microsoft.net.object.binary.base64 is the format 
-    that the ResXResourceWriter will generate, however the reader can 
-    read any of the formats listed below.
-    
-    mimetype: application/x-microsoft.net.object.binary.base64
-    value   : The object must be serialized with 
-            : System.Runtime.Serialization.Formatters.Binary.BinaryFormatter
-            : and then encoded with base64 encoding.
-    
-    mimetype: application/x-microsoft.net.object.soap.base64
-    value   : The object must be serialized with 
-            : System.Runtime.Serialization.Formatters.Soap.SoapFormatter
-            : and then encoded with base64 encoding.
-
-    mimetype: application/x-microsoft.net.object.bytearray.base64
-    value   : The object must be serialized into a byte array 
-            : using a System.ComponentModel.TypeConverter
-            : and then encoded with base64 encoding.
-    -->
-  <xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
-    <xsd:import namespace="http://www.w3.org/XML/1998/namespace" />
-    <xsd:element name="root" msdata:IsDataSet="true">
-      <xsd:complexType>
-        <xsd:choice maxOccurs="unbounded">
-          <xsd:element name="metadata">
-            <xsd:complexType>
-              <xsd:sequence>
-                <xsd:element name="value" type="xsd:string" minOccurs="0" />
-              </xsd:sequence>
-              <xsd:attribute name="name" use="required" type="xsd:string" />
-              <xsd:attribute name="type" type="xsd:string" />
-              <xsd:attribute name="mimetype" type="xsd:string" />
-              <xsd:attribute ref="xml:space" />
-            </xsd:complexType>
-          </xsd:element>
-          <xsd:element name="assembly">
-            <xsd:complexType>
-              <xsd:attribute name="alias" type="xsd:string" />
-              <xsd:attribute name="name" type="xsd:string" />
-            </xsd:complexType>
-          </xsd:element>
-          <xsd:element name="data">
-            <xsd:complexType>
-              <xsd:sequence>
-                <xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
-                <xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
-              </xsd:sequence>
-              <xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1" />
-              <xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
-              <xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
-              <xsd:attribute ref="xml:space" />
-            </xsd:complexType>
-          </xsd:element>
-          <xsd:element name="resheader">
-            <xsd:complexType>
-              <xsd:sequence>
-                <xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
-              </xsd:sequence>
-              <xsd:attribute name="name" type="xsd:string" use="required" />
-            </xsd:complexType>
-          </xsd:element>
-        </xsd:choice>
-      </xsd:complexType>
-    </xsd:element>
-  </xsd:schema>
-  <resheader name="resmimetype">
-    <value>text/microsoft-resx</value>
-  </resheader>
-  <resheader name="version">
-    <value>2.0</value>
-  </resheader>
-  <resheader name="reader">
-    <value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
-  </resheader>
-  <resheader name="writer">
-    <value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
-  </resheader>
-</root>
Index: branches/2521_ProblemRefactoring/HeuristicLab.Problems.TravelingSalesman/3.3/TSP.cs
===================================================================
--- branches/2521_ProblemRefactoring/HeuristicLab.Problems.TravelingSalesman/3.3/TSP.cs	(revision 17250)
+++ branches/2521_ProblemRefactoring/HeuristicLab.Problems.TravelingSalesman/3.3/TSP.cs	(revision 17251)
@@ -37,5 +37,5 @@
   [Creatable(CreatableAttribute.Categories.CombinatorialProblems, Priority = 100)]
   [StorableType("8415476a-69de-45ad-95be-298ed7c97e84")]
-  public class TSP : PermutationProblem, IProblemInstanceConsumer<TSPData> {
+  public class TSP : PermutationProblem, IProblemInstanceConsumer<TSPData>, IProblemInstanceExporter<TSPData> {
     /// <summary>
     /// This limit governs when a distance matrix is used. For all problems smaller than that, the distance matrix is
@@ -70,14 +70,6 @@
       Parameters.Add(TSPDataParameter = new ValueParameter<ITSPData>("TSPData", "The main parameters of the TSP."));
       Parameters.Add(BestKnownSolutionParameter = new OptionalValueParameter<ITSPSolution>("BestKnownSolution", "The best known solution."));
-      
-      TSPData = new EuclideanTSPData() {
-        Coordinates = new DoubleMatrix(new double[,] {
-        { 100, 100 }, { 100, 200 }, { 100, 300 }, { 100, 400 },
-        { 200, 100 }, { 200, 200 }, { 200, 300 }, { 200, 400 },
-        { 300, 100 }, { 300, 200 }, { 300, 300 }, { 300, 400 },
-        { 400, 100 }, { 400, 200 }, { 400, 300 }, { 400, 400 }
-        }),
-        Rounding = EuclideanTSPData.RoundingMode.Midpoint
-      };
+
+      TSPData = new EuclideanTSPData();
 
       InitializeOperators();
@@ -144,20 +136,20 @@
         || data.DistanceMeasure == DistanceMeasure.Maximum
         || data.Dimension <= DistanceMatrixSizeLimit) {
-        TSPData = new MatrixTSPData(data.GetDistanceMatrix(), data.Coordinates);
+        TSPData = new MatrixTSPData(data.Name, data.GetDistanceMatrix(), data.Coordinates) { Description = data.Description };
       } else if (data.DistanceMeasure == DistanceMeasure.Direct && data.Distances != null) {
-        TSPData = new MatrixTSPData(data.Distances, data.Coordinates);
+        TSPData = new MatrixTSPData(data.Name, data.Distances, data.Coordinates) { Description = data.Description };
       } else {
         switch (data.DistanceMeasure) {
           case DistanceMeasure.Euclidean:
-            TSPData = new EuclideanTSPData(data.Coordinates) { Rounding = EuclideanTSPData.RoundingMode.None };
+            TSPData = new EuclideanTSPData(data.Name, data.Coordinates, EuclideanTSPData.DistanceRounding.None) { Description = data.Description };
             break;
           case DistanceMeasure.RoundedEuclidean:
-            TSPData = new EuclideanTSPData(data.Coordinates) { Rounding = EuclideanTSPData.RoundingMode.Midpoint };
+            TSPData = new EuclideanTSPData(data.Name, data.Coordinates, EuclideanTSPData.DistanceRounding.Midpoint) { Description = data.Description };
             break;
           case DistanceMeasure.UpperEuclidean:
-            TSPData = new EuclideanTSPData(data.Coordinates) { Rounding = EuclideanTSPData.RoundingMode.Ceiling };
+            TSPData = new EuclideanTSPData(data.Name, data.Coordinates, EuclideanTSPData.DistanceRounding.Ceiling) { Description = data.Description };
             break;
           case DistanceMeasure.Geo:
-            TSPData = new GeoTSPData(data.Coordinates);
+            TSPData = new GeoTSPData(data.Name, data.Coordinates) { Description = data.Description };
             break;
           default:
@@ -184,4 +176,13 @@
     }
 
+    public TSPData Export() {
+      var instance = TSPData.Export();
+      if (!double.IsNaN(BestKnownQuality))
+        instance.BestKnownQuality = BestKnownQuality;
+      if (BestKnownSolution?.Tour != null)
+        instance.BestKnownTour = BestKnownSolution.Tour.ToArray();
+      return instance;
+    }
+
     protected override void OnEncodingChanged() {
       base.OnEncodingChanged();
Index: branches/2521_ProblemRefactoring/HeuristicLab.Problems.TravelingSalesman/3.3/TSPData.cs
===================================================================
--- branches/2521_ProblemRefactoring/HeuristicLab.Problems.TravelingSalesman/3.3/TSPData.cs	(revision 17250)
+++ branches/2521_ProblemRefactoring/HeuristicLab.Problems.TravelingSalesman/3.3/TSPData.cs	(revision 17251)
@@ -21,5 +21,4 @@
 
 using System;
-using System.ComponentModel;
 using HEAL.Attic;
 using HeuristicLab.Common;
@@ -27,29 +26,19 @@
 using HeuristicLab.Data;
 using HeuristicLab.Encodings.PermutationEncoding;
+using HeuristicLab.Problems.Instances;
 
 namespace HeuristicLab.Problems.TravelingSalesman {
   [StorableType("1a9bf60c-b6a6-4c95-8e99-5a2dec0ee892")]
-  public interface ITSPData : IItem {
+  public interface ITSPData : INamedItem {
     double GetDistance(int fromCity, int toCity);
     ITSPSolution GetSolution(Permutation tspTour, double tourLength);
+    TSPData Export();
   }
 
   [Item("Matrix-based TSP Data", "TSP that is representd by a distance matrix.")]
   [StorableType("4df58a35-679d-4414-b815-9450ae100823")]
-  public sealed class MatrixTSPData : Item, ITSPData, INotifyPropertyChanged {
-
-    [Storable]
-    public DoubleMatrix Matrix { get; private set; }
-
-    [Storable]
-    private DoubleMatrix displayCoordinates;
-    public DoubleMatrix DisplayCoordinates {
-      get => displayCoordinates;
-      set {
-        if (displayCoordinates == value) return;
-        displayCoordinates = value;
-        OnPropertyChanged(nameof(DisplayCoordinates));
-      }
-    }
+  public sealed class MatrixTSPData : NamedItem, ITSPData {
+    [Storable] public DoubleMatrix Matrix { get; private set; }
+    [Storable] public DoubleMatrix DisplayCoordinates { get; private set; }
 
     [StorableConstructor]
@@ -57,17 +46,28 @@
     private MatrixTSPData(MatrixTSPData original, Cloner cloner) : base(original, cloner) {
       Matrix = original.Matrix;
-      displayCoordinates = cloner.Clone(original.displayCoordinates);
+      DisplayCoordinates = original.DisplayCoordinates;
     }
     public MatrixTSPData() {
-      Matrix = new DoubleMatrix(new double[0, 0], @readonly: true);
-      DisplayCoordinates = null;
-    }
-    public MatrixTSPData(double[,] matrix, double[,] coordinates = null) {
+      Name = TSPDefaultInstance.Name;
+      Matrix = TSPDefaultInstance.Distances;
+      DisplayCoordinates = TSPDefaultInstance.Coordinates;
+    }
+    public MatrixTSPData(string name, double[,] matrix, double[,] coordinates = null) {
+      if (coordinates != null && coordinates.GetLength(1) != 2)
+        throw new ArgumentException("Argument must have exactly two columns.", nameof(coordinates));
+      if (coordinates != null && coordinates.GetLength(0) != matrix.GetLength(0))
+        throw new ArgumentException("Unequal number of rows in " + nameof(matrix) + " and " + nameof(coordinates) + ".");
+      Name = name;
       Matrix = new DoubleMatrix(matrix, @readonly: true);
-      if (coordinates != null) DisplayCoordinates = new DoubleMatrix(coordinates);
-      if (DisplayCoordinates != null && DisplayCoordinates.Columns != 2)
+      if (coordinates != null) DisplayCoordinates = new DoubleMatrix(coordinates, @readonly: true);
+    }
+    public MatrixTSPData(string name, DoubleMatrix matrix, DoubleMatrix coordinates = null) {
+      if (coordinates != null && coordinates.Columns != 2)
         throw new ArgumentException("Argument must have exactly two columns.", nameof(coordinates));
-      if (DisplayCoordinates != null && DisplayCoordinates.Rows != Matrix.Rows)
+      if (coordinates != null && coordinates.Rows != matrix.Rows)
         throw new ArgumentException("Unequal number of rows in " + nameof(matrix) + " and " + nameof(coordinates) + ".");
+      Name = name;
+      Matrix = (DoubleMatrix)matrix.AsReadOnly();
+      DisplayCoordinates = (DoubleMatrix)coordinates?.AsReadOnly();
     }
 
@@ -80,31 +80,15 @@
     }
 
-    public void SetMatrix(double[,] matrix, double[,] coordinates = null) {
-      Matrix = new DoubleMatrix(matrix, @readonly: true);
-      OnPropertyChanged(nameof(Matrix));
-      if (coordinates == null) DisplayCoordinates = null;
-      else DisplayCoordinates = new DoubleMatrix(coordinates);
-      if (DisplayCoordinates != null && DisplayCoordinates.Columns != 2)
-        throw new ArgumentException("Argument must have exactly two columns.", nameof(coordinates));
-      if (DisplayCoordinates != null && DisplayCoordinates.Rows != Matrix.Rows)
-        throw new ArgumentException("Unequal number of rows in " + nameof(matrix) + " and " + nameof(coordinates) + ".");
-    }
-
-    public void SetMatrix(DoubleMatrix matrix, DoubleMatrix coordinates = null) {
-      Matrix = (DoubleMatrix)matrix.AsReadOnly();
-      OnPropertyChanged(nameof(Matrix));
-      DisplayCoordinates = (DoubleMatrix)coordinates?.Clone();
-      if (DisplayCoordinates != null && DisplayCoordinates.Columns != 2)
-        throw new ArgumentException("Argument must have exactly two columns.", nameof(coordinates));
-      if (DisplayCoordinates != null && DisplayCoordinates.Rows != Matrix.Rows)
-        throw new ArgumentException("Unequal number of rows in " + nameof(matrix) + " and " + nameof(coordinates) + ".");
-    }
-
     public double GetDistance(int fromCity, int toCity) => Matrix[fromCity, toCity];
 
-
-    public event PropertyChangedEventHandler PropertyChanged;
-    private void OnPropertyChanged(string property) {
-      PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(property));
+    public TSPData Export() {
+      return new TSPData() {
+        Name = name,
+        Description = description,
+        Coordinates = DisplayCoordinates?.CloneAsMatrix(),
+        Dimension = Matrix.Rows,
+        DistanceMeasure = DistanceMeasure.Direct,
+        Distances = Matrix.CloneAsMatrix()
+      };
     }
   }
@@ -112,20 +96,27 @@
   [Item("Coordinates-based TSP Data", "TSP that is represented by coordinates of locations.")]
   [StorableType("3955d07a-d43c-4a01-9505-d2effb1ea865")]
-  public abstract class CoordinatesTSPData : Item, ITSPData {
-    [Storable]
-    public DoubleMatrix Coordinates { get; set; }
+  public abstract class CoordinatesTSPData : NamedItem, ITSPData {
+    [Storable] public DoubleMatrix Coordinates { get; private set; }
 
     [StorableConstructor]
     protected CoordinatesTSPData(StorableConstructorFlag _) : base(_) { }
     protected CoordinatesTSPData(CoordinatesTSPData original, Cloner cloner) : base(original, cloner) {
-      Coordinates = cloner.Clone(original.Coordinates);
+      Coordinates = original.Coordinates;
     }
     protected CoordinatesTSPData() : base() {
-      Coordinates = new DoubleMatrix();
-    }
-    protected CoordinatesTSPData(double[,] coordinates) : base() {
+      Name = TSPDefaultInstance.Name;
+      Coordinates = TSPDefaultInstance.Coordinates;
+    }
+    protected CoordinatesTSPData(string name, double[,] coordinates) : base() {
       if (coordinates == null) throw new ArgumentNullException(nameof(coordinates));
       if (coordinates.GetLength(1) != 2) throw new ArgumentException("Argument must have exactly two columns.", nameof(coordinates));
-      Coordinates = new DoubleMatrix(coordinates);
+      Name = name;
+      Coordinates = new DoubleMatrix(coordinates, @readonly: true);
+    }
+    protected CoordinatesTSPData(string name, DoubleMatrix coordinates) : base() {
+      if (coordinates == null) throw new ArgumentNullException(nameof(coordinates));
+      if (coordinates.Columns != 2) throw new ArgumentException("Argument must have exactly two columns.", nameof(coordinates));
+      Name = name;
+      Coordinates = (DoubleMatrix)coordinates.AsReadOnly();
     }
 
@@ -140,4 +131,6 @@
       return new TSPSolution(Coordinates, tour, new DoubleValue(tourLength));
     }
+
+    public abstract TSPData Export();
   }
 
@@ -145,8 +138,8 @@
   [StorableType("4bf58348-cd98-46c5-a4c0-55f486ca88b4")]
   public sealed class EuclideanTSPData : CoordinatesTSPData {
-    public enum RoundingMode { None, Midpoint, Ceiling }
+    public enum DistanceRounding { None, Midpoint, Ceiling }
 
     [Storable]
-    public RoundingMode Rounding { get; set; }
+    public DistanceRounding Rounding { get; private set; }
 
     [StorableConstructor]
@@ -155,6 +148,16 @@
       Rounding = original.Rounding;
     }
-    public EuclideanTSPData() : base() { }
-    public EuclideanTSPData(double[,] coordinates) : base(coordinates) { }
+    public EuclideanTSPData()
+      : base() {
+      Rounding = DistanceRounding.Midpoint;
+    }
+    public EuclideanTSPData(string name, double[,] coordinates, DistanceRounding rounding = DistanceRounding.None)
+      : base(name, coordinates) {
+      Rounding = rounding;
+    }
+    public EuclideanTSPData(string name, DoubleMatrix coordinates, DistanceRounding rounding = DistanceRounding.None)
+      : base(name, coordinates) {
+      Rounding = rounding;
+    }
 
     public override IDeepCloneable Clone(Cloner cloner) {
@@ -165,9 +168,24 @@
       var dist = Math.Sqrt((fromX - toX) * (fromX - toX) + (fromY - toY) * (fromY - toY));
       switch (Rounding) {
-        case RoundingMode.None: return dist;
-        case RoundingMode.Midpoint: return Math.Round(dist);
-        case RoundingMode.Ceiling: return Math.Ceiling(dist);
+        case DistanceRounding.None: return dist;
+        case DistanceRounding.Midpoint: return Math.Round(dist);
+        case DistanceRounding.Ceiling: return Math.Ceiling(dist);
         default: throw new InvalidOperationException("Unknown rounding mode " + Rounding);
       }
+    }
+
+    public override TSPData Export() {
+      var data = new TSPData() {
+        Name = name,
+        Description = description,
+        Coordinates = Coordinates.CloneAsMatrix(),
+        Dimension = Coordinates.Rows
+      };
+      switch (Rounding) {
+        case DistanceRounding.None: data.DistanceMeasure = DistanceMeasure.Euclidean; break;
+        case DistanceRounding.Midpoint: data.DistanceMeasure = DistanceMeasure.RoundedEuclidean; break;
+        case DistanceRounding.Ceiling: data.DistanceMeasure = DistanceMeasure.UpperEuclidean; break;
+      }
+      return data;
     }
   }
@@ -183,5 +201,6 @@
     private GeoTSPData(GeoTSPData original, Cloner cloner) : base(original, cloner) { }
     public GeoTSPData() : base() { }
-    public GeoTSPData(double[,] coordinates) : base(coordinates) { }
+    public GeoTSPData(string name, double[,] coordinates) : base(name, coordinates) { }
+    public GeoTSPData(string name, DoubleMatrix coordinates) : base(name, coordinates) { }
 
     public override IDeepCloneable Clone(Cloner cloner) {
@@ -210,4 +229,42 @@
       return PI * (Math.Truncate(x) + 5.0 * (x - Math.Truncate(x)) / 3.0) / 180.0;
     }
+
+    public override TSPData Export() {
+      return new TSPData() {
+        Name = name,
+        Description = description,
+        Coordinates = Coordinates.CloneAsMatrix(),
+        Dimension = Coordinates.Rows,
+        DistanceMeasure = DistanceMeasure.Geo
+      };
+    }
+  }
+
+  internal static class TSPDefaultInstance {
+    internal static readonly DoubleMatrix Distances = new DoubleMatrix(new double[,] {
+{ 0, 100, 200, 300, 100, 141, 224, 316, 200, 224, 283, 361, 300, 316, 361, 424 },
+{ 100, 0, 100, 200, 141, 100, 141, 224, 224, 200, 224, 283, 316, 300, 316, 361 },
+{ 200, 100, 0, 100, 224, 141, 100, 141, 283, 224, 200, 224, 361, 316, 300, 316 },
+{ 300, 200, 100, 0, 316, 224, 141, 100, 361, 283, 224, 200, 424, 361, 316, 300 },
+{ 100, 141, 224, 316, 0, 100, 200, 300, 100, 141, 224, 316, 200, 224, 283, 361 },
+{ 141, 100, 141, 224, 100, 0, 100, 200, 141, 100, 141, 224, 224, 200, 224, 283 },
+{ 224, 141, 100, 141, 200, 100, 0, 100, 224, 141, 100, 141, 283, 224, 200, 224 },
+{ 316, 224, 141, 100, 300, 200, 100, 0, 316, 224, 141, 100, 361, 283, 224, 200 },
+{ 200, 224, 283, 361, 100, 141, 224, 316, 0, 100, 200, 300, 100, 141, 224, 316 },
+{ 224, 200, 224, 283, 141, 100, 141, 224, 100, 0, 100, 200, 141, 100, 141, 224 },
+{ 283, 224, 200, 224, 224, 141, 100, 141, 200, 100, 0, 100, 224, 141, 100, 141 },
+{ 361, 283, 224, 200, 316, 224, 141, 100, 300, 200, 100, 0, 316, 224, 141, 100 },
+{ 300, 316, 361, 424, 200, 224, 283, 361, 100, 141, 224, 316, 0, 100, 200, 300 },
+{ 316, 300, 316, 361, 224, 200, 224, 283, 141, 100, 141, 224, 100, 0, 100, 200 },
+{ 361, 316, 300, 316, 283, 224, 200, 224, 224, 141, 100, 141, 200, 100, 0, 100 },
+{ 424, 361, 316, 300, 361, 283, 224, 200, 316, 224, 141, 100, 300, 200, 100, 0 },
+}, @readonly: true);
+    internal static readonly DoubleMatrix Coordinates = new DoubleMatrix(new double[,] {
+{ 100, 100 }, { 100, 200 }, { 100, 300 }, { 100, 400 },
+{ 200, 100 }, { 200, 200 }, { 200, 300 }, { 200, 400 },
+{ 300, 100 }, { 300, 200 }, { 300, 300 }, { 300, 400 },
+{ 400, 100 }, { 400, 200 }, { 400, 300 }, { 400, 400 }
+}, @readonly: true);
+    internal static readonly string Name = "HL TSP Default";
   }
 }
