Google OR-Tools v9.15
a fast and portable software suite for combinatorial optimization
Loading...
Searching...
No Matches
tsplib_parser.h
Go to the documentation of this file.
1// Copyright 2010-2025 Google LLC
2// Licensed under the Apache License, Version 2.0 (the "License");
3// you may not use this file except in compliance with the License.
4// You may obtain a copy of the License at
5//
6// http://www.apache.org/licenses/LICENSE-2.0
7//
8// Unless required by applicable law or agreed to in writing, software
9// distributed under the License is distributed on an "AS IS" BASIS,
10// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
11// See the License for the specific language governing permissions and
12// limitations under the License.
13
14// A TSPLIB parser. The TSPLIB is a library containing Traveling
15// Salesman Problems and other vehicle routing problems.
16// Limitations:
17// - only TSP and CVRP files are currently supported.
18// - XRAY1, XRAY2 and SPECIAL edge weight types are not supported.
19//
20// Takes as input a data file, potentially gzipped. The data must
21// follow the TSPLIB95 format (described at
22// http://www.iwr.uni-heidelberg.de/groups/comopt/software/TSPLIB95/DOC.PS).
23
24#ifndef ORTOOLS_ROUTING_PARSERS_TSPLIB_PARSER_H_
25#define ORTOOLS_ROUTING_PARSERS_TSPLIB_PARSER_H_
26
27#include <cstdint>
28#include <set>
29#include <string>
30#include <utility>
31#include <vector>
32
33#include "absl/container/flat_hash_map.h"
34#include "absl/status/status.h"
35#include "absl/status/statusor.h"
36#include "absl/strings/string_view.h"
37#include "absl/types/span.h"
39
41
42class TspLibParser final {
43 public:
44 // Routing model types (cf. the link above for a description).
46
48 // Loads and parses a routing problem from a given file.
49 absl::Status LoadFile(absl::string_view file_name);
50 // Returns the number of nodes in the routing problem stored in a given file.
51 absl::StatusOr<int> SizeFromFile(absl::string_view file_name) const;
52 // Returns a function returning edge weights between nodes.
53 EdgeWeights GetEdgeWeights() const { return distance_function_; }
54 // Returns the index of the depot.
55 int depot() const { return depot_; }
56 // Returns the number of nodes in the current routing problem.
57 int size() const { return size_; }
58 // Returns the type of the current routing problem.
59 Types type() const { return type_; }
60 // Returns the coordinates of the nodes in the current routing problem (if
61 // they exist).
62 const std::vector<Coordinates3<double>>& coordinates() const {
63 return coords_;
64 }
65 // Returns the capacity of the vehicles in the current routing problem.
66 int64_t capacity() const { return capacity_; }
67 // Returns the maximal distance vehicles can travel.
68 int64_t max_distance() const { return max_distance_; }
69 // Returns the demands (or quantities picked up) at each node.
70 const std::vector<int64_t>& demands() const { return demands_; }
71 // Returns the pairs of nodes corresponding to forced edges (second node is
72 // directly after the first).
73 std::set<std::pair<int, int>> fixed_edges() const { return fixed_edges_; }
74 // Returns edges of the graph on which Hamiltonian cycles need to be built.
75 // Edges are represented as adjacency lists for each node.
76 const std::vector<std::vector<int>>& edges() const { return edges_; }
77 // Returns the name of the current routing model.
78 const std::string& name() const { return name_; }
79 // Returns the comments attached to the data.
80 const std::string& comments() const { return comments_; }
81 // Build a tour output in TSPLIB95 format from a vector of routes, a route
82 // being a sequence of node indices.
83 std::string BuildTourFromRoutes(
84 absl::Span<const std::vector<int>> routes) const;
85
86 private:
87 enum Sections {
88 NAME,
89 TYPE,
90 COMMENT,
91 DIMENSION,
92 DISTANCE,
93 CAPACITY,
94 EDGE_DATA_FORMAT,
95 EDGE_DATA_SECTION,
96 EDGE_WEIGHT_TYPE,
97 EDGE_WEIGHT_FORMAT,
98 EDGE_WEIGHT_SECTION,
99 FIXED_EDGES_SECTION,
100 NODE_COORD_TYPE,
101 DISPLAY_DATA_TYPE,
102 DISPLAY_DATA_SECTION,
103 NODE_COORD_SECTION,
104 DEPOT_SECTION,
105 DEMAND_SECTION,
106 END_OF_FILE,
107 UNDEFINED_SECTION
108 };
109 enum EdgeDataFormat { EDGE_LIST, ADJ_LIST };
110 enum EdgeWeightTypes {
111 EXPLICIT,
112 EUC_2D,
113 EUC_3D,
114 MAX_2D,
115 MAX_3D,
116 MAN_2D,
117 MAN_3D,
118 CEIL_2D,
119 GEO,
120 GEOM,
121 ATT,
122 XRAY1,
123 XRAY2,
124 SPECIAL,
125 UNDEFINED_EDGE_WEIGHT_TYPE
126 };
127 enum EdgeWeightFormats {
128 FUNCTION,
129 FULL_MATRIX,
130 UPPER_ROW,
131 LOWER_ROW,
132 UPPER_DIAG_ROW,
133 LOWER_DIAG_ROW,
134 UPPER_COL,
135 LOWER_COL,
136 UPPER_DIAG_COL,
137 LOWER_DIAG_COL,
138 UNDEFINED_EDGE_WEIGHT_FORMAT
139 };
140
141#ifndef SWIG
142 TspLibParser(const TspLibParser&) = delete;
143 void operator=(const TspLibParser&) = delete;
144#endif
145
146 void ParseExplicitFullMatrix(absl::Span<const std::string> words);
147 void ParseExplicitUpperRow(absl::Span<const std::string> words);
148 void ParseExplicitLowerRow(absl::Span<const std::string> words);
149 void ParseExplicitUpperDiagRow(absl::Span<const std::string> words);
150 void ParseExplicitLowerDiagRow(absl::Span<const std::string> words);
151 void ParseNodeCoord(absl::Span<const std::string> words);
152 void SetUpEdgeWeightSection();
153 void FinalizeEdgeWeights();
154 bool ParseSections(absl::Span<const std::string> words);
155 void ProcessNewLine(const std::string& line);
156 void SetExplicitCost(int from, int to, int64_t cost) {
157 if (explicit_costs_.size() != size_ * size_) {
158 explicit_costs_.resize(size_ * size_, 0);
159 }
160 explicit_costs_[from * size_ + to] = cost;
161 }
162
163 // Model data
164 int64_t size_;
165 int64_t capacity_;
166 int64_t max_distance_;
167 std::vector<int64_t> demands_;
168 EdgeWeights distance_function_;
169 std::vector<int64_t> explicit_costs_;
170 std::set<std::pair<int, int>> fixed_edges_;
171 int depot_;
172 std::vector<std::vector<int>> edges_;
173
174 // Parsing data
175 static const absl::flat_hash_map<std::string, Sections>* const kSections;
176 Sections section_;
177 static const absl::flat_hash_map<std::string, Types>* const kTypes;
178 Types type_;
179 static const absl::flat_hash_map<std::string, EdgeDataFormat>* const
180 kEdgeDataFormats;
181 EdgeDataFormat edge_data_format_;
182 static const absl::flat_hash_map<std::string, EdgeWeightTypes>* const
183 kEdgeWeightTypes;
184 EdgeWeightTypes edge_weight_type_;
185 static const absl::flat_hash_map<std::string, EdgeWeightFormats>* const
186 kEdgeWeightFormats;
187 EdgeWeightFormats edge_weight_format_;
188 int edge_row_;
189 int edge_column_;
190 std::vector<Coordinates3<double>> coords_;
191 std::string name_;
192 std::string comments_;
193 int64_t to_read_;
194 bool valid_section_found_ = false;
195};
196
197// Class parsing tour (solution) data in TSLIB95 format.
198
199class TspLibTourParser final {
200 public:
202 // Loads and parses a given tour file.
203 absl::Status LoadFile(absl::string_view file_name);
204 // Returns a vector corresponding to the sequence of nodes of the tour.
205 const std::vector<int>& tour() const { return tour_; }
206 // Returns the size of the tour.
207 int size() const { return size_; }
208 // Returns the comments attached to the data.
209 const std::string& comments() const { return comments_; }
210
211 private:
212 enum Sections {
213 NAME,
214 TYPE,
215 COMMENT,
216 DIMENSION,
217 TOUR_SECTION,
218 END_OF_FILE,
219 UNDEFINED_SECTION
220 };
221
222#ifndef SWIG
223 TspLibTourParser(const TspLibTourParser&) = delete;
224 void operator=(const TspLibTourParser&) = delete;
225#endif
226
227 void ProcessNewLine(const std::string& line);
228
229 static const absl::flat_hash_map<std::string, Sections>* const kSections;
230 Sections section_;
231 std::string comments_;
232 int64_t size_;
233 std::vector<int> tour_;
234};
235
236// Class parsing tours (solution) data in CVRPlib format.
237
238class CVRPToursParser final {
239 public:
241 // Loads and parses a given tours file.
242 absl::Status LoadFile(absl::string_view file_name);
243 // Returns a vector corresponding to the sequence of nodes of tours.
244 const std::vector<std::vector<int>>& tours() const { return tours_; }
245 int64_t cost() const { return cost_; }
246
247 private:
248 void ProcessNewLine(const std::string& line);
249
250 std::vector<std::vector<int>> tours_;
251 int64_t cost_;
252};
253} // namespace operations_research::routing
254
255#endif // ORTOOLS_ROUTING_PARSERS_TSPLIB_PARSER_H_
const std::vector< std::vector< int > > & tours() const
absl::Status LoadFile(absl::string_view file_name)
const std::vector< Coordinates3< double > > & coordinates() const
std::set< std::pair< int, int > > fixed_edges() const
std::string BuildTourFromRoutes(absl::Span< const std::vector< int > > routes) const
const std::vector< int64_t > & demands() const
const std::string & comments() const
absl::StatusOr< int > SizeFromFile(absl::string_view file_name) const
const std::vector< std::vector< int > > & edges() const
absl::Status LoadFile(absl::string_view file_name)
absl::Status LoadFile(absl::string_view file_name)
const std::vector< int > & tour() const
std::function< int64_t(int, int)> EdgeWeights
trees with all degrees equal to