Free cookie consent management tool by TermsFeed Policy Generator

source: branches/VRP/HeuristicLab.Problems.Instances.VehicleRouting/3.4/GoldenFormat/GoldenParser.cs @ 7883

Last change on this file since 7883 was 7883, checked in by svonolfe, 12 years ago

Added additional test instances (#1177)

File size: 12.2 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.Instances.VehicleRouting {
27  public class GoldenParser {
28    private string file;
29    private Stream stream;
30    private string problemName;
31   
32    #region Inner Enum TSPLIBEdgeWeightType
33    public enum GoldenEdgeWeightType {
34      UNDEFINED,
35      EUC_2D,
36      GEO
37    }
38    #endregion
39
40    private const int EOF = 0;
41    private const int NAME = 1;
42    private const int TYPE = 2;
43    private const int COMMENT = 3;
44    private const int DIM = 4;
45    private const int WEIGHTTYPE = 5;
46    private const int WEIGHTFORMAT = 11;
47    private const int NODETYPE = 6;
48    private const int NODESECTION = 7;
49    private const int CAPACITY = 8;
50    private const int VEHICLES = 13;
51    private const int DEPOTSECTION = 9;
52    private const int DEMANDSECTION = 10;
53
54    private string comment;
55    /// <summary>
56    /// Gets the comment of the parsed VRP.
57    /// </summary>
58    public string Comment {
59      get { return comment; }
60    }
61    private double[,] vertices;
62    /// <summary>
63    /// Gets the vertices of the parsed VRP.
64    /// </summary>
65    public double[,] Vertices {
66      get { return vertices; }
67    }
68    private GoldenEdgeWeightType weightType;
69    /// <summary>
70    /// Gets the weight format of the parsed VRP.
71    /// </summary>
72    public GoldenEdgeWeightType WeightType {
73      get { return weightType; }
74    }
75
76    private double capacity;
77    public double Capacity {
78      get {
79        return capacity;
80      }
81    }
82
83    private int vehicles;
84    public int Vehicles {
85      get {
86        return vehicles;
87      }
88    }
89
90    private double[] demands;
91    public double[] Demands {
92      get {
93        return demands;
94      }
95    }
96
97    public String ProblemName {
98      get {
99        return problemName;
100      }
101    }
102
103    /// <summary>
104    /// Initializes a new instance of <see cref="TSPLIBParser"/> with the given <paramref name="path"/>.
105    /// </summary>
106    /// <exception cref="ArgumentException">Thrown if the input file is not a TSPLIB TSP file (*.vrp)
107    /// </exception>
108    /// <param name="path">The path where the VRP is stored.</param>
109    public GoldenParser() {
110      comment = string.Empty;
111      vertices = null;
112      weightType = GoldenEdgeWeightType.UNDEFINED;
113      capacity = -1;
114      vehicles = -1;
115      demands = null;
116    }
117
118    public GoldenParser(string file): this() {
119      this.file = file;
120    }
121
122    public GoldenParser(Stream stream)
123       : this() {
124      this.stream = stream;
125    }
126
127    /// <summary>
128    /// Reads the TSPLIB VRP file and parses the elements.
129    /// </summary>
130    /// <exception cref="InvalidDataException">Thrown if the file has an invalid format or contains invalid data.</exception>
131    public void Parse() {
132      StreamReader reader;
133      if (stream != null) {
134        reader = new StreamReader(stream);
135      } else {
136        reader = new StreamReader(file);
137        problemName = Path.GetFileNameWithoutExtension(file);
138      }
139
140      using (reader) {
141        int section = -1;
142        string str = null;
143        bool weightFormatIsChecked = false;
144
145        do {
146          str = reader.ReadLine();
147          section = GetSection(str);
148
149          if (section != -1) {
150            switch (section) {
151              case NAME:
152                ReadName(str);
153                break;
154              case TYPE:
155                CheckType(str);
156                break;
157              case COMMENT:
158                ReadComment(str);
159                break;
160              case DIM:
161                InitArrays(str);
162                break;
163              case WEIGHTTYPE:
164                ReadWeightType(str);
165                break;
166              case WEIGHTFORMAT:
167                ReadWeightFormat(str);
168                weightFormatIsChecked = true;
169                break;
170              case NODETYPE:
171                CheckNodeType(str);
172                break;
173              case NODESECTION:
174                ReadVertices(reader);
175                break;
176              case CAPACITY:
177                ReadCapacity(str);
178                break;
179              case VEHICLES:
180                ReadVehicles(str);
181                break;
182              case DEPOTSECTION:
183                ReadDepot(reader);
184                break;
185              case DEMANDSECTION:
186                ReadDemands(reader);
187                break;
188            }
189          }
190        } while (!((section == EOF) || (str == null)));
191
192        if (!weightFormatIsChecked || weightType == GoldenEdgeWeightType.UNDEFINED)
193          throw new InvalidDataException("Input file does not contain format or edge weight format information.");
194      }
195    }
196
197    private int GetSection(string str) {
198      if (str == null)
199        return EOF;
200
201      string[] tokens = str.Split(new string[] { ":" }, StringSplitOptions.None);
202      if (tokens.Length == 0)
203        return -1;
204
205      string token = tokens[0].Trim();
206      if (token.Equals("eof", StringComparison.OrdinalIgnoreCase))
207        return EOF;
208      if (token.Equals("name", StringComparison.OrdinalIgnoreCase))
209        return NAME;
210      if (token.Equals("type", StringComparison.OrdinalIgnoreCase))
211        return TYPE;
212      if (token.Equals("comment", StringComparison.OrdinalIgnoreCase))
213        return COMMENT;
214      if (token.Equals("dimension", StringComparison.OrdinalIgnoreCase))
215        return DIM;
216      if (token.Equals("edge_weight_type", StringComparison.OrdinalIgnoreCase))
217        return WEIGHTTYPE;
218      if (token.Equals("edge_weight_format", StringComparison.OrdinalIgnoreCase))
219        return WEIGHTFORMAT;
220      if (token.Equals("node_coord_type", StringComparison.OrdinalIgnoreCase))
221        return NODETYPE;
222      if (token.Equals("node_coord_section", StringComparison.OrdinalIgnoreCase))
223        return NODESECTION;
224      if (token.Equals("capacity", StringComparison.OrdinalIgnoreCase))
225        return CAPACITY;
226      if (token.Equals("vehicles", StringComparison.OrdinalIgnoreCase))
227        return VEHICLES;
228      if (token.Equals("depot_section", StringComparison.OrdinalIgnoreCase))
229        return DEPOTSECTION;
230      if (token.Equals("demand_section", StringComparison.OrdinalIgnoreCase))
231        return DEMANDSECTION;
232
233      return -1;
234    }
235
236    private void ReadName(string str) {
237      string[] tokens = str.Split(new string[] { ":" }, StringSplitOptions.None);
238      problemName = tokens[tokens.Length - 1].Trim();
239    }
240
241    private void CheckType(string str) {
242      string[] tokens = str.Split(new string[] { ":" }, StringSplitOptions.None);
243
244      string type = tokens[tokens.Length - 1].Trim();
245      if (!type.Equals("cvrp", StringComparison.OrdinalIgnoreCase))
246        throw new InvalidDataException("Input file format is not \"CVRP\"");
247    }
248
249    private void ReadComment(string str) {
250      string[] tokens = str.Split(new string[] { ":" }, StringSplitOptions.None);
251      comment = tokens[tokens.Length - 1].Trim();
252    }
253
254    private void InitArrays(string str) {
255      string[] tokens = str.Split(new string[] { ":" }, StringSplitOptions.None);
256      string dimension = tokens[tokens.Length - 1].Trim();
257
258      int dim = Int32.Parse(dimension);
259      vertices = new double[dim, 2];
260      demands = new double[dim];
261    }
262
263    private void ReadWeightType(string str) {
264      string[] tokens = str.Split(new string[] { ":" }, StringSplitOptions.None);
265      string type = tokens[tokens.Length - 1].Trim();
266
267      if (type.Equals("euc_2d", StringComparison.OrdinalIgnoreCase))
268        weightType = GoldenEdgeWeightType.EUC_2D;
269      else if (type.Equals("geo", StringComparison.OrdinalIgnoreCase))
270        weightType = GoldenEdgeWeightType.GEO;
271      else if (type.Equals("function", StringComparison.OrdinalIgnoreCase)) {
272        weightType = GoldenEdgeWeightType.UNDEFINED;
273      } else
274        throw new InvalidDataException("Input file contains an unsupported edge weight format (only \"EUC_2D\" and \"GEO\" are supported).");
275    }
276
277    private void ReadWeightFormat(string str) {
278      string[] tokens = str.Split(new string[] { ":" }, StringSplitOptions.None);
279      string format = tokens[tokens.Length - 1].Trim();
280
281      if (format.Equals("euc_2d", StringComparison.OrdinalIgnoreCase))
282        weightType = GoldenEdgeWeightType.EUC_2D;
283      else if (format.Equals("geo", StringComparison.OrdinalIgnoreCase))
284        weightType = GoldenEdgeWeightType.GEO;
285      else
286        throw new InvalidDataException("Input file contains an unsupported edge weight format.");
287    }
288
289    private void CheckNodeType(string str) {
290      string[] tokens = str.Split(new string[] { ":" }, StringSplitOptions.None);
291      string type = tokens[tokens.Length - 1].Trim();
292
293      if (!type.Equals("twod_coords", StringComparison.OrdinalIgnoreCase))
294        throw new InvalidDataException("Input file contains an unsupported node coordinates format (only \"TWOD_COORDS\" is supported).");
295    }
296
297    private void ReadVertices(StreamReader reader) {
298      if (vertices == null)
299        throw new InvalidDataException("Input file does not contain dimension information.");
300
301      for (int i = 1; i < (vertices.Length / 2); i++) {
302        string str = reader.ReadLine();
303        string[] tokens = str.Split(new string[] { " " }, StringSplitOptions.RemoveEmptyEntries);
304
305        if (tokens.Length != 3)
306          throw new InvalidDataException("Input file contains invalid node coordinates.");
307
308        vertices[i, 0] = double.Parse(tokens[1], System.Globalization.CultureInfo.InvariantCulture);
309        vertices[i, 1] = double.Parse(tokens[2], System.Globalization.CultureInfo.InvariantCulture);
310      }
311    }
312
313    private void ReadCapacity(string str) {
314      string[] tokens = str.Split(new string[] { ":" }, StringSplitOptions.None);
315      capacity = double.Parse(tokens[tokens.Length - 1].Trim(), System.Globalization.CultureInfo.InvariantCulture);
316    }
317
318    private void ReadVehicles(string str) {
319      string[] tokens = str.Split(new string[] { ":" }, StringSplitOptions.None);
320      vehicles = int.Parse(tokens[tokens.Length - 1].Trim());
321    }
322
323    private void ReadDepot(StreamReader reader) {
324      string[] tokens;
325      do {
326        string str = reader.ReadLine();
327        tokens = str.Split(new string[] { " " }, StringSplitOptions.RemoveEmptyEntries);
328
329        if (tokens.Length == 2) {
330          vertices[0, 0] = double.Parse(tokens[0], System.Globalization.CultureInfo.InvariantCulture);
331          vertices[0, 1] = double.Parse(tokens[1], System.Globalization.CultureInfo.InvariantCulture);
332        }
333      } while (tokens.Length == 2);
334    }
335
336    private void ReadDemands(StreamReader reader) {
337      if (demands == null)
338        throw new InvalidDataException("Input file does not contain dimension information.");
339
340      for (int i = 0; i < demands.Length; i++) {
341        if (i != 0) {
342          string str = reader.ReadLine();
343          string[] tokens = str.Split(new string[] { " " }, StringSplitOptions.RemoveEmptyEntries);
344
345          if (tokens.Length != 2)
346            throw new InvalidDataException("Input file contains invalid demands.");
347
348          int index = int.Parse(tokens[0]);
349          double value = double.Parse(tokens[1]);
350
351          demands[index] = value;
352        } else {
353          demands[0] = 0;
354        }
355      }
356    }
357  }
358}
Note: See TracBrowser for help on using the repository browser.