Free cookie consent management tool by TermsFeed Policy Generator

source: branches/PTSP/HeuristicLab.Problems.PTSP/3.3/PTSPLIBInstanceProvider.cs @ 13202

Last change on this file since 13202 was 13202, checked in by abeham, 8 years ago

#2221: reverse engineered PTSPData and added simple instance provider based on TSPLIB

File size: 6.5 KB
Line 
1using System;
2using System.Collections.Generic;
3using System.IO;
4using System.IO.Compression;
5using System.Linq;
6using HeuristicLab.Problems.Instances;
7using HeuristicLab.Problems.Instances.TSPLIB;
8
9namespace HeuristicLab.Problems.PTSP {
10  public class PTSPLIBInstanceProvider : TSPLIBInstanceProvider<PTSPData> {
11
12    public override string Name {
13      get { return "(P)TSPLIB (symmetric TSP)"; }
14    }
15
16    public override string Description {
17      get { return "Adaption of the Traveling Salesman Problem Library for probabilistic instances"; }
18    }
19
20    protected override string FileExtension { get { return "tsp"; } }
21
22    public override IEnumerable<IDataDescriptor> GetDataDescriptors() {
23      Dictionary<string, string> solutions = new Dictionary<string, string>();
24      var solutionsArchiveName = GetResourceName(FileExtension + @"\.opt\.tour\.zip");
25      if (!String.IsNullOrEmpty(solutionsArchiveName)) {
26        using (var solutionsZipFile = new ZipArchive(typeof(TSPLIBTSPInstanceProvider).Assembly.GetManifestResourceStream(solutionsArchiveName), ZipArchiveMode.Read)) {
27          foreach (var entry in solutionsZipFile.Entries)
28            solutions.Add(entry.Name.Substring(0, entry.Name.Length - ".opt.tour".Length) + "." + FileExtension, entry.Name);
29        }
30      }
31      var instanceArchiveName = GetResourceName(FileExtension + @"\.zip");
32      if (String.IsNullOrEmpty(instanceArchiveName)) yield break;
33
34      using (var instanceStream = new ZipArchive(typeof(TSPLIBTSPInstanceProvider).Assembly.GetManifestResourceStream(instanceArchiveName), ZipArchiveMode.Read)) {
35        foreach (var entry in instanceStream.Entries.Select(x => x.Name).OrderBy(x => x)) {
36          yield return new PTSPDataDescriptor(Path.GetFileNameWithoutExtension(entry), GetInstanceDescription(), entry, solutions.ContainsKey(entry) ? solutions[entry] : String.Empty);
37        }
38      }
39    }
40
41    public override PTSPData LoadData(IDataDescriptor id) {
42      var descriptor = (PTSPDataDescriptor)id;
43      var instanceArchiveName = GetResourceName(FileExtension + @"\.zip");
44      using (var instancesZipFile = new ZipArchive(typeof(TSPLIBTSPInstanceProvider).Assembly.GetManifestResourceStream(instanceArchiveName), ZipArchiveMode.Read)) {
45        var entry = instancesZipFile.GetEntry(descriptor.InstanceIdentifier);
46        var stream = entry.Open();
47        var parser = new TSPLIBParser(stream);
48        var instance = LoadInstance(parser);
49
50        if (!String.IsNullOrEmpty(descriptor.SolutionIdentifier)) {
51          var solutionsArchiveName = GetResourceName(FileExtension + @"\.opt\.tour\.zip");
52          using (var solutionsZipFile = new ZipArchive(typeof(TSPLIBTSPInstanceProvider).Assembly.GetManifestResourceStream(solutionsArchiveName), ZipArchiveMode.Read)) {
53            entry = solutionsZipFile.GetEntry(descriptor.SolutionIdentifier);
54            stream = entry.Open();
55            parser = new TSPLIBParser(stream);
56            LoadSolution(parser, instance);
57          }
58        }
59
60        return instance;
61      }
62    }
63
64    protected override PTSPData LoadInstance(TSPLIBParser parser) {
65      parser.Parse();
66      if (parser.FixedEdges != null) throw new InvalidDataException("TSP instance " + parser.Name + " contains fixed edges which are not supported by HeuristicLab.");
67      var instance = new PTSPData();
68      instance.Dimension = parser.Dimension;
69      instance.Coordinates = parser.Vertices ?? parser.DisplayVertices;
70      instance.Distances = parser.Distances;
71      switch (parser.EdgeWeightType) {
72        case TSPLIBEdgeWeightTypes.ATT:
73          instance.DistanceMeasure = DistanceMeasure.Att; break;
74        case TSPLIBEdgeWeightTypes.CEIL_2D:
75          instance.DistanceMeasure = DistanceMeasure.UpperEuclidean; break;
76        case TSPLIBEdgeWeightTypes.EUC_2D:
77          instance.DistanceMeasure = DistanceMeasure.RoundedEuclidean; break;
78        case TSPLIBEdgeWeightTypes.EUC_3D:
79          throw new InvalidDataException("3D coordinates are not supported.");
80        case TSPLIBEdgeWeightTypes.EXPLICIT:
81          instance.DistanceMeasure = DistanceMeasure.Direct; break;
82        case TSPLIBEdgeWeightTypes.GEO:
83          instance.DistanceMeasure = DistanceMeasure.Geo; break;
84        case TSPLIBEdgeWeightTypes.MAN_2D:
85          instance.DistanceMeasure = DistanceMeasure.Manhattan; break;
86        case TSPLIBEdgeWeightTypes.MAN_3D:
87          throw new InvalidDataException("3D coordinates are not supported.");
88        case TSPLIBEdgeWeightTypes.MAX_2D:
89          instance.DistanceMeasure = DistanceMeasure.Maximum; break;
90        case TSPLIBEdgeWeightTypes.MAX_3D:
91          throw new InvalidDataException("3D coordinates are not supported.");
92        default:
93          throw new InvalidDataException("The given edge weight is not supported by HeuristicLab.");
94      }
95
96      // use own hash function in case the implementation of String.GetHashCode() changes
97      // ... and hope that System.Random doesn't change
98      var random = new System.Random(Hash(parser.Name));
99      instance.Probabilities = Enumerable.Range(0, parser.Dimension).Select(x => random.NextDouble() * 0.8 + 0.1).ToArray();
100      instance.Name = parser.Name;
101      instance.Description = parser.Comment
102        + Environment.NewLine + Environment.NewLine
103        + GetInstanceDescription();
104      return instance;
105    }
106
107    protected override void LoadSolution(TSPLIBParser parser, PTSPData instance) {
108      // the TSP optimal tour isn't necessarily the PTSP optimal tour
109    }
110
111    public PTSPData LoadData(string tspFile, double? bestQuality) {
112      var data = LoadInstance(new TSPLIBParser(tspFile));
113      if (bestQuality.HasValue)
114        data.BestKnownQuality = bestQuality.Value;
115      return data;
116    }
117
118    private int Hash(string s) {
119      var h = 3571;
120      unchecked {
121        for (var i = 0; i < s.Length; i++)
122          h = h * 31 + s[i];
123      }
124      return h;
125    }
126  }
127
128  internal class PTSPDataDescriptor : IDataDescriptor {
129    public string Name { get; internal set; }
130    public string Description { get; internal set; }
131
132    internal string InstanceIdentifier { get; set; }
133    internal string SolutionIdentifier { get; set; }
134
135    internal PTSPDataDescriptor(string name, string description, string instanceIdentifier, string solutionIdentifier) {
136      this.Name = name;
137      this.Description = description;
138      this.InstanceIdentifier = instanceIdentifier;
139      this.SolutionIdentifier = solutionIdentifier;
140    }
141  }
142}
Note: See TracBrowser for help on using the repository browser.