Free cookie consent management tool by TermsFeed Policy Generator

source: trunk/sources/HeuristicLab.Routing.TSP/TSPParser.cs @ 1502

Last change on this file since 1502 was 884, checked in by vdorfer, 16 years ago

Created API documentation for HeuristicLab.Routing.TSP namespace (#331)

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