Free cookie consent management tool by TermsFeed Policy Generator

Changeset 17335


Ignore:
Timestamp:
10/17/19 21:40:30 (4 years ago)
Author:
abeham
Message:

#2521: Refactored pTSP to use compositional pattern

Location:
branches/2521_ProblemRefactoring
Files:
5 added
16 edited

Legend:

Unmodified
Added
Removed
  • branches/2521_ProblemRefactoring/HeuristicLab.Problems.PTSP.Views/3.3/HeuristicLab.Problems.PTSP.Views-3.3.csproj

    r17320 r17335  
    172172  </ItemGroup>
    173173  <ItemGroup>
    174     <Compile Include="CoordinatesPTSPDataView.cs">
     174    <Compile Include="ProbabilisticTSPDataView.cs">
    175175      <SubType>UserControl</SubType>
    176176    </Compile>
    177     <Compile Include="CoordinatesPTSPDataView.Designer.cs">
    178       <DependentUpon>CoordinatesPTSPDataView.cs</DependentUpon>
    179     </Compile>
    180     <Compile Include="EuclideanPTSPDataView.cs">
    181       <SubType>UserControl</SubType>
    182     </Compile>
    183     <Compile Include="EuclideanPTSPDataView.Designer.cs">
    184       <DependentUpon>EuclideanPTSPDataView.cs</DependentUpon>
    185     </Compile>
    186     <Compile Include="MatrixPTSPDataView.cs">
    187       <SubType>UserControl</SubType>
    188     </Compile>
    189     <Compile Include="MatrixPTSPDataView.Designer.cs">
    190       <DependentUpon>MatrixPTSPDataView.cs</DependentUpon>
     177    <Compile Include="ProbabilisticTSPDataView.Designer.cs">
     178      <DependentUpon>ProbabilisticTSPDataView.cs</DependentUpon>
    191179    </Compile>
    192180    <Compile Include="ProbabilisticTSPSolutionView.cs">
     
    198186    <Compile Include="Plugin.cs" />
    199187    <Compile Include="Properties\AssemblyInfo.cs" />
     188    <Compile Include="ProbabilisticTSPVisualizer.cs" />
    200189  </ItemGroup>
    201190  <ItemGroup>
  • branches/2521_ProblemRefactoring/HeuristicLab.Problems.PTSP.Views/3.3/ProbabilisticTSPSolutionView.cs

    r17260 r17335  
    2222using System;
    2323using System.Drawing;
     24using HeuristicLab.Core.Views;
    2425using HeuristicLab.Data;
    2526using HeuristicLab.Encodings.PermutationEncoding;
     
    3132  /// The base class for visual representations of a path tour for a PTSP.
    3233  /// </summary>
    33   [View("PathPTSPTour View")]
     34  [View("pTSP Solution View")]
    3435  [Content(typeof(IProbabilisticTSPSolution), true)]
    35   public sealed partial class ProbabilisticTSPSolutionView : TSPSolutionView {
     36  public sealed partial class ProbabilisticTSPSolutionView : ItemView {
     37    public TSPVisualizer Visualizer { get; set; }
     38
    3639    public new IProbabilisticTSPSolution Content {
    3740      get { return (IProbabilisticTSPSolution)base.Content; }
     
    4447    public ProbabilisticTSPSolutionView() {
    4548      InitializeComponent();
    46     }
    47 
    48     protected override void GenerateImage() {
    49       if ((pictureBox.Width > 0) && (pictureBox.Height > 0)) {
    50         if (Content == null) {
    51           pictureBox.Image = null;
    52         } else {
    53           DoubleMatrix coordinates = Content.Coordinates;
    54           Permutation permutation = Content.Tour;
    55           DoubleArray probabilities = Content.Probabilities;
    56           Bitmap bitmap = new Bitmap(pictureBox.Width, pictureBox.Height);
    57 
    58           if ((coordinates != null) && (coordinates.Rows > 0) && (coordinates.Columns == 2) && (probabilities.Length == coordinates.Rows)) {
    59             double xMin = double.MaxValue, yMin = double.MaxValue, xMax = double.MinValue, yMax = double.MinValue;
    60             for (int i = 0; i < coordinates.Rows; i++) {
    61               if (xMin > coordinates[i, 0]) xMin = coordinates[i, 0];
    62               if (yMin > coordinates[i, 1]) yMin = coordinates[i, 1];
    63               if (xMax < coordinates[i, 0]) xMax = coordinates[i, 0];
    64               if (yMax < coordinates[i, 1]) yMax = coordinates[i, 1];
    65             }
    66 
    67             int border = 20;
    68             double xStep = xMax != xMin ? (pictureBox.Width - 2 * border) / (xMax - xMin) : 1;
    69             double yStep = yMax != yMin ? (pictureBox.Height - 2 * border) / (yMax - yMin) : 1;
    70 
    71             Point[] points = new Point[coordinates.Rows];
    72             for (int i = 0; i < coordinates.Rows; i++)
    73               points[i] = new Point(border + ((int)((coordinates[i, 0] - xMin) * xStep)),
    74                                     bitmap.Height - (border + ((int)((coordinates[i, 1] - yMin) * yStep))));
    75 
    76             using (Graphics graphics = Graphics.FromImage(bitmap)) {
    77               if (permutation != null && permutation.Length > 1) {
    78                 Point[] tour = new Point[permutation.Length];
    79                 for (int i = 0; i < permutation.Length; i++) {
    80                   if (permutation[i] >= 0 && permutation[i] < points.Length)
    81                     tour[i] = points[permutation[i]];
    82                 }
    83                 graphics.DrawPolygon(Pens.Black, tour);
    84               }
    85               for (int i = 0; i < points.Length; i++)
    86                 graphics.FillRectangle(Brushes.Red, points[i].X - 2, points[i].Y - 2, Convert.ToInt32(probabilities[i] * 20), Convert.ToInt32(probabilities[i] * 20));
    87             }
    88           } else {
    89             using (Graphics graphics = Graphics.FromImage(bitmap)) {
    90               graphics.Clear(Color.White);
    91               Font font = new Font(FontFamily.GenericSansSerif, 12, FontStyle.Regular);
    92               string text = "No coordinates defined or in wrong format.";
    93               SizeF strSize = graphics.MeasureString(text, font);
    94               graphics.DrawString(text, font, Brushes.Black, (float)(pictureBox.Width - strSize.Width) / 2.0f, (float)(pictureBox.Height - strSize.Height) / 2.0f);
    95             }
    96           }
    97           pictureBox.Image = bitmap;
    98         }
    99       }
     49      Visualizer = new ProbabilisticTSPVisualizer();
    10050    }
    10151  }
  • branches/2521_ProblemRefactoring/HeuristicLab.Problems.PTSP/3.3/AnalyticalPTSP.cs

    r17320 r17335  
    6969      for (var i = 0; i < tour.Length - 1; i++) {
    7070        for (var j = i + 1; j < tour.Length; j++) {
    71           var prod1 = data.GetDistance(tour[i], tour[j]) * data.GetProbability(tour[i]) * data.GetProbability(tour[j]);
     71          var prod1 = data.TSPData.GetDistance(tour[i], tour[j]) * data.GetProbability(tour[i]) * data.GetProbability(tour[j]);
    7272          for (var k = i + 1; k < j; k++) {
    7373            prod1 *= (1 - data.GetProbability(tour[k]));
     
    7979      for (var j = 0; j < tour.Length; j++) {
    8080        for (var i = 0; i < j; i++) {
    81           var prod2 = data.GetDistance(tour[j], tour[i]) * data.GetProbability(tour[i]) * data.GetProbability(tour[j]);
     81          var prod2 = data.TSPData.GetDistance(tour[j], tour[i]) * data.GetProbability(tour[i]) * data.GetProbability(tour[j]);
    8282          for (var k = j + 1; k < tour.Length; k++) {
    8383            prod2 *= (1 - data.GetProbability(tour[k]));
  • branches/2521_ProblemRefactoring/HeuristicLab.Problems.PTSP/3.3/EstimatedPTSP.cs

    r17320 r17335  
    117117      foreach (var r in realizations) {
    118118        int singleRealization = -1, firstNode = -1;
    119         for (var j = 0; j < data.Cities; j++) {
     119        for (var j = 0; j < data.TSPData.Cities; j++) {
    120120          if (r[tour[j]]) {
    121121            if (singleRealization != -1) {
    122               estimatedSum += data.GetDistance(singleRealization, tour[j]);
     122              estimatedSum += data.TSPData.GetDistance(singleRealization, tour[j]);
    123123            } else {
    124124              firstNode = tour[j];
     
    128128        }
    129129        if (singleRealization != -1)
    130           estimatedSum += data.GetDistance(singleRealization, firstNode);
     130          estimatedSum += data.TSPData.GetDistance(singleRealization, firstNode);
    131131        count++;
    132132      }
     
    151151        var pSum = 0.0;
    152152        int singleRealization = -1, firstNode = -1;
    153         for (var j = 0; j < data.Cities; j++) {
     153        for (var j = 0; j < data.TSPData.Cities; j++) {
    154154          if (r[tour[j]]) {
    155155            if (singleRealization != -1) {
    156               pSum += data.GetDistance(singleRealization, tour[j]);
     156              pSum += data.TSPData.GetDistance(singleRealization, tour[j]);
    157157            } else {
    158158              firstNode = tour[j];
     
    162162        }
    163163        if (singleRealization != -1) {
    164           pSum += data.GetDistance(singleRealization, firstNode);
     164          pSum += data.TSPData.GetDistance(singleRealization, firstNode);
    165165        }
    166166        estimatedSum += pSum;
     
    199199      var data = new List<BoolArray>(Realizations);
    200200      var rng = new MersenneTwister((uint)RealizationsSeed);
    201       if (Enumerable.Range(0, ProbabilisticTSPData.Cities).All(c => ProbabilisticTSPData.GetProbability(c) <= 0))
     201      if (Enumerable.Range(0, ProbabilisticTSPData.TSPData.Cities).All(c => ProbabilisticTSPData.GetProbability(c) <= 0))
    202202        throw new InvalidOperationException("All probabilities are zero.");
    203203      while (data.Count < Realizations) {
    204204        var cities = 0;
    205         var r = new bool[ProbabilisticTSPData.Cities];
    206         for (var j = 0; j < ProbabilisticTSPData.Cities; j++) {
     205        var r = new bool[ProbabilisticTSPData.TSPData.Cities];
     206        for (var j = 0; j < ProbabilisticTSPData.TSPData.Cities; j++) {
    207207          if (rng.NextDouble() < ProbabilisticTSPData.GetProbability(j)) {
    208208            r[j] = true;
  • branches/2521_ProblemRefactoring/HeuristicLab.Problems.PTSP/3.3/Moves/OneShift/PTSPEstimatedInsertionMoveEvaluator.cs

    r17253 r17335  
    126126          !(aPosteriori[2] == aPosteriori[4] && aPosteriori[3] == aPosteriori[5])) {
    127127          // compute cost difference between the two a posteriori solutions
    128           moveQuality = moveQuality + data.GetDistance(aPosteriori[6], aPosteriori[7]) + data.GetDistance(aPosteriori[8], aPosteriori[9]) + data.GetDistance(aPosteriori[10], aPosteriori[11]);
    129           moveQuality = moveQuality - data.GetDistance(aPosteriori[0], aPosteriori[1]) - data.GetDistance(aPosteriori[2], aPosteriori[3]) - data.GetDistance(aPosteriori[4], aPosteriori[5]);
     128          moveQuality = moveQuality + data.TSPData.GetDistance(aPosteriori[6], aPosteriori[7]) + data.TSPData.GetDistance(aPosteriori[8], aPosteriori[9]) + data.TSPData.GetDistance(aPosteriori[10], aPosteriori[11]);
     129          moveQuality = moveQuality - data.TSPData.GetDistance(aPosteriori[0], aPosteriori[1]) - data.TSPData.GetDistance(aPosteriori[2], aPosteriori[3]) - data.TSPData.GetDistance(aPosteriori[4], aPosteriori[5]);
    130130        }
    131131        Array.Clear(aPosteriori, 0, aPosteriori.Length);
  • branches/2521_ProblemRefactoring/HeuristicLab.Problems.PTSP/3.3/Moves/TwoOpt/PTSPEstimatedInversionMoveEvaluator.cs

    r17253 r17335  
    8989        // compute cost difference between the two a posteriori solutions
    9090        if (!(aPosteriori[0] == aPosteriori[2] && aPosteriori[1] == aPosteriori[3])) {
    91           moveQuality = moveQuality + data.GetDistance(aPosteriori[0], aPosteriori[2]) + data.GetDistance(aPosteriori[1], aPosteriori[3])
    92             - data.GetDistance(aPosteriori[0], aPosteriori[1]) - data.GetDistance(aPosteriori[2], aPosteriori[3]);
     91          moveQuality = moveQuality + data.TSPData.GetDistance(aPosteriori[0], aPosteriori[2]) + data.TSPData.GetDistance(aPosteriori[1], aPosteriori[3])
     92            - data.TSPData.GetDistance(aPosteriori[0], aPosteriori[1]) - data.TSPData.GetDistance(aPosteriori[2], aPosteriori[3]);
    9393        }
    9494        Array.Clear(aPosteriori, 0, aPosteriori.Length);
  • branches/2521_ProblemRefactoring/HeuristicLab.Problems.PTSP/3.3/ProbabilisticTSP.cs

    r17270 r17335  
    2525using HeuristicLab.Common;
    2626using HeuristicLab.Core;
    27 using HeuristicLab.Data;
    2827using HeuristicLab.Encodings.PermutationEncoding;
    2928using HeuristicLab.Optimization;
     
    7069      Parameters.Add(BestKnownSolutionParameter = new OptionalValueParameter<IProbabilisticTSPSolution>("BestKnownSolution", "The best known solution of this pTSP instance."));
    7170
    72       ProbabilisticTSPData = new MatrixPTSPData();
    73       Encoding.Length = ProbabilisticTSPData.Cities;
     71      ProbabilisticTSPData = new ProbabilisticTSPData();
     72      Encoding.Length = ProbabilisticTSPData.TSPData.Cities;
    7473    }
    7574
    7675    protected override void OnEncodingChanged() {
    7776      base.OnEncodingChanged();
    78       Encoding.Length = ProbabilisticTSPData.Cities;
     77      Encoding.Length = ProbabilisticTSPData.TSPData.Cities;
    7978    }
    8079
     
    117116      Description = data.Description;
    118117
    119       if (data.Dimension <= DistanceMatrixSizeLimit) {
    120         ProbabilisticTSPData = new MatrixPTSPData(data.Name, data.GetDistanceMatrix(), data.Probabilities, data.Coordinates) { Description = data.Description };
    121       } else if (data.DistanceMeasure == DistanceMeasure.Direct && data.Distances != null) {
    122         ProbabilisticTSPData = new MatrixPTSPData(data.Name, data.Distances, data.Probabilities, data.Coordinates) { Description = data.Description };
    123       } else {
    124         switch (data.DistanceMeasure) {
    125           case DistanceMeasure.Att:
    126             ProbabilisticTSPData = new AttPTSPData(data.Name, data.Coordinates, data.Probabilities) { Description = data.Description };
    127             break;
    128           case DistanceMeasure.Euclidean:
    129             ProbabilisticTSPData = new EuclideanPTSPData(data.Name, data.Coordinates, data.Probabilities, EuclideanTSPData.DistanceRounding.None) { Description = data.Description };
    130             break;
    131           case DistanceMeasure.RoundedEuclidean:
    132             ProbabilisticTSPData = new EuclideanPTSPData(data.Name, data.Coordinates, data.Probabilities, EuclideanTSPData.DistanceRounding.Midpoint) { Description = data.Description };
    133             break;
    134           case DistanceMeasure.UpperEuclidean:
    135             ProbabilisticTSPData = new EuclideanPTSPData(data.Name, data.Coordinates, data.Probabilities, EuclideanTSPData.DistanceRounding.Ceiling) { Description = data.Description };
    136             break;
    137           case DistanceMeasure.Geo:
    138             ProbabilisticTSPData = new GeoPTSPData(data.Name, data.Coordinates, data.Probabilities) { Description = data.Description };
    139             break;
    140           case DistanceMeasure.Manhattan:
    141             ProbabilisticTSPData = new ManhattanPTSPData(data.Name, data.Coordinates, data.Probabilities) { Description = data.Description };
    142             break;
    143           case DistanceMeasure.Maximum:
    144             ProbabilisticTSPData = new MaximumPTSPData(data.Name, data.Coordinates, data.Probabilities) { Description = data.Description };
    145             break;
    146           default:
    147             throw new System.IO.InvalidDataException("An unknown distance measure is given in the instance!");
    148         }
    149       }
     118      var tspData = TSP.GetDataFromInstance(data);
     119      ProbabilisticTSPData = new ProbabilisticTSPData(tspData, data.Probabilities);
    150120      BestKnownSolution = null;
    151121      BestKnownQuality = double.NaN;
     
    154124        try {
    155125          var tour = new Permutation(PermutationTypes.RelativeUndirected, data.BestKnownTour);
    156           var tourLength = Evaluate(tour, new MersenneTwister(1));
    157           BestKnownSolution = new ProbabilisticTSPSolution(data.Coordinates != null ? new DoubleMatrix(data.Coordinates) : null, new PercentArray(data.Probabilities), tour, new DoubleValue(tourLength));
     126          var tourLength = Evaluate(tour, new MersenneTwister(1));         
     127          BestKnownSolution = ProbabilisticTSPData.GetSolution(tour, tourLength);
    158128          BestKnownQuality = tourLength;
    159129        } catch (InvalidOperationException) {
  • branches/2521_ProblemRefactoring/HeuristicLab.Problems.PTSP/3.3/ProbabilisticTSPData.cs

    r17260 r17335  
    2121
    2222using System;
     23using System.Linq;
    2324using HEAL.Attic;
    2425using HeuristicLab.Common;
     
    3132namespace HeuristicLab.Problems.PTSP {
    3233  [StorableType("dd2d0ecc-372e-46f1-846f-fb4ca2afa124")]
    33   public interface IProbabilisticTSPData : ITSPData {
     34  public interface IProbabilisticTSPData : INamedItem {
     35    ITSPData TSPData { get; }
     36
    3437    double GetProbability(int city);
    35     new IProbabilisticTSPSolution GetSolution(Permutation tspTour, double tourLength);
    36     new PTSPData Export();
     38    IProbabilisticTSPSolution GetSolution(Permutation tspTour, double tourLength);
     39    PTSPData Export();
    3740  }
    3841
    39   [Item("Matrix-based pTSP Data", "pTSP that is representd by a distance matrix.")]
    40   [StorableType("30ebade1-d28c-4e45-b195-c7fa32a15df5")]
    41   public class MatrixPTSPData : MatrixTSPData, IProbabilisticTSPData {
     42  [Item("Probabilistic TSP Data", "An extension to the TSP where customers have to be served with a certain probability only.")]
     43  [StorableType("b79f0ad6-b7f7-49c5-9a62-8089db6af1aa")]
     44  public class ProbabilisticTSPData : NamedItem, IProbabilisticTSPData {
     45    [Storable] public ITSPData TSPData { get; protected set; }
    4246    [Storable] public PercentArray Probabilities { get; protected set; }
    4347
    4448    [StorableConstructor]
    45     protected MatrixPTSPData(StorableConstructorFlag _) : base(_) { }
    46     protected MatrixPTSPData(MatrixPTSPData original, Cloner cloner) : base(original, cloner) {
     49    protected ProbabilisticTSPData(StorableConstructorFlag _) : base(_) { }
     50    protected ProbabilisticTSPData(ProbabilisticTSPData original, Cloner cloner) : base(original, cloner) {
     51      TSPData = original.TSPData;
    4752      Probabilities = original.Probabilities;
    4853    }
    49     public MatrixPTSPData() {
    50       Name = PTSPDefaultInstance.Name;
    51       Matrix = PTSPDefaultInstance.Distances;
    52       Probabilities = PTSPDefaultInstance.Probabilities;
    53       DisplayCoordinates = PTSPDefaultInstance.Coordinates;
     54    public ProbabilisticTSPData() {
     55      TSPData = new EuclideanTSPData();
     56      Name = TSPData.Name;
     57      Probabilities = new PercentArray(Enumerable.Repeat(0.5, TSPData.Cities).ToArray(), @readonly: true);
    5458    }
    55     public MatrixPTSPData(string name, double[,] matrix, double[] probabilities, double[,] coordinates = null)
    56       : base(name, matrix, coordinates) {
     59    public ProbabilisticTSPData(ITSPData tspData, double[] probabilities)
     60      : base(tspData.Name, tspData.Description) {
     61      if (tspData.Cities != probabilities.Length) throw new ArgumentException("Unequal number of cities and probabilities.");
     62      TSPData = tspData;
    5763      Probabilities = new PercentArray(probabilities, @readonly: true);
    5864    }
    59     public MatrixPTSPData(string name, DoubleMatrix matrix, PercentArray probabilities, DoubleMatrix coordinates = null)
    60       : base(name, matrix, coordinates) {
     65    public ProbabilisticTSPData(ITSPData tspData, PercentArray probabilities)
     66      : base(tspData.Name, tspData.Description) {
     67      if (tspData.Cities != probabilities.Length) throw new ArgumentException("Unequal number of cities and probabilities.");
     68      TSPData = tspData;
    6169      Probabilities = probabilities.AsReadOnly();
    6270    }
    6371
    6472    public override IDeepCloneable Clone(Cloner cloner) {
    65       return new MatrixPTSPData(this, cloner);
     73      return new ProbabilisticTSPData(this, cloner);
    6674    }
    6775
    6876    public double GetProbability(int city) => Probabilities[city];
    6977
    70     public new IProbabilisticTSPSolution GetSolution(Permutation tspTour, double tourLength) {
    71       return new ProbabilisticTSPSolution(DisplayCoordinates, Probabilities, tspTour, new DoubleValue(tourLength));
     78    public IProbabilisticTSPSolution GetSolution(Permutation tspTour, double tourLength) {
     79      var tspSolution = TSPData.GetSolution(tspTour, tourLength);
     80      return new ProbabilisticTSPSolution(tspSolution, Probabilities);
    7281    }
    7382
    74     public new PTSPData Export() {
     83    public PTSPData Export() {
     84      var tspExport = TSPData.Export();
    7585      return new PTSPData() {
    76         Name = name,
    77         Description = description,
    78         Coordinates = DisplayCoordinates?.CloneAsMatrix(),
    79         Dimension = Matrix.Rows,
    80         DistanceMeasure = DistanceMeasure.Direct,
    81         Distances = Matrix.CloneAsMatrix(),
     86        Name = tspExport.Name,
     87        Description = tspExport.Description,
     88        Coordinates = tspExport.Coordinates,
     89        Dimension = tspExport.Dimension,
     90        DistanceMeasure = tspExport.DistanceMeasure,
     91        Distances = tspExport.Distances,
    8292        Probabilities = Probabilities.CloneAsArray()
    8393      };
    8494    }
    8595  }
    86 
    87   [Item("Euclidean pTSP Data", "pTSP that is represented by coordinates in an Euclidean plane.")]
    88   [StorableType("8d4cf257-9013-4746-bc6c-37615954c3fb")]
    89   public class EuclideanPTSPData : EuclideanTSPData, IProbabilisticTSPData {
    90     [Storable] public PercentArray Probabilities { get; protected set; }
    91 
    92     [StorableConstructor]
    93     protected EuclideanPTSPData(StorableConstructorFlag _) : base(_) { }
    94     protected EuclideanPTSPData(EuclideanPTSPData original, Cloner cloner) : base(original, cloner) {
    95       Probabilities = original.Probabilities;
    96     }
    97     public EuclideanPTSPData() : base() {
    98       Name = PTSPDefaultInstance.Name;
    99       Coordinates = PTSPDefaultInstance.Coordinates;
    100       Probabilities = PTSPDefaultInstance.Probabilities;
    101       Rounding = DistanceRounding.Midpoint;
    102     }
    103     public EuclideanPTSPData(string name, double[,] coordinates, double[] probabilities, DistanceRounding rounding = DistanceRounding.None)
    104       : base(name, coordinates) {
    105       if (coordinates.GetLength(0) != probabilities.Length) throw new InvalidOperationException("Number of cities is ambiguous between " + nameof(coordinates) + " and " + nameof(probabilities) + ".");
    106       Probabilities = new PercentArray(probabilities, @readonly: true);
    107     }
    108     public EuclideanPTSPData(string name, DoubleMatrix coordinates, PercentArray probabilities, DistanceRounding rounding = DistanceRounding.None)
    109       : base(name, coordinates, rounding) {
    110       if (coordinates.Rows != probabilities.Length) throw new InvalidOperationException("Number of cities is ambiguous between " + nameof(coordinates) + " and " + nameof(probabilities) + ".");
    111       Probabilities = probabilities.AsReadOnly();
    112     }
    113 
    114     public override IDeepCloneable Clone(Cloner cloner) {
    115       return new EuclideanPTSPData(this, cloner);
    116     }
    117 
    118     public double GetProbability(int city) => Probabilities[city];
    119 
    120     public new IProbabilisticTSPSolution GetSolution(Permutation tspTour, double tourLength) {
    121       return new ProbabilisticTSPSolution(Coordinates, Probabilities, tspTour, new DoubleValue(tourLength));
    122     }
    123 
    124     public new PTSPData Export() {
    125       var data = new PTSPData() {
    126         Name = name,
    127         Description = description,
    128         Coordinates = Coordinates.CloneAsMatrix(),
    129         Probabilities = Probabilities.CloneAsArray(),
    130         Dimension = Coordinates.Rows,
    131       };
    132       switch (Rounding) {
    133         case DistanceRounding.None: data.DistanceMeasure = DistanceMeasure.Euclidean; break;
    134         case DistanceRounding.Midpoint: data.DistanceMeasure = DistanceMeasure.RoundedEuclidean; break;
    135         case DistanceRounding.Ceiling: data.DistanceMeasure = DistanceMeasure.UpperEuclidean; break;
    136       }
    137       return data;
    138     }
    139   }
    140 
    141   [Item("Coordinates pTSP Data", "pTSP that is represented by a distance between coordinates.")]
    142   [StorableType("db0ff368-23cf-4a28-bd82-5979c6a93ee5")]
    143   public abstract class CoordinatesPTSPData : CoordinatesTSPData, IProbabilisticTSPData {
    144     [Storable] public PercentArray Probabilities { get; protected set; }
    145 
    146     [StorableConstructor]
    147     protected CoordinatesPTSPData(StorableConstructorFlag _) : base(_) { }
    148     protected CoordinatesPTSPData(CoordinatesPTSPData original, Cloner cloner)
    149       : base(original, cloner) {
    150       Probabilities = original.Probabilities;
    151     }
    152     protected CoordinatesPTSPData() : base() {
    153       Name = PTSPDefaultInstance.Name;
    154       Coordinates = PTSPDefaultInstance.Coordinates;
    155       Probabilities = PTSPDefaultInstance.Probabilities;
    156     }
    157     protected CoordinatesPTSPData(string name, double[,] coordinates, double[] probabilities)
    158       : base(name, coordinates) {
    159       if (coordinates.GetLength(0) != probabilities.Length) throw new InvalidOperationException("Number of cities is ambiguous between " + nameof(coordinates) + " and " + nameof(probabilities) + ".");
    160       Probabilities = new PercentArray(probabilities, @readonly: true);
    161     }
    162     protected CoordinatesPTSPData(string name, DoubleMatrix coordinates, PercentArray probabilities)
    163       : base(name, coordinates) {
    164       if (coordinates.Rows != probabilities.Length) throw new InvalidOperationException("Number of cities is ambiguous between " + nameof(coordinates) + " and " + nameof(probabilities) + ".");
    165       Probabilities = probabilities.AsReadOnly();
    166     }
    167 
    168     public double GetProbability(int city) => Probabilities[city];
    169 
    170     public new IProbabilisticTSPSolution GetSolution(Permutation tspTour, double tourLength) {
    171       return new ProbabilisticTSPSolution(Coordinates, Probabilities, tspTour, new DoubleValue(tourLength));
    172     }
    173 
    174     PTSPData IProbabilisticTSPData.Export() {
    175       return (PTSPData)Export();
    176     }
    177   }
    178 
    179   [Item("Geo pTSP Data", "pTSP that is represented by geo coordinates.")]
    180   [StorableType("b175e0be-5706-4c44-b3f0-dcb948d5c47a")]
    181   public class GeoPTSPData : CoordinatesPTSPData {
    182 
    183     [StorableConstructor]
    184     protected GeoPTSPData(StorableConstructorFlag _) : base(_) { }
    185     protected GeoPTSPData(GeoPTSPData original, Cloner cloner) : base(original, cloner) { }
    186     public GeoPTSPData() : base() { }
    187     public GeoPTSPData(string name, double[,] coordinates, double[] probabilities) : base(name, coordinates, probabilities) { }
    188     public GeoPTSPData(string name, DoubleMatrix coordinates, PercentArray probabilities) : base(name, coordinates, probabilities) { }
    189 
    190     public override IDeepCloneable Clone(Cloner cloner) {
    191       return new GeoPTSPData(this, cloner);
    192     }
    193 
    194     public override double GetDistance(double fromX, double fromY, double toX, double toY) {
    195       return DistanceHelper.GeoDistance(fromX, fromY, toX, toY);
    196     }
    197 
    198     public override TSPData Export() {
    199       return new PTSPData() {
    200         Name = name,
    201         Description = description,
    202         Coordinates = Coordinates.CloneAsMatrix(),
    203         Probabilities = Probabilities.CloneAsArray(),
    204         Dimension = Coordinates.Rows,
    205         DistanceMeasure = DistanceMeasure.Geo,
    206       };
    207     }
    208   }
    209 
    210   [Item("ATT pTSP Data", "pTSP that is represented by ATT distance.")]
    211   [StorableType("7a2aa605-58d2-4533-a763-3d474e185460")]
    212   public class AttPTSPData : CoordinatesPTSPData {
    213 
    214     [StorableConstructor]
    215     protected AttPTSPData(StorableConstructorFlag _) : base(_) { }
    216     protected AttPTSPData(AttPTSPData original, Cloner cloner) : base(original, cloner) { }
    217     public AttPTSPData() : base() { }
    218     public AttPTSPData(string name, double[,] coordinates, double[] probabilities) : base(name, coordinates, probabilities) { }
    219     public AttPTSPData(string name, DoubleMatrix coordinates, PercentArray probabilities) : base(name, coordinates, probabilities) { }
    220 
    221     public override IDeepCloneable Clone(Cloner cloner) {
    222       return new AttPTSPData(this, cloner);
    223     }
    224 
    225     public override double GetDistance(double fromX, double fromY, double toX, double toY) {
    226       return DistanceHelper.AttDistance(fromX, fromY, toX, toY);
    227     }
    228 
    229     public override TSPData Export() {
    230       return new PTSPData() {
    231         Name = name,
    232         Description = description,
    233         Coordinates = Coordinates.CloneAsMatrix(),
    234         Probabilities = Probabilities.CloneAsArray(),
    235         Dimension = Coordinates.Rows,
    236         DistanceMeasure = DistanceMeasure.Att,
    237       };
    238     }
    239   }
    240 
    241   [Item("Manhattan pTSP Data", "pTSP that is represented by Manhattan distance.")]
    242   [StorableType("cc43d1db-3da9-4d6e-becb-6b475b42fc59")]
    243   public class ManhattanPTSPData : CoordinatesPTSPData {
    244 
    245     [StorableConstructor]
    246     protected ManhattanPTSPData(StorableConstructorFlag _) : base(_) { }
    247     protected ManhattanPTSPData(ManhattanPTSPData original, Cloner cloner) : base(original, cloner) { }
    248     public ManhattanPTSPData() : base() { }
    249     public ManhattanPTSPData(string name, double[,] coordinates, double[] probabilities) : base(name, coordinates, probabilities) { }
    250     public ManhattanPTSPData(string name, DoubleMatrix coordinates, PercentArray probabilities) : base(name, coordinates, probabilities) { }
    251 
    252     public override IDeepCloneable Clone(Cloner cloner) {
    253       return new ManhattanPTSPData(this, cloner);
    254     }
    255 
    256     public override double GetDistance(double fromX, double fromY, double toX, double toY) {
    257       return DistanceHelper.ManhattanDistance(fromX, fromY, toX, toY);
    258     }
    259 
    260     public override TSPData Export() {
    261       return new PTSPData() {
    262         Name = name,
    263         Description = description,
    264         Coordinates = Coordinates.CloneAsMatrix(),
    265         Probabilities = Probabilities.CloneAsArray(),
    266         Dimension = Coordinates.Rows,
    267         DistanceMeasure = DistanceMeasure.Manhattan,
    268       };
    269     }
    270   }
    271 
    272   [Item("Maximum pTSP Data", "pTSP that is represented by maximum absolute distance in either the x or y coordinates.")]
    273   [StorableType("82e9cde2-a942-403a-80ff-8deae4fa8214")]
    274   public class MaximumPTSPData : CoordinatesPTSPData {
    275 
    276     [StorableConstructor]
    277     protected MaximumPTSPData(StorableConstructorFlag _) : base(_) { }
    278     protected MaximumPTSPData(MaximumPTSPData original, Cloner cloner) : base(original, cloner) { }
    279     public MaximumPTSPData() : base() { }
    280     public MaximumPTSPData(string name, double[,] coordinates, double[] probabilities) : base(name, coordinates, probabilities) { }
    281     public MaximumPTSPData(string name, DoubleMatrix coordinates, PercentArray probabilities) : base(name, coordinates, probabilities) { }
    282 
    283     public override IDeepCloneable Clone(Cloner cloner) {
    284       return new MaximumPTSPData(this, cloner);
    285     }
    286 
    287     public override double GetDistance(double fromX, double fromY, double toX, double toY) {
    288       return DistanceHelper.MaximumDistance(fromX, fromY, toX, toY);
    289     }
    290 
    291     public override TSPData Export() {
    292       return new PTSPData() {
    293         Name = name,
    294         Description = description,
    295         Coordinates = Coordinates.CloneAsMatrix(),
    296         Probabilities = Probabilities.CloneAsArray(),
    297         Dimension = Coordinates.Rows,
    298         DistanceMeasure = DistanceMeasure.Maximum,
    299       };
    300     }
    301   }
    302 
    303   internal static class PTSPDefaultInstance {
    304     internal static readonly DoubleMatrix Distances = new DoubleMatrix(new double[,] {
    305 { 0, 100, 200, 300, 100, 141, 224, 316, 200, 224, 283, 361, 300, 316, 361, 424 },
    306 { 100, 0, 100, 200, 141, 100, 141, 224, 224, 200, 224, 283, 316, 300, 316, 361 },
    307 { 200, 100, 0, 100, 224, 141, 100, 141, 283, 224, 200, 224, 361, 316, 300, 316 },
    308 { 300, 200, 100, 0, 316, 224, 141, 100, 361, 283, 224, 200, 424, 361, 316, 300 },
    309 { 100, 141, 224, 316, 0, 100, 200, 300, 100, 141, 224, 316, 200, 224, 283, 361 },
    310 { 141, 100, 141, 224, 100, 0, 100, 200, 141, 100, 141, 224, 224, 200, 224, 283 },
    311 { 224, 141, 100, 141, 200, 100, 0, 100, 224, 141, 100, 141, 283, 224, 200, 224 },
    312 { 316, 224, 141, 100, 300, 200, 100, 0, 316, 224, 141, 100, 361, 283, 224, 200 },
    313 { 200, 224, 283, 361, 100, 141, 224, 316, 0, 100, 200, 300, 100, 141, 224, 316 },
    314 { 224, 200, 224, 283, 141, 100, 141, 224, 100, 0, 100, 200, 141, 100, 141, 224 },
    315 { 283, 224, 200, 224, 224, 141, 100, 141, 200, 100, 0, 100, 224, 141, 100, 141 },
    316 { 361, 283, 224, 200, 316, 224, 141, 100, 300, 200, 100, 0, 316, 224, 141, 100 },
    317 { 300, 316, 361, 424, 200, 224, 283, 361, 100, 141, 224, 316, 0, 100, 200, 300 },
    318 { 316, 300, 316, 361, 224, 200, 224, 283, 141, 100, 141, 224, 100, 0, 100, 200 },
    319 { 361, 316, 300, 316, 283, 224, 200, 224, 224, 141, 100, 141, 200, 100, 0, 100 },
    320 { 424, 361, 316, 300, 361, 283, 224, 200, 316, 224, 141, 100, 300, 200, 100, 0 },
    321 }, @readonly: true);
    322     internal static readonly DoubleMatrix Coordinates = new DoubleMatrix(new double[,] {
    323 { 100, 100 }, { 100, 200 }, { 100, 300 }, { 100, 400 },
    324 { 200, 100 }, { 200, 200 }, { 200, 300 }, { 200, 400 },
    325 { 300, 100 }, { 300, 200 }, { 300, 300 }, { 300, 400 },
    326 { 400, 100 }, { 400, 200 }, { 400, 300 }, { 400, 400 }
    327 }, @readonly: true);
    328     internal static readonly PercentArray Probabilities = new PercentArray(new double[] {
    329 0.2, 0.3, 0.4, 0.5, 0.6, 0.7, 0.8, 0.7, 0.6, 0.5, 0.4, 0.3, 0.2, 0.3, 0.4, 0.5
    330 }, @readonly: true);
    331     internal static readonly string Name = "HL PTSP Default";
    332   }
    33396}
  • branches/2521_ProblemRefactoring/HeuristicLab.Problems.PTSP/3.3/ProbabilisticTSPSolution.cs

    r17260 r17335  
    2020#endregion
    2121
     22using System.ComponentModel;
    2223using System.Drawing;
    2324using HEAL.Attic;
     
    2526using HeuristicLab.Core;
    2627using HeuristicLab.Data;
    27 using HeuristicLab.Encodings.PermutationEncoding;
    2828using HeuristicLab.Problems.TravelingSalesman;
    2929
    3030namespace HeuristicLab.Problems.PTSP {
    3131  [StorableType("596f52b5-b2c8-45a0-a7bd-e5b9c787c960")]
    32   public interface IProbabilisticTSPSolution : ITSPSolution {
     32  public interface IProbabilisticTSPSolution : IItem, INotifyPropertyChanged {
     33    ITSPSolution TSPSolution { get; }
    3334    DoubleArray Probabilities { get; }
    3435  }
     
    3940  [Item("pTSP Solution", "Represents a tour of a Probabilistic Traveling Salesman Problem given in path representation which can be visualized in the GUI.")]
    4041  [StorableType("ea784622-41e5-493e-a1f3-4c38fed99216")]
    41   public sealed class ProbabilisticTSPSolution : TSPSolution, IProbabilisticTSPSolution {
     42  public sealed class ProbabilisticTSPSolution : Item, IProbabilisticTSPSolution {
    4243    public static new Image StaticItemImage {
    4344      get { return HeuristicLab.Common.Resources.VSImageLibrary.Image; }
     45    }
     46
     47    [Storable]
     48    private ITSPSolution tspSolution;
     49    public ITSPSolution TSPSolution {
     50      get { return tspSolution; }
     51      set {
     52        if (tspSolution == value) return;
     53        tspSolution = value;
     54        OnPropertyChanged(nameof(TSPSolution));
     55      }
    4456    }
    4557
     
    5971    private ProbabilisticTSPSolution(ProbabilisticTSPSolution original, Cloner cloner)
    6072      : base(original, cloner) {
     73      this.tspSolution = cloner.Clone(original.tspSolution);
    6174      this.probabilities = cloner.Clone(original.probabilities);
    6275    }
    6376    public ProbabilisticTSPSolution() : base() { }
    64     public ProbabilisticTSPSolution(DoubleMatrix coordinates, PercentArray probabilities)
    65       : base(coordinates) {
    66       this.probabilities = probabilities;
    67     }
    68     public ProbabilisticTSPSolution(DoubleMatrix coordinates, PercentArray probabilities, Permutation permutation)
    69       : base(coordinates, permutation) {
    70       this.probabilities = probabilities;
    71     }
    72     public ProbabilisticTSPSolution(DoubleMatrix coordinates, PercentArray probabilities, Permutation permutation, DoubleValue quality)
    73       : base(coordinates, permutation, quality) {
     77    public ProbabilisticTSPSolution(ITSPSolution tspSolution, PercentArray probabilities)
     78      : base() {
     79      this.tspSolution = tspSolution;
    7480      this.probabilities = probabilities;
    7581    }
     
    7884      return new ProbabilisticTSPSolution(this, cloner);
    7985    }
     86
     87    public event PropertyChangedEventHandler PropertyChanged;
     88    private void OnPropertyChanged(string property) {
     89      PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(property));
     90    }
    8091  }
    8192}
  • branches/2521_ProblemRefactoring/HeuristicLab.Problems.TravelingSalesman.Views/3.3/CoordinatesTSPDataView.cs

    r17260 r17335  
    2020#endregion
    2121
    22 using System.Drawing;
    2322using System.Windows.Forms;
    2423using HeuristicLab.Core.Views;
    25 using HeuristicLab.Data;
    2624using HeuristicLab.MainForm;
    2725using HeuristicLab.MainForm.WindowsForms;
     
    3028  [View("Coordinates TSP Data View")]
    3129  [Content(typeof(CoordinatesTSPData), IsDefaultView = true)]
    32   public partial class CoordinatesTSPDataView : NamedItemView {
     30  public partial class CoordinatesTSPDataView : NamedItemView, ITSPVisualizerView {
     31   
     32    private TSPVisualizer visualizer;
     33    public TSPVisualizer Visualizer {
     34      get => visualizer;
     35      set {
     36        if (visualizer == value) return;
     37        visualizer = value;
     38        if (Content != null) {
     39          visualizer.Coordinates = Content.Coordinates;
     40        }
     41        GenerateImage();
     42      }
     43    }
    3344
    3445    public new CoordinatesTSPData Content {
     
    3950    public CoordinatesTSPDataView() {
    4051      InitializeComponent();
     52      visualizer = new TSPVisualizer();
    4153    }
    4254
     
    4658        coordinatesMatrixView.Content = null;
    4759        coordinatesPictureBox.Image = null;
     60        Visualizer.Coordinates = null;
    4861      } else {
    4962        coordinatesMatrixView.Content = Content.Coordinates;
     63        Visualizer.Coordinates = Content.Coordinates;
    5064        GenerateImage();
    5165      }
     
    5872
    5973    protected virtual void GenerateImage() {
    60       if (coordinatesPictureBox.Width > 0 && coordinatesPictureBox.Height > 0) {
    61         DoubleMatrix coordinates = Content.Coordinates;
    62         var xAxis = Content is GeoTSPData ? 1 : 0;
    63         var yAxis = 1 - xAxis;
    64         var bitmap = new Bitmap(coordinatesPictureBox.Width, coordinatesPictureBox.Height);
    65 
    66         if (coordinates.Rows > 0 && coordinates.Columns == 2) {
    67           double xMin = double.MaxValue, yMin = double.MaxValue, xMax = double.MinValue, yMax = double.MinValue;
    68           for (int i = 0; i < coordinates.Rows; i++) {
    69             if (xMin > coordinates[i, xAxis]) xMin = coordinates[i, xAxis];
    70             if (yMin > coordinates[i, yAxis]) yMin = coordinates[i, yAxis];
    71             if (xMax < coordinates[i, xAxis]) xMax = coordinates[i, xAxis];
    72             if (yMax < coordinates[i, yAxis]) yMax = coordinates[i, yAxis];
    73           }
    74 
    75           int border = 20;
    76           double xStep = xMax != xMin ? (coordinatesPictureBox.Width - 2 * border) / (xMax - xMin) : 1;
    77           double yStep = yMax != yMin ? (coordinatesPictureBox.Height - 2 * border) / (yMax - yMin) : 1;
    78 
    79           Point[] points = new Point[coordinates.Rows];
    80           for (int i = 0; i < coordinates.Rows; i++)
    81             points[i] = new Point(border + ((int)((coordinates[i, xAxis] - xMin) * xStep)),
    82                                   bitmap.Height - (border + ((int)((coordinates[i, yAxis] - yMin) * yStep))));
    83 
    84           using (Graphics graphics = Graphics.FromImage(bitmap)) {
    85             for (int i = 0; i < points.Length; i++)
    86               graphics.FillRectangle(Brushes.Red, points[i].X - 2, points[i].Y - 2, 6, 6);
    87           }
    88         } else {
    89           using (Graphics graphics = Graphics.FromImage(bitmap)) {
    90             graphics.Clear(Color.White);
    91             Font font = new Font(FontFamily.GenericSansSerif, 12, FontStyle.Regular);
    92             string text = "No coordinates defined or in wrong format.";
    93             SizeF strSize = graphics.MeasureString(text, font);
    94             graphics.DrawString(text, font, Brushes.Black, (float)(coordinatesPictureBox.Width - strSize.Width) / 2.0f, (float)(coordinatesPictureBox.Height - strSize.Height) / 2.0f);
    95           }
    96         }
    97         coordinatesPictureBox.Image = bitmap;
    98       }
     74      coordinatesPictureBox.Image = Visualizer.Draw(coordinatesPictureBox.Width, coordinatesPictureBox.Height);
    9975    }
    10076  }
  • branches/2521_ProblemRefactoring/HeuristicLab.Problems.TravelingSalesman.Views/3.3/HeuristicLab.Problems.TravelingSalesman.Views-3.3.csproj

    r17251 r17335  
    135135      <DependentUpon>EuclideanTSPDataView.cs</DependentUpon>
    136136    </Compile>
     137    <Compile Include="ITSPDataView.cs" />
    137138    <Compile Include="MatrixTSPDataView.cs">
    138139      <SubType>UserControl</SubType>
     
    149150    <Compile Include="Plugin.cs" />
    150151    <Compile Include="Properties\AssemblyInfo.cs" />
     152    <Compile Include="TSPVisualizer.cs" />
    151153  </ItemGroup>
    152154  <ItemGroup>
  • branches/2521_ProblemRefactoring/HeuristicLab.Problems.TravelingSalesman.Views/3.3/MatrixTSPDataView.cs

    r17260 r17335  
    2020#endregion
    2121
    22 using System.Drawing;
    2322using System.Windows.Forms;
    2423using HeuristicLab.Core.Views;
    25 using HeuristicLab.Data;
    2624using HeuristicLab.MainForm;
    2725using HeuristicLab.MainForm.WindowsForms;
     
    3028  [View("Matrix TSP Data View")]
    3129  [Content(typeof(MatrixTSPData), IsDefaultView = true)]
    32   public partial class MatrixTSPDataView : NamedItemView {
     30  public partial class MatrixTSPDataView : NamedItemView, ITSPVisualizerView {
     31
     32    private TSPVisualizer visualizer;
     33    public TSPVisualizer Visualizer {
     34      get => visualizer;
     35      set {
     36        if (visualizer == value) return;
     37        visualizer = value;
     38        if (Content != null) {
     39          visualizer.Coordinates = Content.DisplayCoordinates;
     40        }
     41        GenerateImage();
     42      }
     43    }
    3344
    3445    public new MatrixTSPData Content {
     
    3950    public MatrixTSPDataView() {
    4051      InitializeComponent();
     52      visualizer = new TSPVisualizer();
    4153    }
    4254
     
    4759        coordinatesMatrixView.Content = null;
    4860        coordinatesPictureBox.Image = null;
     61        Visualizer.Coordinates = null;
    4962      } else {
    5063        distanceMatrixView.Content = Content.Matrix;
    5164        coordinatesMatrixView.Content = Content.DisplayCoordinates;
     65        Visualizer.Coordinates = Content.DisplayCoordinates;
    5266        GenerateImage();
    5367      }
     
    6175
    6276    protected virtual void GenerateImage() {
    63       if (coordinatesPictureBox.Width > 0 && coordinatesPictureBox.Height > 0) {
    64         DoubleMatrix coordinates = Content?.DisplayCoordinates;
    65         var bitmap = new Bitmap(coordinatesPictureBox.Width, coordinatesPictureBox.Height);
    66 
    67         if ((coordinates != null) && (coordinates.Rows > 0) && (coordinates.Columns == 2)) {
    68           double xMin = double.MaxValue, yMin = double.MaxValue, xMax = double.MinValue, yMax = double.MinValue;
    69           for (int i = 0; i < coordinates.Rows; i++) {
    70             if (xMin > coordinates[i, 0]) xMin = coordinates[i, 0];
    71             if (yMin > coordinates[i, 1]) yMin = coordinates[i, 1];
    72             if (xMax < coordinates[i, 0]) xMax = coordinates[i, 0];
    73             if (yMax < coordinates[i, 1]) yMax = coordinates[i, 1];
    74           }
    75 
    76           int border = 20;
    77           double xStep = xMax != xMin ? (coordinatesPictureBox.Width - 2 * border) / (xMax - xMin) : 1;
    78           double yStep = yMax != yMin ? (coordinatesPictureBox.Height - 2 * border) / (yMax - yMin) : 1;
    79 
    80           Point[] points = new Point[coordinates.Rows];
    81           for (int i = 0; i < coordinates.Rows; i++)
    82             points[i] = new Point(border + ((int)((coordinates[i, 0] - xMin) * xStep)),
    83                                   bitmap.Height - (border + ((int)((coordinates[i, 1] - yMin) * yStep))));
    84 
    85           using (Graphics graphics = Graphics.FromImage(bitmap)) {
    86             for (int i = 0; i < points.Length; i++)
    87               graphics.FillRectangle(Brushes.Red, points[i].X - 2, points[i].Y - 2, 6, 6);
    88           }
    89         } else {
    90           using (Graphics graphics = Graphics.FromImage(bitmap)) {
    91             graphics.Clear(Color.White);
    92             Font font = new Font(FontFamily.GenericSansSerif, 12, FontStyle.Regular);
    93             string text = "No coordinates defined or in wrong format.";
    94             SizeF strSize = graphics.MeasureString(text, font);
    95             graphics.DrawString(text, font, Brushes.Black, (float)(coordinatesPictureBox.Width - strSize.Width) / 2.0f, (float)(coordinatesPictureBox.Height - strSize.Height) / 2.0f);
    96           }
    97         }
    98         coordinatesPictureBox.Image = bitmap;
    99       }
     77      coordinatesPictureBox.Image = Visualizer.Draw(coordinatesPictureBox.Width, coordinatesPictureBox.Height);
    10078    }
    10179  }
  • branches/2521_ProblemRefactoring/HeuristicLab.Problems.TravelingSalesman.Views/3.3/TSPSolutionView.cs

    r17260 r17335  
    2222using System;
    2323using System.ComponentModel;
    24 using System.Drawing;
    2524using System.Windows.Forms;
    2625using HeuristicLab.Core.Views;
    27 using HeuristicLab.Data;
    28 using HeuristicLab.Encodings.PermutationEncoding;
    2926using HeuristicLab.MainForm;
    3027
     
    3532  [View("TSP Solution View")]
    3633  [Content(typeof(ITSPSolution), true)]
    37   public partial class TSPSolutionView : ItemView {
     34  public partial class TSPSolutionView : ItemView, ITSPVisualizerView {
     35    public TSPVisualizer Visualizer { get; set; }
     36
    3837    public new ITSPSolution Content {
    3938      get { return (ITSPSolution)base.Content; }
     
    4645    public TSPSolutionView() {
    4746      InitializeComponent();
     47      Visualizer = new TSPVisualizer();
    4848    }
    4949
     
    6363        pictureBox.Image = null;
    6464        tourViewHost.Content = null;
     65        Visualizer.Coordinates = null;
     66        Visualizer.Tour = null;
    6567      } else {
    6668        qualityViewHost.Content = Content.TourLength;
     69        if (Content.TSPData is CoordinatesTSPData coordTsp)
     70          Visualizer.Coordinates = coordTsp.Coordinates;
     71        else if (Content.TSPData is MatrixTSPData matrixTsp)
     72          Visualizer.Coordinates = matrixTsp.DisplayCoordinates;
     73        Visualizer.Tour = Content.Tour;
    6774        GenerateImage();
    6875        tourViewHost.Content = Content.Tour;
     
    8289          pictureBox.Image = null;
    8390        } else {
    84           DoubleMatrix coordinates = Content.Coordinates;
    85           Permutation permutation = Content.Tour;
    86           Bitmap bitmap = new Bitmap(pictureBox.Width, pictureBox.Height);
    87 
    88           if ((coordinates != null) && (coordinates.Rows > 0) && (coordinates.Columns == 2)) {
    89             double xMin = double.MaxValue, yMin = double.MaxValue, xMax = double.MinValue, yMax = double.MinValue;
    90             for (int i = 0; i < coordinates.Rows; i++) {
    91               if (xMin > coordinates[i, 0]) xMin = coordinates[i, 0];
    92               if (yMin > coordinates[i, 1]) yMin = coordinates[i, 1];
    93               if (xMax < coordinates[i, 0]) xMax = coordinates[i, 0];
    94               if (yMax < coordinates[i, 1]) yMax = coordinates[i, 1];
    95             }
    96 
    97             int border = 20;
    98             double xStep = xMax != xMin ? (pictureBox.Width - 2 * border) / (xMax - xMin) : 1;
    99             double yStep = yMax != yMin ? (pictureBox.Height - 2 * border) / (yMax - yMin) : 1;
    100 
    101             Point[] points = new Point[coordinates.Rows];
    102             for (int i = 0; i < coordinates.Rows; i++)
    103               points[i] = new Point(border + ((int)((coordinates[i, 0] - xMin) * xStep)),
    104                                     bitmap.Height - (border + ((int)((coordinates[i, 1] - yMin) * yStep))));
    105 
    106             using (Graphics graphics = Graphics.FromImage(bitmap)) {
    107               if (permutation != null && permutation.Length > 1) {
    108                 Point[] tour = new Point[permutation.Length];
    109                 for (int i = 0; i < permutation.Length; i++) {
    110                   if (permutation[i] >= 0 && permutation[i] < points.Length)
    111                     tour[i] = points[permutation[i]];
    112                 }
    113                 graphics.DrawPolygon(Pens.Black, tour);
    114               }
    115               for (int i = 0; i < points.Length; i++)
    116                 graphics.FillRectangle(Brushes.Red, points[i].X - 2, points[i].Y - 2, 6, 6);
    117             }
    118           } else {
    119             using (Graphics graphics = Graphics.FromImage(bitmap)) {
    120               graphics.Clear(Color.White);
    121               Font font = new Font(FontFamily.GenericSansSerif, 12, FontStyle.Regular);
    122               string text = "No coordinates defined or in wrong format.";
    123               SizeF strSize = graphics.MeasureString(text, font);
    124               graphics.DrawString(text, font, Brushes.Black, (float)(pictureBox.Width - strSize.Width) / 2.0f, (float)(pictureBox.Height - strSize.Height) / 2.0f);
    125             }
    126           }
    127           pictureBox.Image = bitmap;
     91          pictureBox.Image = Visualizer.Draw(pictureBox.Width, pictureBox.Height);
    12892        }
    12993      }
     
    13599      else {
    136100        switch (e.PropertyName) {
    137           case nameof(Content.Coordinates):
     101          case nameof(Content.TSPData):
     102            if (Content.TSPData is CoordinatesTSPData coordTsp)
     103              Visualizer.Coordinates = coordTsp.Coordinates;
     104            else if (Content.TSPData is MatrixTSPData matrixTsp)
     105              Visualizer.Coordinates = matrixTsp.DisplayCoordinates;
    138106            GenerateImage();
    139107            break;
    140108          case nameof(Content.Tour):
     109            Visualizer.Tour = Content.Tour;
    141110            GenerateImage();
    142111            tourViewHost.Content = Content.Tour;
  • branches/2521_ProblemRefactoring/HeuristicLab.Problems.TravelingSalesman/3.3/TSP.cs

    r17320 r17335  
    143143      Description = data.Description;
    144144
    145       if (data.Dimension <= DistanceMatrixSizeLimit) {
    146         TSPData = new MatrixTSPData(data.Name, data.GetDistanceMatrix(), data.Coordinates) { Description = data.Description };
    147       } else if (data.DistanceMeasure == DistanceMeasure.Direct && data.Distances != null) {
    148         TSPData = new MatrixTSPData(data.Name, data.Distances, data.Coordinates) { Description = data.Description };
    149       } else {
    150         switch (data.DistanceMeasure) {
    151           case DistanceMeasure.Att:
    152             TSPData = new AttTSPData(data.Name, data.Coordinates) { Description = data.Description };
    153             break;
    154           case DistanceMeasure.Euclidean:
    155             TSPData = new EuclideanTSPData(data.Name, data.Coordinates, EuclideanTSPData.DistanceRounding.None) { Description = data.Description };
    156             break;
    157           case DistanceMeasure.RoundedEuclidean:
    158             TSPData = new EuclideanTSPData(data.Name, data.Coordinates, EuclideanTSPData.DistanceRounding.Midpoint) { Description = data.Description };
    159             break;
    160           case DistanceMeasure.UpperEuclidean:
    161             TSPData = new EuclideanTSPData(data.Name, data.Coordinates, EuclideanTSPData.DistanceRounding.Ceiling) { Description = data.Description };
    162             break;
    163           case DistanceMeasure.Geo:
    164             TSPData = new GeoTSPData(data.Name, data.Coordinates) { Description = data.Description };
    165             break;
    166           case DistanceMeasure.Manhattan:
    167             TSPData = new ManhattanTSPData(data.Name, data.Coordinates) { Description = data.Description };
    168             break;
    169           case DistanceMeasure.Maximum:
    170             TSPData = new MaximumTSPData(data.Name, data.Coordinates) { Description = data.Description };
    171             break;
    172           default:
    173             throw new System.IO.InvalidDataException("An unknown distance measure is given in the instance!");
    174         }
    175       }
     145      TSPData = GetDataFromInstance(data);
    176146      BestKnownSolution = null;
    177147      BestKnownQuality = double.NaN;
     
    181151          var tour = new Permutation(PermutationTypes.RelativeUndirected, data.BestKnownTour);
    182152          var tourLength = Evaluate(tour);
    183           BestKnownSolution = new TSPSolution(data.Coordinates != null ? new DoubleMatrix(data.Coordinates) : null, tour, new DoubleValue(tourLength));
     153          BestKnownSolution = new TSPSolution(TSPData, tour, new DoubleValue(tourLength));
    184154          BestKnownQuality = tourLength;
    185155        } catch (InvalidOperationException) {
     
    191161      }
    192162      OnReset();
     163    }
     164
     165    public static ITSPData GetDataFromInstance(TSPData input) {
     166      ITSPData tspData = null;
     167      if (input.Dimension <= DistanceMatrixSizeLimit) {
     168        tspData = new MatrixTSPData(input.Name, input.GetDistanceMatrix(), input.Coordinates) { Description = input.Description };
     169      } else if (input.DistanceMeasure == DistanceMeasure.Direct && input.Distances != null) {
     170        tspData = new MatrixTSPData(input.Name, input.Distances, input.Coordinates) { Description = input.Description };
     171      } else {
     172        switch (input.DistanceMeasure) {
     173          case DistanceMeasure.Att:
     174            tspData = new AttTSPData(input.Name, input.Coordinates) { Description = input.Description };
     175            break;
     176          case DistanceMeasure.Euclidean:
     177            tspData = new EuclideanTSPData(input.Name, input.Coordinates, EuclideanTSPData.DistanceRounding.None) { Description = input.Description };
     178            break;
     179          case DistanceMeasure.RoundedEuclidean:
     180            tspData = new EuclideanTSPData(input.Name, input.Coordinates, EuclideanTSPData.DistanceRounding.Midpoint) { Description = input.Description };
     181            break;
     182          case DistanceMeasure.UpperEuclidean:
     183            tspData = new EuclideanTSPData(input.Name, input.Coordinates, EuclideanTSPData.DistanceRounding.Ceiling) { Description = input.Description };
     184            break;
     185          case DistanceMeasure.Geo:
     186            tspData = new GeoTSPData(input.Name, input.Coordinates) { Description = input.Description };
     187            break;
     188          case DistanceMeasure.Manhattan:
     189            tspData = new ManhattanTSPData(input.Name, input.Coordinates) { Description = input.Description };
     190            break;
     191          case DistanceMeasure.Maximum:
     192            tspData = new MaximumTSPData(input.Name, input.Coordinates) { Description = input.Description };
     193            break;
     194          default:
     195            throw new System.IO.InvalidDataException("An unknown distance measure is given in the instance!");
     196        }
     197      }
     198      return tspData;
    193199    }
    194200
  • branches/2521_ProblemRefactoring/HeuristicLab.Problems.TravelingSalesman/3.3/TSPData.cs

    r17254 r17335  
    4040  [Item("Matrix-based TSP Data", "TSP that is representd by a distance matrix.")]
    4141  [StorableType("4df58a35-679d-4414-b815-9450ae100823")]
    42   public class MatrixTSPData : NamedItem, ITSPData {
    43     [Storable] public DoubleMatrix Matrix { get; protected set; }
    44     [Storable] public DoubleMatrix DisplayCoordinates { get; protected set; }
     42  public sealed class MatrixTSPData : NamedItem, ITSPData {
     43    [Storable] public DoubleMatrix Matrix { get; private set; }
     44    [Storable] public DoubleMatrix DisplayCoordinates { get; private set; }
    4545
    4646    public int Cities => Matrix.Rows;
    4747
    4848    [StorableConstructor]
    49     protected  MatrixTSPData(StorableConstructorFlag _) : base(_) { }
    50     protected MatrixTSPData(MatrixTSPData original, Cloner cloner) : base(original, cloner) {
     49    private  MatrixTSPData(StorableConstructorFlag _) : base(_) { }
     50    private MatrixTSPData(MatrixTSPData original, Cloner cloner) : base(original, cloner) {
    5151      Matrix = original.Matrix;
    5252      DisplayCoordinates = original.DisplayCoordinates;
     
    7676    }
    7777
    78     public virtual ITSPSolution GetSolution(Permutation tour, double tourLength) {
    79       return new TSPSolution(DisplayCoordinates, tour, new DoubleValue(tourLength));
     78    public ITSPSolution GetSolution(Permutation tour, double tourLength) {
     79      return new TSPSolution(this, tour, new DoubleValue(tourLength));
    8080    }
    8181
     
    135135
    136136    public virtual ITSPSolution GetSolution(Permutation tour, double tourLength) {
    137       return new TSPSolution(Coordinates, tour, new DoubleValue(tourLength));
     137      return new TSPSolution(this, tour, new DoubleValue(tourLength));
    138138    }
    139139
     
    143143  [Item("Euclidean TSP Data", "TSP that is represented by coordinates in an Euclidean plane.")]
    144144  [StorableType("4bf58348-cd98-46c5-a4c0-55f486ca88b4")]
    145   public class EuclideanTSPData : CoordinatesTSPData {
     145  public sealed class EuclideanTSPData : CoordinatesTSPData {
    146146    public enum DistanceRounding { None, Midpoint, Ceiling }
    147147
    148148    [Storable]
    149     public DistanceRounding Rounding { get; protected set; }
    150 
    151     [StorableConstructor]
    152     protected EuclideanTSPData(StorableConstructorFlag _) : base(_) { }
    153     protected EuclideanTSPData(EuclideanTSPData original, Cloner cloner) : base(original, cloner) {
     149    public DistanceRounding Rounding { get; private set; }
     150
     151    [StorableConstructor]
     152    private EuclideanTSPData(StorableConstructorFlag _) : base(_) { }
     153    private EuclideanTSPData(EuclideanTSPData original, Cloner cloner) : base(original, cloner) {
    154154      Rounding = original.Rounding;
    155155    }
     
    199199  [Item("Geo TSP Data", "TSP that is represented by geo coordinates.")]
    200200  [StorableType("dc859a89-e6c2-4af3-a3b6-9aa3041b14a9")]
    201   public class GeoTSPData : CoordinatesTSPData {
    202     [StorableConstructor]
    203     protected GeoTSPData(StorableConstructorFlag _) : base(_) { }
    204     protected GeoTSPData(GeoTSPData original, Cloner cloner) : base(original, cloner) { }
     201  public sealed class GeoTSPData : CoordinatesTSPData {
     202    [StorableConstructor]
     203    private GeoTSPData(StorableConstructorFlag _) : base(_) { }
     204    private GeoTSPData(GeoTSPData original, Cloner cloner) : base(original, cloner) { }
    205205    public GeoTSPData() : base() { }
    206206    public GeoTSPData(string name, double[,] coordinates) : base(name, coordinates) { }
     
    228228  [Item("ATT TSP Data", "TSP that is represented by ATT coordinates.")]
    229229  [StorableType("d7a0add3-6ec1-42e0-b1d7-b6454694d485")]
    230   public class AttTSPData : CoordinatesTSPData {
    231     [StorableConstructor]
    232     protected AttTSPData(StorableConstructorFlag _) : base(_) { }
    233     protected AttTSPData(AttTSPData original, Cloner cloner) : base(original, cloner) { }
     230  public sealed class AttTSPData : CoordinatesTSPData {
     231    [StorableConstructor]
     232    private AttTSPData(StorableConstructorFlag _) : base(_) { }
     233    private AttTSPData(AttTSPData original, Cloner cloner) : base(original, cloner) { }
    234234    public AttTSPData() : base() { }
    235235    public AttTSPData(string name, double[,] coordinates) : base(name, coordinates) { }
     
    257257  [Item("Manhattan TSP Data", "TSP that is represented by Manhattan coordinates.")]
    258258  [StorableType("5f1ef9e2-cbd1-400e-8f87-6855f091fc9e")]
    259   public class ManhattanTSPData : CoordinatesTSPData {
    260     [StorableConstructor]
    261     protected ManhattanTSPData(StorableConstructorFlag _) : base(_) { }
    262     protected ManhattanTSPData(ManhattanTSPData original, Cloner cloner) : base(original, cloner) { }
     259  public sealed class ManhattanTSPData : CoordinatesTSPData {
     260    [StorableConstructor]
     261    private ManhattanTSPData(StorableConstructorFlag _) : base(_) { }
     262    private ManhattanTSPData(ManhattanTSPData original, Cloner cloner) : base(original, cloner) { }
    263263    public ManhattanTSPData() : base() { }
    264264    public ManhattanTSPData(string name, double[,] coordinates) : base(name, coordinates) { }
     
    286286  [Item("Manhattan TSP Data", "TSP that is represented by the maximum absolute distance in either x or y coordinates.")]
    287287  [StorableType("c6294a6c-fe62-4906-9765-4bc306d3e4a8")]
    288   public class MaximumTSPData : CoordinatesTSPData {
    289     [StorableConstructor]
    290     protected MaximumTSPData(StorableConstructorFlag _) : base(_) { }
    291     protected MaximumTSPData(MaximumTSPData original, Cloner cloner) : base(original, cloner) { }
     288  public sealed class MaximumTSPData : CoordinatesTSPData {
     289    [StorableConstructor]
     290    private MaximumTSPData(StorableConstructorFlag _) : base(_) { }
     291    private MaximumTSPData(MaximumTSPData original, Cloner cloner) : base(original, cloner) { }
    292292    public MaximumTSPData() : base() { }
    293293    public MaximumTSPData(string name, double[,] coordinates) : base(name, coordinates) { }
  • branches/2521_ProblemRefactoring/HeuristicLab.Problems.TravelingSalesman/3.3/TSPSolution.cs

    r17260 r17335  
    3131  [StorableType("f08a63d9-0b83-4944-9251-42925baeb872")]
    3232  public interface ITSPSolution : IItem, INotifyPropertyChanged {
    33     DoubleMatrix Coordinates { get; }
     33    ITSPData TSPData { get; }
    3434    Permutation Tour { get; }
    3535    DoubleValue TourLength { get; }
     
    4141  [Item("TSP Solution", "Represents a tour of a Traveling Salesman Problem given in path representation which can be visualized in the GUI.")]
    4242  [StorableType("38d1aac3-3047-40d9-bcf9-4b3ca0b9f95c")]
    43   public class TSPSolution : Item, ITSPSolution {
     43  public sealed class TSPSolution : Item, ITSPSolution {
    4444    public static new Image StaticItemImage {
    4545      get { return HeuristicLab.Common.Resources.VSImageLibrary.Image; }
     
    4747
    4848    [Storable]
    49     private DoubleMatrix coordinates;
    50     public DoubleMatrix Coordinates {
    51       get { return coordinates; }
     49    private ITSPData tspData;
     50    public ITSPData TSPData {
     51      get { return tspData; }
    5252      set {
    53         if (coordinates == value) return;
    54         coordinates = value;
    55         OnPropertyChanged(nameof(Coordinates));
     53        if (tspData == value) return;
     54        tspData = value;
     55        OnPropertyChanged(nameof(TSPData));
    5656      }
    5757    }
     
    7979
    8080    [StorableConstructor]
    81     protected TSPSolution(StorableConstructorFlag _) : base(_) { }
    82     protected TSPSolution(TSPSolution original, Cloner cloner)
     81    private TSPSolution(StorableConstructorFlag _) : base(_) { }
     82    private TSPSolution(TSPSolution original, Cloner cloner)
    8383      : base(original, cloner) {
    84       this.coordinates = cloner.Clone(original.coordinates);
     84      this.tspData = cloner.Clone(original.tspData);
    8585      this.tour = cloner.Clone(original.tour);
    8686      this.tourLength = cloner.Clone(original.tourLength);
    8787    }
    8888    public TSPSolution() : base() { }
    89     public TSPSolution(DoubleMatrix coordinates)
     89    public TSPSolution(ITSPData data)
    9090      : base() {
    91       this.coordinates = coordinates;
     91      this.tspData = data;
    9292    }
    93     public TSPSolution(DoubleMatrix coordinates, Permutation permutation)
     93    public TSPSolution(ITSPData data, Permutation permutation)
    9494      : base() {
    95       this.coordinates = coordinates;
     95      this.tspData = data;
    9696      this.tour = permutation;
    9797    }
    98     public TSPSolution(DoubleMatrix coordinates, Permutation permutation, DoubleValue quality)
     98    public TSPSolution(ITSPData data, Permutation permutation, DoubleValue quality)
    9999      : base() {
    100       this.coordinates = coordinates;
     100      this.tspData = data;
    101101      this.tour = permutation;
    102102      this.tourLength = quality;
     
    108108
    109109    public event PropertyChangedEventHandler PropertyChanged;
    110     protected void OnPropertyChanged(string property) {
     110    private void OnPropertyChanged(string property) {
    111111      PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(property));
    112112    }
Note: See TracChangeset for help on using the changeset viewer.