Changeset 17251


Ignore:
Timestamp:
09/13/19 11:37:59 (3 years ago)
Author:
abeham
Message:

#2521: finished refactoring TSP

Location:
branches/2521_ProblemRefactoring
Files:
4 added
2 deleted
8 edited

Legend:

Unmodified
Added
Removed
  • branches/2521_ProblemRefactoring/HeuristicLab.Data/3.3/ValueTypeMatrix.cs

    r17248 r17251  
    190190
    191191    public virtual ValueTypeMatrix<T> AsReadOnly() {
    192       ValueTypeMatrix<T> readOnlyValueTypeMatrix = (ValueTypeMatrix<T>)this.Clone();
     192      if (readOnly) return this;
     193      var readOnlyValueTypeMatrix = (ValueTypeMatrix<T>)this.Clone();
    193194      readOnlyValueTypeMatrix.readOnly = true;
    194195      return readOnlyValueTypeMatrix;
  • branches/2521_ProblemRefactoring/HeuristicLab.Optimizer/3.3/StartPage.cs

    r17241 r17251  
    2222using System;
    2323using System.Collections.Generic;
     24using System.Drawing;
    2425using System.IO;
    2526using System.Linq;
     
    110111        }
    111112
    112       } catch {
    113113      } finally {
    114114        OnAllSamplesLoaded();
     
    120120      using (var stream = assembly.GetManifestResourceStream(name)) {
    121121        var serializer = new ProtoBufSerializer();
    122         var item = (NamedItem)serializer.Deserialize(stream, false);
     122        NamedItem item;
     123        try {
     124          item = (NamedItem)serializer.Deserialize(stream, false);
     125        } catch {
     126          item = new ErrorMessage(name, "Sample failed to load!");
     127        }
    123128        OnSampleLoaded(item, group, 1.0 / count);
    124129      }
     
    197202      Properties.Settings.Default.Save();
    198203    }
     204
     205    [Item("Error Message", "")]
     206    class ErrorMessage : NamedItem {
     207      public override Image ItemImage => Common.Resources.VSImageLibrary.Error;
     208
     209      protected ErrorMessage(ErrorMessage original, Cloner cloner) : base(original, cloner) { }
     210      public ErrorMessage(string error, string description) : base(error, description) { }
     211
     212      public override IDeepCloneable Clone(Cloner cloner) {
     213        return new ErrorMessage(this, cloner);
     214      }
     215    }
    199216  }
    200217}
  • branches/2521_ProblemRefactoring/HeuristicLab.Problems.Instances.TSPLIB/3.3/TSPLIBTSPInstanceProvider.cs

    r17226 r17251  
    9696    }
    9797
     98    public override bool CanExportData => true;
     99
     100    public override void ExportData(TSPData instance, string path) {
     101      using (var writer = new StreamWriter(File.OpenWrite(path))) {
     102        writer.WriteLine("NAME: " + instance.Name);
     103        writer.WriteLine("TYPE: TSP");
     104        writer.WriteLine("COMMENT: " + instance.Description.Replace(Environment.NewLine, " \\\\ " ));
     105        writer.WriteLine("DIMENSION: " + instance.Dimension);
     106
     107        if (instance.DistanceMeasure == DistanceMeasure.Euclidean) {
     108          // TSPLIB only knows rounded euclidean distance
     109          instance.Distances = instance.GetDistanceMatrix();
     110          instance.DistanceMeasure = DistanceMeasure.Direct;
     111        }
     112
     113        if (instance.DistanceMeasure == DistanceMeasure.Direct) {
     114          writer.WriteLine("EDGE_WEIGHT_TYPE: EXPLICIT");
     115          writer.WriteLine("EDGE_WEIGHT_FORMAT: UPPER_ROW");
     116          if (instance.Coordinates != null && instance.Coordinates.GetLength(1) == 2) {
     117            writer.WriteLine("DISPLAY_DATA_TYPE: TWOD_DISPLAY");
     118          }
     119        } else {
     120          writer.Write("EDGE_WEIGHT_TYPE: ");
     121          switch (instance.DistanceMeasure) {
     122            case DistanceMeasure.RoundedEuclidean:
     123              writer.WriteLine("EUC_2D");
     124              break;
     125            case DistanceMeasure.UpperEuclidean:
     126              writer.WriteLine("CEIL_2D");
     127              break;
     128            case DistanceMeasure.Att:
     129              writer.WriteLine("ATT");
     130              break;
     131            case DistanceMeasure.Geo:
     132              writer.WriteLine("GEO");
     133              break;
     134            case DistanceMeasure.Manhattan:
     135              writer.WriteLine("MAN_2D");
     136              break;
     137            case DistanceMeasure.Maximum:
     138              writer.WriteLine("MAX_2D");
     139              break;
     140            default: throw new InvalidOperationException("Unknown distance measure: " + instance.DistanceMeasure);
     141          }
     142          writer.WriteLine("DISPLAY_DATA_TYPE: COORD_DISPLAY");
     143        }
     144
     145        if (instance.DistanceMeasure == DistanceMeasure.Direct) {
     146          writer.WriteLine("EDGE_WEIGHT_SECTION");
     147          for (var i = 0; i < instance.Distances.GetLength(0) - 1; i++) {
     148            for (var j = i + 1; j < instance.Distances.GetLength(1); j++) {
     149              writer.Write(instance.Distances[i, j] + " ");
     150            }
     151            writer.WriteLine();
     152          }
     153        }
     154
     155        if (instance.Coordinates != null && instance.Coordinates.GetLength(1) == 2) {
     156          if (instance.DistanceMeasure == DistanceMeasure.Direct)
     157            writer.WriteLine("DISPLAY_DATA_SECTION");
     158          else writer.WriteLine("NODE_COORD_SECTION");
     159          for (var i = 1; i <= instance.Coordinates.GetLength(0); i++) {
     160            writer.WriteLine(i + " " + instance.Coordinates[i - 1, 0] + " " + instance.Coordinates[i - 1, 1]);
     161          }
     162        }
     163        writer.WriteLine("EOF");
     164        writer.Flush();
     165      }
     166    }
    98167  }
    99168}
  • branches/2521_ProblemRefactoring/HeuristicLab.Problems.TravelingSalesman.Views/3.3/HeuristicLab.Problems.TravelingSalesman.Views-3.3.csproj

    r17248 r17251  
    123123  </ItemGroup>
    124124  <ItemGroup>
     125    <Compile Include="CoordinatesTSPDataView.cs">
     126      <SubType>UserControl</SubType>
     127    </Compile>
     128    <Compile Include="CoordinatesTSPDataView.Designer.cs">
     129      <DependentUpon>CoordinatesTSPDataView.cs</DependentUpon>
     130    </Compile>
     131    <Compile Include="EuclideanTSPDataView.cs">
     132      <SubType>UserControl</SubType>
     133    </Compile>
     134    <Compile Include="EuclideanTSPDataView.Designer.cs">
     135      <DependentUpon>EuclideanTSPDataView.cs</DependentUpon>
     136    </Compile>
    125137    <Compile Include="MatrixTSPDataView.cs">
    126138      <SubType>UserControl</SubType>
     
    235247      <Private>False</Private>
    236248    </ProjectReference>
    237   </ItemGroup>
    238   <ItemGroup>
    239     <EmbeddedResource Include="MatrixTSPDataView.resx">
    240       <DependentUpon>MatrixTSPDataView.cs</DependentUpon>
    241     </EmbeddedResource>
    242     <EmbeddedResource Include="TSPSolutionView.resx">
    243       <DependentUpon>TSPSolutionView.cs</DependentUpon>
    244     </EmbeddedResource>
    245249  </ItemGroup>
    246250  <Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
  • branches/2521_ProblemRefactoring/HeuristicLab.Problems.TravelingSalesman.Views/3.3/MatrixTSPDataView.Designer.cs

    r17248 r17251  
    2626      this.tabControl = new System.Windows.Forms.TabControl();
    2727      this.distancesTabPage = new System.Windows.Forms.TabPage();
    28       this.setMatrixButton = new System.Windows.Forms.Button();
     28      this.distanceMatrixView = new HeuristicLab.Data.Views.StringConvertibleMatrixView();
    2929      this.coordinatesTabPage = new System.Windows.Forms.TabPage();
    30       this.distanceMatrixView = new HeuristicLab.Data.Views.StringConvertibleMatrixView();
    3130      this.coordinatesSplitContainer = new System.Windows.Forms.SplitContainer();
    32       this.setCoordinatesButton = new System.Windows.Forms.Button();
    3331      this.coordinatesMatrixView = new HeuristicLab.Data.Views.StringConvertibleMatrixView();
    3432      this.coordinatesPictureBox = new System.Windows.Forms.PictureBox();
     33      ((System.ComponentModel.ISupportInitialize)(this.errorProvider)).BeginInit();
    3534      this.tabControl.SuspendLayout();
    3635      this.distancesTabPage.SuspendLayout();
     
    4342      this.SuspendLayout();
    4443      //
     44      // nameTextBox
     45      //
     46      this.errorProvider.SetIconAlignment(this.nameTextBox, System.Windows.Forms.ErrorIconAlignment.MiddleLeft);
     47      this.errorProvider.SetIconPadding(this.nameTextBox, 2);
     48      this.nameTextBox.Size = new System.Drawing.Size(688, 20);
     49      //
     50      // infoLabel
     51      //
     52      this.infoLabel.Location = new System.Drawing.Point(752, 3);
     53      //
    4554      // tabControl
    4655      //
     56      this.tabControl.Anchor = ((System.Windows.Forms.AnchorStyles)((((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom)
     57            | System.Windows.Forms.AnchorStyles.Left)
     58            | System.Windows.Forms.AnchorStyles.Right)));
    4759      this.tabControl.Controls.Add(this.distancesTabPage);
    4860      this.tabControl.Controls.Add(this.coordinatesTabPage);
    49       this.tabControl.Dock = System.Windows.Forms.DockStyle.Fill;
    50       this.tabControl.Location = new System.Drawing.Point(0, 0);
     61      this.tabControl.Location = new System.Drawing.Point(0, 26);
    5162      this.tabControl.Name = "tabControl";
    5263      this.tabControl.SelectedIndex = 0;
    53       this.tabControl.Size = new System.Drawing.Size(771, 596);
     64      this.tabControl.Size = new System.Drawing.Size(771, 570);
    5465      this.tabControl.TabIndex = 1;
    5566      //
    5667      // distancesTabPage
    5768      //
    58       this.distancesTabPage.Controls.Add(this.setMatrixButton);
    5969      this.distancesTabPage.Controls.Add(this.distanceMatrixView);
    6070      this.distancesTabPage.Location = new System.Drawing.Point(4, 22);
    6171      this.distancesTabPage.Name = "distancesTabPage";
    6272      this.distancesTabPage.Padding = new System.Windows.Forms.Padding(3);
    63       this.distancesTabPage.Size = new System.Drawing.Size(763, 570);
     73      this.distancesTabPage.Size = new System.Drawing.Size(763, 544);
    6474      this.distancesTabPage.TabIndex = 0;
    6575      this.distancesTabPage.Text = "Distances";
    6676      this.distancesTabPage.UseVisualStyleBackColor = true;
    6777      //
    68       // setMatrixButton
     78      // distanceMatrixView
    6979      //
    70       this.setMatrixButton.Location = new System.Drawing.Point(6, 6);
    71       this.setMatrixButton.Name = "setMatrixButton";
    72       this.setMatrixButton.Size = new System.Drawing.Size(26, 23);
    73       this.setMatrixButton.TabIndex = 1;
    74       this.setMatrixButton.Text = "Set";
    75       this.setMatrixButton.TextImageRelation = System.Windows.Forms.TextImageRelation.ImageBeforeText;
    76       this.setMatrixButton.UseVisualStyleBackColor = true;
    77       this.setMatrixButton.Click += new System.EventHandler(this.SetMatrixButton_Click);
     80      this.distanceMatrixView.Caption = "StringConvertibleMatrix View";
     81      this.distanceMatrixView.Content = null;
     82      this.distanceMatrixView.Dock = System.Windows.Forms.DockStyle.Fill;
     83      this.distanceMatrixView.Location = new System.Drawing.Point(3, 3);
     84      this.distanceMatrixView.Name = "distanceMatrixView";
     85      this.distanceMatrixView.ReadOnly = false;
     86      this.distanceMatrixView.ShowRowsAndColumnsTextBox = true;
     87      this.distanceMatrixView.ShowStatisticalInformation = true;
     88      this.distanceMatrixView.Size = new System.Drawing.Size(757, 538);
     89      this.distanceMatrixView.TabIndex = 0;
    7890      //
    7991      // coordinatesTabPage
     
    88100      this.coordinatesTabPage.UseVisualStyleBackColor = true;
    89101      //
    90       // distanceMatrixView
    91       //
    92       this.distanceMatrixView.Anchor = ((System.Windows.Forms.AnchorStyles)((((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom)
    93             | System.Windows.Forms.AnchorStyles.Left)
    94             | System.Windows.Forms.AnchorStyles.Right)));
    95       this.distanceMatrixView.Caption = "StringConvertibleMatrix View";
    96       this.distanceMatrixView.Content = null;
    97       this.distanceMatrixView.Location = new System.Drawing.Point(6, 35);
    98       this.distanceMatrixView.Name = "distanceMatrixView";
    99       this.distanceMatrixView.ReadOnly = false;
    100       this.distanceMatrixView.ShowRowsAndColumnsTextBox = true;
    101       this.distanceMatrixView.ShowStatisticalInformation = true;
    102       this.distanceMatrixView.Size = new System.Drawing.Size(751, 529);
    103       this.distanceMatrixView.TabIndex = 0;
    104       //
    105102      // coordinatesSplitContainer
    106103      //
     
    111108      // coordinatesSplitContainer.Panel1
    112109      //
    113       this.coordinatesSplitContainer.Panel1.Controls.Add(this.setCoordinatesButton);
    114110      this.coordinatesSplitContainer.Panel1.Controls.Add(this.coordinatesMatrixView);
    115111      //
     
    121117      this.coordinatesSplitContainer.TabIndex = 0;
    122118      //
    123       // setCoordinatesButton
    124       //
    125       this.setCoordinatesButton.Location = new System.Drawing.Point(3, 3);
    126       this.setCoordinatesButton.Name = "setCoordinatesButton";
    127       this.setCoordinatesButton.Size = new System.Drawing.Size(26, 23);
    128       this.setCoordinatesButton.TabIndex = 2;
    129       this.setCoordinatesButton.Text = "Set";
    130       this.setCoordinatesButton.TextImageRelation = System.Windows.Forms.TextImageRelation.ImageBeforeText;
    131       this.setCoordinatesButton.UseVisualStyleBackColor = true;
    132       this.setCoordinatesButton.Click += new System.EventHandler(this.SetCoordinatesButton_Click);
    133       //
    134119      // coordinatesMatrixView
    135120      //
    136       this.coordinatesMatrixView.Anchor = ((System.Windows.Forms.AnchorStyles)((((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom)
    137             | System.Windows.Forms.AnchorStyles.Left)
    138             | System.Windows.Forms.AnchorStyles.Right)));
    139121      this.coordinatesMatrixView.Caption = "StringConvertibleMatrix View";
    140122      this.coordinatesMatrixView.Content = null;
    141       this.coordinatesMatrixView.Location = new System.Drawing.Point(0, 32);
     123      this.coordinatesMatrixView.Dock = System.Windows.Forms.DockStyle.Fill;
     124      this.coordinatesMatrixView.Location = new System.Drawing.Point(0, 0);
    142125      this.coordinatesMatrixView.Name = "coordinatesMatrixView";
    143126      this.coordinatesMatrixView.ReadOnly = false;
    144127      this.coordinatesMatrixView.ShowRowsAndColumnsTextBox = true;
    145128      this.coordinatesMatrixView.ShowStatisticalInformation = true;
    146       this.coordinatesMatrixView.Size = new System.Drawing.Size(249, 532);
     129      this.coordinatesMatrixView.Size = new System.Drawing.Size(252, 564);
    147130      this.coordinatesMatrixView.TabIndex = 1;
    148131      //
     
    163146      this.Name = "MatrixTSPDataView";
    164147      this.Size = new System.Drawing.Size(771, 596);
     148      this.Controls.SetChildIndex(this.tabControl, 0);
     149      this.Controls.SetChildIndex(this.nameLabel, 0);
     150      this.Controls.SetChildIndex(this.nameTextBox, 0);
     151      this.Controls.SetChildIndex(this.infoLabel, 0);
     152      ((System.ComponentModel.ISupportInitialize)(this.errorProvider)).EndInit();
    165153      this.tabControl.ResumeLayout(false);
    166154      this.distancesTabPage.ResumeLayout(false);
     
    172160      ((System.ComponentModel.ISupportInitialize)(this.coordinatesPictureBox)).EndInit();
    173161      this.ResumeLayout(false);
     162      this.PerformLayout();
    174163
    175164    }
     
    183172    private Data.Views.StringConvertibleMatrixView coordinatesMatrixView;
    184173    private System.Windows.Forms.TabPage distancesTabPage;
    185     private System.Windows.Forms.Button setMatrixButton;
    186174    private System.Windows.Forms.PictureBox coordinatesPictureBox;
    187     private System.Windows.Forms.Button setCoordinatesButton;
    188175  }
    189176}
  • branches/2521_ProblemRefactoring/HeuristicLab.Problems.TravelingSalesman.Views/3.3/MatrixTSPDataView.cs

    r17248 r17251  
    2020#endregion
    2121
    22 using System;
    23 using System.ComponentModel;
    2422using System.Drawing;
    2523using System.Windows.Forms;
    26 using HeuristicLab.Common.Resources;
    2724using HeuristicLab.Core.Views;
    2825using HeuristicLab.Data;
     
    3330  [View("Matrix TSP Data View")]
    3431  [Content(typeof(MatrixTSPData), IsDefaultView = true)]
    35   public partial class MatrixTSPDataView : ItemView {
     32  public partial class MatrixTSPDataView : NamedItemView {
    3633
    3734    public new MatrixTSPData Content {
     
    4239    public MatrixTSPDataView() {
    4340      InitializeComponent();
    44       setMatrixButton.Text = string.Empty;
    45       setMatrixButton.Image = VSImageLibrary.Edit;
    46       setCoordinatesButton.Text = string.Empty;
    47       setCoordinatesButton.Image = VSImageLibrary.Edit;
    4841    }
    49 
    50     #region Content Events
    51     protected override void RegisterContentEvents() {
    52       base.RegisterContentEvents();
    53       Content.PropertyChanged += ContentOnPropertyChanged;
    54       if (Content.DisplayCoordinates != null) {
    55         Content.DisplayCoordinates.Reset += ContentDisplayCoordinatesOnChanged;
    56         Content.DisplayCoordinates.ItemChanged += ContentDisplayCoordinatesOnChanged;
    57       }
    58     }
    59 
    60     protected override void DeregisterContentEvents() {
    61       base.DeregisterContentEvents();
    62       Content.PropertyChanged -= ContentOnPropertyChanged;
    63       if (Content.DisplayCoordinates != null) {
    64         Content.DisplayCoordinates.Reset -= ContentDisplayCoordinatesOnChanged;
    65         Content.DisplayCoordinates.ItemChanged -= ContentDisplayCoordinatesOnChanged;
    66       }
    67     }
    68 
    69     private void ContentOnPropertyChanged(object sender, PropertyChangedEventArgs e) {
    70       switch (e.PropertyName) {
    71         case nameof(Content.Matrix):
    72           distanceMatrixView.Content = Content.Matrix;
    73           break;
    74         case nameof(Content.DisplayCoordinates):
    75           if (coordinatesMatrixView.Content != null) {
    76             coordinatesMatrixView.Content.Reset -= ContentDisplayCoordinatesOnChanged;
    77             coordinatesMatrixView.Content.ItemChanged -= ContentDisplayCoordinatesOnChanged;
    78           }
    79           if (Content.DisplayCoordinates != null) {
    80             Content.DisplayCoordinates.Reset += ContentDisplayCoordinatesOnChanged;
    81             Content.DisplayCoordinates.ItemChanged += ContentDisplayCoordinatesOnChanged;
    82           }
    83           coordinatesMatrixView.Content = Content.DisplayCoordinates;
    84           GenerateImage();
    85           break;
    86       }
    87     }
    88 
    89     private void ContentDisplayCoordinatesOnChanged(object sender, EventArgs e) {
    90       GenerateImage();
    91     }
    92     #endregion
    9342
    9443    protected override void OnContentChanged() {
     
    10756    protected override void SetEnabledStateOfControls() {
    10857      base.SetEnabledStateOfControls();
    109       setMatrixButton.Enabled = !ReadOnly && !Locked && Content != null;
    110       setCoordinatesButton.Enabled = !ReadOnly && !Locked && Content != null;
    11158      distanceMatrixView.Enabled = !ReadOnly && !Locked && Content != null;
    11259      coordinatesMatrixView.Enabled = !ReadOnly && !Locked && Content != null;
     
    15299      }
    153100    }
    154 
    155     private void SetCoordinatesButton_Click(object sender, EventArgs e) {
    156       if (Content.DisplayCoordinates != null) {
    157         Content.DisplayCoordinates.Reset -= ContentDisplayCoordinatesOnChanged;
    158         Content.DisplayCoordinates.ItemChanged -= ContentDisplayCoordinatesOnChanged;
    159       }
    160       var items = Math.Max(Content.Matrix.Rows, 1);
    161       Content.DisplayCoordinates = new DoubleMatrix(items, 2);
    162     }
    163 
    164     private void SetMatrixButton_Click(object sender, EventArgs e) {
    165       MessageBox.Show("Not yet implemented");
    166     }
    167101  }
    168102}
  • branches/2521_ProblemRefactoring/HeuristicLab.Problems.TravelingSalesman/3.3/TSP.cs

    r17248 r17251  
    3737  [Creatable(CreatableAttribute.Categories.CombinatorialProblems, Priority = 100)]
    3838  [StorableType("8415476a-69de-45ad-95be-298ed7c97e84")]
    39   public class TSP : PermutationProblem, IProblemInstanceConsumer<TSPData> {
     39  public class TSP : PermutationProblem, IProblemInstanceConsumer<TSPData>, IProblemInstanceExporter<TSPData> {
    4040    /// <summary>
    4141    /// This limit governs when a distance matrix is used. For all problems smaller than that, the distance matrix is
     
    7070      Parameters.Add(TSPDataParameter = new ValueParameter<ITSPData>("TSPData", "The main parameters of the TSP."));
    7171      Parameters.Add(BestKnownSolutionParameter = new OptionalValueParameter<ITSPSolution>("BestKnownSolution", "The best known solution."));
    72      
    73       TSPData = new EuclideanTSPData() {
    74         Coordinates = new DoubleMatrix(new double[,] {
    75         { 100, 100 }, { 100, 200 }, { 100, 300 }, { 100, 400 },
    76         { 200, 100 }, { 200, 200 }, { 200, 300 }, { 200, 400 },
    77         { 300, 100 }, { 300, 200 }, { 300, 300 }, { 300, 400 },
    78         { 400, 100 }, { 400, 200 }, { 400, 300 }, { 400, 400 }
    79         }),
    80         Rounding = EuclideanTSPData.RoundingMode.Midpoint
    81       };
     72
     73      TSPData = new EuclideanTSPData();
    8274
    8375      InitializeOperators();
     
    144136        || data.DistanceMeasure == DistanceMeasure.Maximum
    145137        || data.Dimension <= DistanceMatrixSizeLimit) {
    146         TSPData = new MatrixTSPData(data.GetDistanceMatrix(), data.Coordinates);
     138        TSPData = new MatrixTSPData(data.Name, data.GetDistanceMatrix(), data.Coordinates) { Description = data.Description };
    147139      } else if (data.DistanceMeasure == DistanceMeasure.Direct && data.Distances != null) {
    148         TSPData = new MatrixTSPData(data.Distances, data.Coordinates);
     140        TSPData = new MatrixTSPData(data.Name, data.Distances, data.Coordinates) { Description = data.Description };
    149141      } else {
    150142        switch (data.DistanceMeasure) {
    151143          case DistanceMeasure.Euclidean:
    152             TSPData = new EuclideanTSPData(data.Coordinates) { Rounding = EuclideanTSPData.RoundingMode.None };
     144            TSPData = new EuclideanTSPData(data.Name, data.Coordinates, EuclideanTSPData.DistanceRounding.None) { Description = data.Description };
    153145            break;
    154146          case DistanceMeasure.RoundedEuclidean:
    155             TSPData = new EuclideanTSPData(data.Coordinates) { Rounding = EuclideanTSPData.RoundingMode.Midpoint };
     147            TSPData = new EuclideanTSPData(data.Name, data.Coordinates, EuclideanTSPData.DistanceRounding.Midpoint) { Description = data.Description };
    156148            break;
    157149          case DistanceMeasure.UpperEuclidean:
    158             TSPData = new EuclideanTSPData(data.Coordinates) { Rounding = EuclideanTSPData.RoundingMode.Ceiling };
     150            TSPData = new EuclideanTSPData(data.Name, data.Coordinates, EuclideanTSPData.DistanceRounding.Ceiling) { Description = data.Description };
    159151            break;
    160152          case DistanceMeasure.Geo:
    161             TSPData = new GeoTSPData(data.Coordinates);
     153            TSPData = new GeoTSPData(data.Name, data.Coordinates) { Description = data.Description };
    162154            break;
    163155          default:
     
    184176    }
    185177
     178    public TSPData Export() {
     179      var instance = TSPData.Export();
     180      if (!double.IsNaN(BestKnownQuality))
     181        instance.BestKnownQuality = BestKnownQuality;
     182      if (BestKnownSolution?.Tour != null)
     183        instance.BestKnownTour = BestKnownSolution.Tour.ToArray();
     184      return instance;
     185    }
     186
    186187    protected override void OnEncodingChanged() {
    187188      base.OnEncodingChanged();
  • branches/2521_ProblemRefactoring/HeuristicLab.Problems.TravelingSalesman/3.3/TSPData.cs

    r17248 r17251  
    2121
    2222using System;
    23 using System.ComponentModel;
    2423using HEAL.Attic;
    2524using HeuristicLab.Common;
     
    2726using HeuristicLab.Data;
    2827using HeuristicLab.Encodings.PermutationEncoding;
     28using HeuristicLab.Problems.Instances;
    2929
    3030namespace HeuristicLab.Problems.TravelingSalesman {
    3131  [StorableType("1a9bf60c-b6a6-4c95-8e99-5a2dec0ee892")]
    32   public interface ITSPData : IItem {
     32  public interface ITSPData : INamedItem {
    3333    double GetDistance(int fromCity, int toCity);
    3434    ITSPSolution GetSolution(Permutation tspTour, double tourLength);
     35    TSPData Export();
    3536  }
    3637
    3738  [Item("Matrix-based TSP Data", "TSP that is representd by a distance matrix.")]
    3839  [StorableType("4df58a35-679d-4414-b815-9450ae100823")]
    39   public sealed class MatrixTSPData : Item, ITSPData, INotifyPropertyChanged {
    40 
    41     [Storable]
    42     public DoubleMatrix Matrix { get; private set; }
    43 
    44     [Storable]
    45     private DoubleMatrix displayCoordinates;
    46     public DoubleMatrix DisplayCoordinates {
    47       get => displayCoordinates;
    48       set {
    49         if (displayCoordinates == value) return;
    50         displayCoordinates = value;
    51         OnPropertyChanged(nameof(DisplayCoordinates));
    52       }
    53     }
     40  public sealed class MatrixTSPData : NamedItem, ITSPData {
     41    [Storable] public DoubleMatrix Matrix { get; private set; }
     42    [Storable] public DoubleMatrix DisplayCoordinates { get; private set; }
    5443
    5544    [StorableConstructor]
     
    5746    private MatrixTSPData(MatrixTSPData original, Cloner cloner) : base(original, cloner) {
    5847      Matrix = original.Matrix;
    59       displayCoordinates = cloner.Clone(original.displayCoordinates);
     48      DisplayCoordinates = original.DisplayCoordinates;
    6049    }
    6150    public MatrixTSPData() {
    62       Matrix = new DoubleMatrix(new double[0, 0], @readonly: true);
    63       DisplayCoordinates = null;
    64     }
    65     public MatrixTSPData(double[,] matrix, double[,] coordinates = null) {
     51      Name = TSPDefaultInstance.Name;
     52      Matrix = TSPDefaultInstance.Distances;
     53      DisplayCoordinates = TSPDefaultInstance.Coordinates;
     54    }
     55    public MatrixTSPData(string name, double[,] matrix, double[,] coordinates = null) {
     56      if (coordinates != null && coordinates.GetLength(1) != 2)
     57        throw new ArgumentException("Argument must have exactly two columns.", nameof(coordinates));
     58      if (coordinates != null && coordinates.GetLength(0) != matrix.GetLength(0))
     59        throw new ArgumentException("Unequal number of rows in " + nameof(matrix) + " and " + nameof(coordinates) + ".");
     60      Name = name;
    6661      Matrix = new DoubleMatrix(matrix, @readonly: true);
    67       if (coordinates != null) DisplayCoordinates = new DoubleMatrix(coordinates);
    68       if (DisplayCoordinates != null && DisplayCoordinates.Columns != 2)
     62      if (coordinates != null) DisplayCoordinates = new DoubleMatrix(coordinates, @readonly: true);
     63    }
     64    public MatrixTSPData(string name, DoubleMatrix matrix, DoubleMatrix coordinates = null) {
     65      if (coordinates != null && coordinates.Columns != 2)
    6966        throw new ArgumentException("Argument must have exactly two columns.", nameof(coordinates));
    70       if (DisplayCoordinates != null && DisplayCoordinates.Rows != Matrix.Rows)
     67      if (coordinates != null && coordinates.Rows != matrix.Rows)
    7168        throw new ArgumentException("Unequal number of rows in " + nameof(matrix) + " and " + nameof(coordinates) + ".");
     69      Name = name;
     70      Matrix = (DoubleMatrix)matrix.AsReadOnly();
     71      DisplayCoordinates = (DoubleMatrix)coordinates?.AsReadOnly();
    7272    }
    7373
     
    8080    }
    8181
    82     public void SetMatrix(double[,] matrix, double[,] coordinates = null) {
    83       Matrix = new DoubleMatrix(matrix, @readonly: true);
    84       OnPropertyChanged(nameof(Matrix));
    85       if (coordinates == null) DisplayCoordinates = null;
    86       else DisplayCoordinates = new DoubleMatrix(coordinates);
    87       if (DisplayCoordinates != null && DisplayCoordinates.Columns != 2)
    88         throw new ArgumentException("Argument must have exactly two columns.", nameof(coordinates));
    89       if (DisplayCoordinates != null && DisplayCoordinates.Rows != Matrix.Rows)
    90         throw new ArgumentException("Unequal number of rows in " + nameof(matrix) + " and " + nameof(coordinates) + ".");
    91     }
    92 
    93     public void SetMatrix(DoubleMatrix matrix, DoubleMatrix coordinates = null) {
    94       Matrix = (DoubleMatrix)matrix.AsReadOnly();
    95       OnPropertyChanged(nameof(Matrix));
    96       DisplayCoordinates = (DoubleMatrix)coordinates?.Clone();
    97       if (DisplayCoordinates != null && DisplayCoordinates.Columns != 2)
    98         throw new ArgumentException("Argument must have exactly two columns.", nameof(coordinates));
    99       if (DisplayCoordinates != null && DisplayCoordinates.Rows != Matrix.Rows)
    100         throw new ArgumentException("Unequal number of rows in " + nameof(matrix) + " and " + nameof(coordinates) + ".");
    101     }
    102 
    10382    public double GetDistance(int fromCity, int toCity) => Matrix[fromCity, toCity];
    10483
    105 
    106     public event PropertyChangedEventHandler PropertyChanged;
    107     private void OnPropertyChanged(string property) {
    108       PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(property));
     84    public TSPData Export() {
     85      return new TSPData() {
     86        Name = name,
     87        Description = description,
     88        Coordinates = DisplayCoordinates?.CloneAsMatrix(),
     89        Dimension = Matrix.Rows,
     90        DistanceMeasure = DistanceMeasure.Direct,
     91        Distances = Matrix.CloneAsMatrix()
     92      };
    10993    }
    11094  }
     
    11296  [Item("Coordinates-based TSP Data", "TSP that is represented by coordinates of locations.")]
    11397  [StorableType("3955d07a-d43c-4a01-9505-d2effb1ea865")]
    114   public abstract class CoordinatesTSPData : Item, ITSPData {
    115     [Storable]
    116     public DoubleMatrix Coordinates { get; set; }
     98  public abstract class CoordinatesTSPData : NamedItem, ITSPData {
     99    [Storable] public DoubleMatrix Coordinates { get; private set; }
    117100
    118101    [StorableConstructor]
    119102    protected CoordinatesTSPData(StorableConstructorFlag _) : base(_) { }
    120103    protected CoordinatesTSPData(CoordinatesTSPData original, Cloner cloner) : base(original, cloner) {
    121       Coordinates = cloner.Clone(original.Coordinates);
     104      Coordinates = original.Coordinates;
    122105    }
    123106    protected CoordinatesTSPData() : base() {
    124       Coordinates = new DoubleMatrix();
    125     }
    126     protected CoordinatesTSPData(double[,] coordinates) : base() {
     107      Name = TSPDefaultInstance.Name;
     108      Coordinates = TSPDefaultInstance.Coordinates;
     109    }
     110    protected CoordinatesTSPData(string name, double[,] coordinates) : base() {
    127111      if (coordinates == null) throw new ArgumentNullException(nameof(coordinates));
    128112      if (coordinates.GetLength(1) != 2) throw new ArgumentException("Argument must have exactly two columns.", nameof(coordinates));
    129       Coordinates = new DoubleMatrix(coordinates);
     113      Name = name;
     114      Coordinates = new DoubleMatrix(coordinates, @readonly: true);
     115    }
     116    protected CoordinatesTSPData(string name, DoubleMatrix coordinates) : base() {
     117      if (coordinates == null) throw new ArgumentNullException(nameof(coordinates));
     118      if (coordinates.Columns != 2) throw new ArgumentException("Argument must have exactly two columns.", nameof(coordinates));
     119      Name = name;
     120      Coordinates = (DoubleMatrix)coordinates.AsReadOnly();
    130121    }
    131122
     
    140131      return new TSPSolution(Coordinates, tour, new DoubleValue(tourLength));
    141132    }
     133
     134    public abstract TSPData Export();
    142135  }
    143136
     
    145138  [StorableType("4bf58348-cd98-46c5-a4c0-55f486ca88b4")]
    146139  public sealed class EuclideanTSPData : CoordinatesTSPData {
    147     public enum RoundingMode { None, Midpoint, Ceiling }
     140    public enum DistanceRounding { None, Midpoint, Ceiling }
    148141
    149142    [Storable]
    150     public RoundingMode Rounding { get; set; }
     143    public DistanceRounding Rounding { get; private set; }
    151144
    152145    [StorableConstructor]
     
    155148      Rounding = original.Rounding;
    156149    }
    157     public EuclideanTSPData() : base() { }
    158     public EuclideanTSPData(double[,] coordinates) : base(coordinates) { }
     150    public EuclideanTSPData()
     151      : base() {
     152      Rounding = DistanceRounding.Midpoint;
     153    }
     154    public EuclideanTSPData(string name, double[,] coordinates, DistanceRounding rounding = DistanceRounding.None)
     155      : base(name, coordinates) {
     156      Rounding = rounding;
     157    }
     158    public EuclideanTSPData(string name, DoubleMatrix coordinates, DistanceRounding rounding = DistanceRounding.None)
     159      : base(name, coordinates) {
     160      Rounding = rounding;
     161    }
    159162
    160163    public override IDeepCloneable Clone(Cloner cloner) {
     
    165168      var dist = Math.Sqrt((fromX - toX) * (fromX - toX) + (fromY - toY) * (fromY - toY));
    166169      switch (Rounding) {
    167         case RoundingMode.None: return dist;
    168         case RoundingMode.Midpoint: return Math.Round(dist);
    169         case RoundingMode.Ceiling: return Math.Ceiling(dist);
     170        case DistanceRounding.None: return dist;
     171        case DistanceRounding.Midpoint: return Math.Round(dist);
     172        case DistanceRounding.Ceiling: return Math.Ceiling(dist);
    170173        default: throw new InvalidOperationException("Unknown rounding mode " + Rounding);
    171174      }
     175    }
     176
     177    public override TSPData Export() {
     178      var data = new TSPData() {
     179        Name = name,
     180        Description = description,
     181        Coordinates = Coordinates.CloneAsMatrix(),
     182        Dimension = Coordinates.Rows
     183      };
     184      switch (Rounding) {
     185        case DistanceRounding.None: data.DistanceMeasure = DistanceMeasure.Euclidean; break;
     186        case DistanceRounding.Midpoint: data.DistanceMeasure = DistanceMeasure.RoundedEuclidean; break;
     187        case DistanceRounding.Ceiling: data.DistanceMeasure = DistanceMeasure.UpperEuclidean; break;
     188      }
     189      return data;
    172190    }
    173191  }
     
    183201    private GeoTSPData(GeoTSPData original, Cloner cloner) : base(original, cloner) { }
    184202    public GeoTSPData() : base() { }
    185     public GeoTSPData(double[,] coordinates) : base(coordinates) { }
     203    public GeoTSPData(string name, double[,] coordinates) : base(name, coordinates) { }
     204    public GeoTSPData(string name, DoubleMatrix coordinates) : base(name, coordinates) { }
    186205
    187206    public override IDeepCloneable Clone(Cloner cloner) {
     
    210229      return PI * (Math.Truncate(x) + 5.0 * (x - Math.Truncate(x)) / 3.0) / 180.0;
    211230    }
     231
     232    public override TSPData Export() {
     233      return new TSPData() {
     234        Name = name,
     235        Description = description,
     236        Coordinates = Coordinates.CloneAsMatrix(),
     237        Dimension = Coordinates.Rows,
     238        DistanceMeasure = DistanceMeasure.Geo
     239      };
     240    }
     241  }
     242
     243  internal static class TSPDefaultInstance {
     244    internal static readonly DoubleMatrix Distances = new DoubleMatrix(new double[,] {
     245{ 0, 100, 200, 300, 100, 141, 224, 316, 200, 224, 283, 361, 300, 316, 361, 424 },
     246{ 100, 0, 100, 200, 141, 100, 141, 224, 224, 200, 224, 283, 316, 300, 316, 361 },
     247{ 200, 100, 0, 100, 224, 141, 100, 141, 283, 224, 200, 224, 361, 316, 300, 316 },
     248{ 300, 200, 100, 0, 316, 224, 141, 100, 361, 283, 224, 200, 424, 361, 316, 300 },
     249{ 100, 141, 224, 316, 0, 100, 200, 300, 100, 141, 224, 316, 200, 224, 283, 361 },
     250{ 141, 100, 141, 224, 100, 0, 100, 200, 141, 100, 141, 224, 224, 200, 224, 283 },
     251{ 224, 141, 100, 141, 200, 100, 0, 100, 224, 141, 100, 141, 283, 224, 200, 224 },
     252{ 316, 224, 141, 100, 300, 200, 100, 0, 316, 224, 141, 100, 361, 283, 224, 200 },
     253{ 200, 224, 283, 361, 100, 141, 224, 316, 0, 100, 200, 300, 100, 141, 224, 316 },
     254{ 224, 200, 224, 283, 141, 100, 141, 224, 100, 0, 100, 200, 141, 100, 141, 224 },
     255{ 283, 224, 200, 224, 224, 141, 100, 141, 200, 100, 0, 100, 224, 141, 100, 141 },
     256{ 361, 283, 224, 200, 316, 224, 141, 100, 300, 200, 100, 0, 316, 224, 141, 100 },
     257{ 300, 316, 361, 424, 200, 224, 283, 361, 100, 141, 224, 316, 0, 100, 200, 300 },
     258{ 316, 300, 316, 361, 224, 200, 224, 283, 141, 100, 141, 224, 100, 0, 100, 200 },
     259{ 361, 316, 300, 316, 283, 224, 200, 224, 224, 141, 100, 141, 200, 100, 0, 100 },
     260{ 424, 361, 316, 300, 361, 283, 224, 200, 316, 224, 141, 100, 300, 200, 100, 0 },
     261}, @readonly: true);
     262    internal static readonly DoubleMatrix Coordinates = new DoubleMatrix(new double[,] {
     263{ 100, 100 }, { 100, 200 }, { 100, 300 }, { 100, 400 },
     264{ 200, 100 }, { 200, 200 }, { 200, 300 }, { 200, 400 },
     265{ 300, 100 }, { 300, 200 }, { 300, 300 }, { 300, 400 },
     266{ 400, 100 }, { 400, 200 }, { 400, 300 }, { 400, 400 }
     267}, @readonly: true);
     268    internal static readonly string Name = "HL TSP Default";
    212269  }
    213270}
Note: See TracChangeset for help on using the changeset viewer.