Free cookie consent management tool by TermsFeed Policy Generator

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

Last change on this file since 12147 was 7887, checked in by svonolfe, 13 years ago

Added support for the DCVRP in the Golden format (#1177)

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