Free cookie consent management tool by TermsFeed Policy Generator

source: trunk/sources/HeuristicLab.Problems.TSP/3.3/TSPLIBParser.cs @ 3038

Last change on this file since 3038 was 2883, checked in by swagner, 15 years ago

Operator architecture refactoring (#95)

  • renamed HeuristicLab.Routing.TSP to HeuristicLab.Problems.TSP
File size: 7.0 KB
Line 
1#region License Information
2/* HeuristicLab
3 * Copyright (C) 2002-2010 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.TSP {
27  /// <summary>
28  /// Parses a *.tsp file in the TSPLIB format and extracts its information about a TSP.
29  /// </summary>
30  public class TSPLIBParser {
31    private const int EOF = 0;
32    private const int NAME = 1;
33    private const int TYPE = 2;
34    private const int DIM = 3;
35    private const int WEIGHTTYPE = 4;
36    private const int NODETYPE = 5;
37    private const int NODESECTION = 6;
38
39    private StreamReader source;
40
41    private string myName;
42    /// <summary>
43    /// Gets the name of the parsed TSP.
44    /// </summary>
45    public string Name {
46      get { return myName; }
47    }
48    private double[,] myVertices;
49    /// <summary>
50    /// Gets the vertices of the parsed TSP.
51    /// </summary>
52    public double[,] Vertices {
53      get { return myVertices; }
54    }
55    private int myWeightType;
56    /// <summary>
57    /// Gets the weight type of the parsed TSP.
58    /// </summary>
59    public int WeightType {
60      get { return myWeightType; }
61    }
62
63    /// <summary>
64    /// Initializes a new instance of <see cref="TSPParser"/> with the given <paramref name="path"/>.
65    /// </summary>
66    /// <exception cref="ArgumentException">Thrown when the input file name is not in TSP format (*.tsp)
67    /// </exception>
68    /// <param name="path">The path where the TSP is stored.</param>
69    public TSPLIBParser(String path) {
70      if (!path.EndsWith(".tsp"))
71        throw new ArgumentException("Input file name has to be in TSP format (*.tsp)");
72
73      source = new StreamReader(path);
74      myName = path;
75      myVertices = null;
76      myWeightType = -1;
77    }
78
79    /// <summary>
80    /// Reads the TSP file and parses the elements.
81    /// </summary>
82    /// <exception cref="InvalidDataException">Thrown when file contains unknown (edge) types.</exception>
83    public void Parse() {
84      int section = -1;
85      string str = null;
86      bool typeIsChecked = false;
87      bool weightTypeIsChecked = false;
88
89      do {
90        str = source.ReadLine();
91        section = GetSection(str);
92
93        if (section != -1) {
94          switch (section) {
95            case NAME:
96              ReadName(str);
97              break;
98            case TYPE:
99              CheckType(str);
100              typeIsChecked = true;
101              break;
102            case DIM:
103              InitVerticesArray(str);
104              break;
105            case WEIGHTTYPE:
106              ReadWeightType(str);
107              weightTypeIsChecked = true;
108              break;
109            case NODETYPE:
110              CheckNodeType(str);
111              break;
112            case NODESECTION:
113              ReadVertices();
114              break;
115          }
116        }
117      } while (!((section == EOF) || (str == null)));
118
119      if (!(typeIsChecked && weightTypeIsChecked))
120        throw new InvalidDataException("File contains unknown (edge) types");
121    }
122
123    private int GetSection(string str) {
124      if (str == null)
125        return EOF;
126
127      string[] tokens = str.Split(new string[] { ":" }, StringSplitOptions.None);
128      if (tokens.Length == 0)
129        return -1;
130
131      string token = tokens[0].Trim();
132      if (token.Equals("eof", StringComparison.OrdinalIgnoreCase))
133        return EOF;
134      if (token.Equals("name", StringComparison.OrdinalIgnoreCase))
135        return NAME;
136      if (token.Equals("type", StringComparison.OrdinalIgnoreCase))
137        return TYPE;
138      if (token.Equals("dimension", StringComparison.OrdinalIgnoreCase))
139        return DIM;
140      if (token.Equals("edge_weight_type", StringComparison.OrdinalIgnoreCase))
141        return WEIGHTTYPE;
142      if (token.Equals("node_coord_type", StringComparison.OrdinalIgnoreCase))
143        return NODETYPE;
144      if (token.Equals("node_coord_section", StringComparison.OrdinalIgnoreCase))
145        return NODESECTION;
146
147      return -1;
148    }
149
150    private void ReadName(string str) {
151      string[] tokens = str.Split(new string[] { ":" }, StringSplitOptions.None);
152      myName = tokens[tokens.Length - 1].Trim();
153    }
154
155    private void CheckType(string str) {
156      string[] tokens = str.Split(new string[] { ":" }, StringSplitOptions.None);
157
158      string type = tokens[tokens.Length - 1].Trim();
159      if (!type.Equals("tsp", StringComparison.OrdinalIgnoreCase))
160        throw new InvalidDataException("Input data format is not \"TSP\"");
161    }
162
163    private void InitVerticesArray(string str) {
164      string[] tokens = str.Split(new string[] { ":" }, StringSplitOptions.None);
165      string dimension = tokens[tokens.Length - 1].Trim();
166
167      int dim = Int32.Parse(dimension);
168      myVertices = new double[dim, 2];
169    }
170
171    private void ReadWeightType(string str) {
172      string[] tokens = str.Split(new string[] { ":" }, StringSplitOptions.None);
173      string type = tokens[tokens.Length - 1].Trim();
174
175      if (type.Equals("euc_2d", StringComparison.OrdinalIgnoreCase))
176        myWeightType = 0;
177      else if (type.Equals("geo", StringComparison.OrdinalIgnoreCase))
178        myWeightType = 1;
179      else
180        throw new InvalidDataException("Unsupported type of edge weights");
181    }
182
183    private void CheckNodeType(string str) {
184      string[] tokens = str.Split(new string[] { ":" }, StringSplitOptions.None);
185      string type = tokens[tokens.Length - 1].Trim();
186
187      if (!type.Equals("twod_coords", StringComparison.OrdinalIgnoreCase))
188        throw new InvalidDataException("Unsupported node type");
189    }
190
191    private void ReadVertices() {
192      if (myVertices == null)
193        throw new InvalidDataException("Dimension not found");
194
195      for (int i = 0; i < (myVertices.Length / 2); i++) {
196        string str = source.ReadLine();
197        string[] tokens = str.Split(new string[] { " " }, StringSplitOptions.RemoveEmptyEntries);
198
199        if (tokens.Length != 3)
200          throw new InvalidDataException("Invalid node format");
201
202        CultureInfo culture = new CultureInfo("en-US");
203        myVertices[i, 0] = Double.Parse(tokens[1], culture.NumberFormat);
204        myVertices[i, 1] = Double.Parse(tokens[2], culture.NumberFormat);
205      }
206    }
207  }
208}
Note: See TracBrowser for help on using the repository browser.