OR-Tools  9.6
carp_parser.h
Go to the documentation of this file.
1 // Copyright 2010-2022 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 parser for CARPLIB instances. The base files are available online, as well
15 // as a description of the (Spanish-based) format:
16 // https://www.uv.es/belengue/carp.html ("CARPLIB")
17 // https://www.uv.es/~belengue/carp/READ_ME
18 //
19 // The goal is to find routes starting and ending at a depot which visit a
20 // set of arcs (whereas a VRP visits nodes). The objective is to minimize the
21 // total cost, which is due to either servicing an edge (i.e. performing the
22 // required action) or traversing an edge (to get to another point in space).
23 // Not all arcs/edges in the graph must be serviced.
24 //
25 // By this formulation, the total cost of servicing is known in advance.
26 // All vehicles start at the same node, the depot, having index 1.
27 // Servicing an edge requires resources, vehicles have a limited capacity. All
28 // vehicles have the same capacity.
29 //
30 // The format of the data is the following:
31 //
32 // NOMBRE : <INSTANCE-NAME>
33 // COMENTARIO : <ARBITRARY-COMMENT>
34 // VERTICES : <NUMBER-OF-NODES, int>
35 // ARISTAS_REQ : <NUMBER-OF-EDGES-WITH-NONZERO-SERVICING, int>
36 // ARISTAS_NOREQ : <NUMBER-OF-EDGES-WITH-ZERO-SERVICING, int>
37 // VEHICULOS : <NUMBER-OF-VEHICLES, int>
38 // CAPACIDAD : <CAPACITY-OF-EACH-VEHICLE, int>
39 // TIPO_COSTES_ARISTAS : EXPLICITOS
40 // COSTE_TOTAL_REQ : <TOTAL-SERVICING-COST>
41 // LISTA_ARISTAS_REQ :
42 // ( <HEAD-NODE-OF-EDGE, int>, <TAIL-NODE-OF-EDGE, int> )
43 // coste <TRAVERSING-COST, int> demanda <SERVICING, int>
44 // <repeated, one edge per line>
45 // LISTA_ARISTAS_NOREQ :
46 // ( <HEAD-NODE-OF-EDGE, int>, <TAIL-NODE-OF-EDGE, int> )
47 // coste <TRAVERSING-COST, int>
48 // <repeated, one edge per line>
49 // DEPOSITO : 1
50 //
51 // While the file format is defined with 1-based indexing, the output of the
52 // parser is always 0-based. Users of this parser should never see any 1-based
53 // index; only 0-based index should be used to query values.
54 
55 #ifndef OR_TOOLS_ROUTING_CARP_PARSER_H_
56 #define OR_TOOLS_ROUTING_CARP_PARSER_H_
57 
58 #include <algorithm>
59 #include <string>
60 #include <string_view>
61 #include <vector>
62 
64 #include "ortools/base/logging.h"
66 
67 namespace operations_research {
68 class CarpParser {
69  public:
70  CarpParser();
71 
72 #ifndef SWIG
73  CarpParser(const CarpParser&) = delete;
74  const CarpParser& operator=(const CarpParser&) = delete;
75 #endif
76 
77  // Loads instance from a file into this parser object.
78  bool LoadFile(const std::string& file_name);
79 
80  // Returns the name of the instance being solved.
81  const std::string& name() const { return name_; }
82  // Returns the comment of the instance being solved, typically an upper bound.
83  const std::string& comment() const { return comment_; }
84  // Returns the index of the depot.
85  int64_t depot() const { return depot_; }
86  // Returns the number of nodes in the current routing problem.
87  int64_t NumberOfNodes() const { return number_of_nodes_; }
88  // Returns the number of edges in the current routing problem, with or
89  // without servicing required.
90  int64_t NumberOfEdges() const {
92  }
93  // Returns the number of edges in the current routing problem that require
94  // servicing.
95  int64_t NumberOfEdgesWithServicing() const {
96  return number_of_edges_with_servicing_;
97  }
98  // Returns the number of edges in the current routing problem that do not
99  // require servicing.
101  return number_of_edges_without_servicing_;
102  }
103  // Returns the total servicing cost for all arcs.
104  int64_t TotalServicingCost() const { return total_servicing_cost_; }
105  // Returns the servicing of the edges in the current routing problem.
107  return servicing_demands_;
108  }
109  // Returns the traversing costs of the edges in the current routing problem.
111  return traversing_costs_;
112  }
113  // Returns the maximum number of vehicles to use.
114  int64_t NumberOfVehicles() const { return n_vehicles_; }
115  // Returns the capacity of the vehicles.
116  int64_t capacity() const { return capacity_; }
117 
118  // Returns the traversing cost for an edge. All edges are supposed to have
119  // a traversing cost.
120  int64_t GetTraversingCost(Edge edge) const {
121  CHECK(traversing_costs_.contains(edge))
122  << "Unknown edge: " << edge.tail() << " - " << edge.head();
123  return traversing_costs_.at(edge);
124  }
125  int64_t GetTraversingCost(int64_t tail, int64_t head) const {
126  return GetTraversingCost({tail, head});
127  }
128 
129  // Checks whether this edge requires servicing.
130  int64_t HasServicingNeed(Edge edge) const {
131  return servicing_demands_.contains(edge);
132  }
133  int64_t HasServicingNeed(int64_t tail, int64_t head) const {
134  return HasServicingNeed({tail, head});
135  }
136 
137  // Returns the servicing for an edge. Only a subset of edges have a servicing
138  // need.
139  int64_t GetServicing(Edge edge) const {
140  CHECK(HasServicingNeed(edge))
141  << "Unknown edge: " << edge.tail() << " - " << edge.head();
142  return servicing_demands_.at(edge);
143  }
144  int64_t GetServicing(int64_t tail, int64_t head) const {
145  return GetServicing({tail, head});
146  }
147 
148  private:
149  // Parsing.
150  enum Section {
151  METADATA,
152  ARCS_WITH_SERVICING,
153  ARCS_WITHOUT_SERVICING,
154  UNDEFINED_SECTION
155  };
156 
157  void Initialize();
158  bool ParseFile(const std::string& file_name);
159  bool ParseMetadataLine(const std::vector<std::string>& words);
160  bool ParseEdge(std::string_view line, bool with_servicing);
161 
162  // Parsing data.
163  Section section_;
164 
165  // Instance data:
166  // - metadata
167  std::string name_;
168  std::string comment_;
169  int64_t number_of_nodes_;
170  int64_t number_of_edges_with_servicing_;
171  int64_t number_of_edges_without_servicing_;
172  int64_t total_servicing_cost_;
173  int64_t depot_;
174  // - graph costs and servicing demands. Keep track of the order of the
175  // demands: the output format requires to use the servicing-demands IDs,
176  // which are indices when iterating over this map.
177  gtl::linked_hash_map<Edge, int64_t> traversing_costs_;
178  gtl::linked_hash_map<Edge, int64_t> servicing_demands_;
179  // - vehicles
180  int64_t n_vehicles_;
181  int64_t capacity_;
182 };
183 } // namespace operations_research
184 
185 #endif // OR_TOOLS_ROUTING_CARP_PARSER_H_
int64_t GetServicing(Edge edge) const
Definition: carp_parser.h:139
int64_t NumberOfEdgesWithoutServicing() const
Definition: carp_parser.h:100
bool LoadFile(const std::string &file_name)
Definition: carp_parser.cc:46
int64_t HasServicingNeed(int64_t tail, int64_t head) const
Definition: carp_parser.h:133
const CarpParser & operator=(const CarpParser &)=delete
int64_t GetTraversingCost(Edge edge) const
Definition: carp_parser.h:120
int64_t NumberOfVehicles() const
Definition: carp_parser.h:114
int64_t GetServicing(int64_t tail, int64_t head) const
Definition: carp_parser.h:144
int64_t NumberOfEdgesWithServicing() const
Definition: carp_parser.h:95
CarpParser(const CarpParser &)=delete
int64_t GetTraversingCost(int64_t tail, int64_t head) const
Definition: carp_parser.h:125
int64_t TotalServicingCost() const
Definition: carp_parser.h:104
const gtl::linked_hash_map< Edge, int64_t > & servicing_demands() const
Definition: carp_parser.h:106
int64_t HasServicingNeed(Edge edge) const
Definition: carp_parser.h:130
const std::string & name() const
Definition: carp_parser.h:81
const gtl::linked_hash_map< Edge, int64_t > & traversing_costs() const
Definition: carp_parser.h:110
const std::string & comment() const
Definition: carp_parser.h:83
int64_t head() const
Definition: simple_graph.h:38
int64_t tail() const
Definition: simple_graph.h:37
Collection of objects used to extend the Constraint Solver library.
int line
Definition: parse_proto.cc:31
int64_t tail
int64_t head