Free cookie consent management tool by TermsFeed Policy Generator

source: branches/Scheduling/HeuristicLab.Problems.TravelingSalesman/3.3/TSPLIBTourParser.cs @ 7089

Last change on this file since 7089 was 5445, checked in by swagner, 14 years ago

Updated year of copyrights (#1406)

File size: 5.8 KB
Line 
1#region License Information
2/* HeuristicLab
3 * Copyright (C) 2002-2011 Heuristic and Evolutionary Algorithms Laboratory (HEAL)
4 *
5 * This file is part of HeuristicLab.
6 *
7 * HeuristicLab is free software: you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation, either version 3 of the License, or
10 * (at your option) any later version.
11 *
12 * HeuristicLab is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15 * GNU General Public License for more details.
16 *
17 * You should have received a copy of the GNU General Public License
18 * along with HeuristicLab. If not, see <http://www.gnu.org/licenses/>.
19 */
20#endregion
21
22using System;
23using System.Globalization;
24using System.IO;
25
26namespace HeuristicLab.Problems.TravelingSalesman {
27  /// <summary>
28  /// Parses a *.opt.tour file in TSPLIB format and extracts its information about an optimal tour of a TSP.
29  /// </summary>
30  public class TSPLIBTourParser {
31    private const int EOF = 0;
32    private const int NAME = 1;
33    private const int TYPE = 2;
34    private const int COMMENT = 3;
35    private const int DIM = 4;
36    private const int TOURSECTION = 5;
37
38    private StreamReader source;
39
40    private string name;
41    /// <summary>
42    /// Gets the name of the parsed tour.
43    /// </summary>
44    public string Name {
45      get { return name; }
46    }
47    private string comment;
48    /// <summary>
49    /// Gets the comment of the parsed tour.
50    /// </summary>
51    public string Comment {
52      get { return comment; }
53    }
54    private int[] tour;
55    /// <summary>
56    /// Gets the parsed tour.
57    /// </summary>
58    public int[] Tour {
59      get { return tour; }
60    }
61
62    /// <summary>
63    /// Initializes a new instance of <see cref="TSPLIBTourParser"/> with the given <paramref name="path"/>.
64    /// </summary>
65    /// <exception cref="ArgumentException">Thrown if the input file is not a TSPLIB optimal tour file (*.opt.tour)
66    /// </exception>
67    /// <param name="path">The path where the optimal tour is stored.</param>
68    public TSPLIBTourParser(String path) {
69      if (!path.EndsWith(".opt.tour"))
70        throw new ArgumentException("Input file has to be a TSPLIB optimal tour file (*.opt.tour).");
71
72      source = new StreamReader(path);
73      name = path;
74      comment = string.Empty;
75      tour = null;
76    }
77
78    /// <summary>
79    /// Reads the TSPLIB optimal tour file and parses its elements.
80    /// </summary>
81    /// <exception cref="InvalidDataException">Thrown if the file has an invalid format or contains invalid data.</exception>
82    public void Parse() {
83      int section = -1;
84      string str = null;
85      bool typeIsChecked = false;
86
87      do {
88        str = source.ReadLine();
89        section = GetSection(str);
90
91        if (section != -1) {
92          switch (section) {
93            case NAME:
94              ReadName(str);
95              break;
96            case TYPE:
97              CheckType(str);
98              typeIsChecked = true;
99              break;
100            case COMMENT:
101              ReadComment(str);
102              break;
103            case DIM:
104              InitTour(str);
105              break;
106            case TOURSECTION:
107              ReadTour();
108              break;
109          }
110        }
111      } while (!((section == EOF) || (str == null)));
112
113      if (!typeIsChecked)
114        throw new InvalidDataException("Input file does not contain type information.");
115    }
116
117    private int GetSection(string str) {
118      if (str == null)
119        return EOF;
120
121      string[] tokens = str.Split(new string[] { ":" }, StringSplitOptions.None);
122      if (tokens.Length == 0)
123        return -1;
124
125      string token = tokens[0].Trim();
126      if (token.Equals("eof", StringComparison.OrdinalIgnoreCase))
127        return EOF;
128      if (token.Equals("name", StringComparison.OrdinalIgnoreCase))
129        return NAME;
130      if (token.Equals("type", StringComparison.OrdinalIgnoreCase))
131        return TYPE;
132      if (token.Equals("comment", StringComparison.OrdinalIgnoreCase))
133        return COMMENT;
134      if (token.Equals("dimension", StringComparison.OrdinalIgnoreCase))
135        return DIM;
136      if (token.Equals("tour_section", StringComparison.OrdinalIgnoreCase))
137        return TOURSECTION;
138
139      return -1;
140    }
141
142    private void ReadName(string str) {
143      string[] tokens = str.Split(new string[] { ":" }, StringSplitOptions.None);
144      name = tokens[tokens.Length - 1].Trim();
145    }
146
147    private void CheckType(string str) {
148      string[] tokens = str.Split(new string[] { ":" }, StringSplitOptions.None);
149
150      string type = tokens[tokens.Length - 1].Trim();
151      if (!type.Equals("tour", StringComparison.OrdinalIgnoreCase))
152        throw new InvalidDataException("Input data format is not \"TOUR\"");
153    }
154
155    private void ReadComment(string str) {
156      string[] tokens = str.Split(new string[] { ":" }, StringSplitOptions.None);
157      comment = tokens[tokens.Length - 1].Trim();
158    }
159
160    private void InitTour(string str) {
161      string[] tokens = str.Split(new string[] { ":" }, StringSplitOptions.None);
162      string dimension = tokens[tokens.Length - 1].Trim();
163
164      int dim = Int32.Parse(dimension);
165      tour = new int[dim];
166    }
167
168    private void ReadTour() {
169      if (tour == null)
170        throw new InvalidDataException("Input file does not contain dimension information.");
171
172      for (int i = 0; i < (tour.Length); i++) {
173        string str = source.ReadLine();
174
175        CultureInfo culture = new CultureInfo("en-US");
176        tour[i] = int.Parse(str, culture.NumberFormat) - 1;
177      }
178    }
179  }
180}
Note: See TracBrowser for help on using the repository browser.