36void CarpParser::Initialize() {
40 number_of_edges_with_servicing_ = 0;
41 number_of_edges_without_servicing_ = 0;
42 total_servicing_cost_ = 0;
44 traversing_costs_.clear();
45 servicing_demands_.clear();
53 return ParseFile(file_name);
56bool CarpParser::ParseFile(absl::string_view file_name) {
57 static auto section_headers = std::array<const char*, 12>({
65 "TIPO_COSTES_ARISTAS",
68 "LISTA_ARISTAS_NOREQ",
72 for (
const std::string& line :
74 const std::vector<std::string> words =
75 absl::StrSplit(line, absl::ByAnyChar(
" :\t"), absl::SkipEmpty());
77 if (absl::c_linear_search(section_headers, words[0])) {
79 if (words[0] ==
"LISTA_ARISTAS_REQ") {
82 section_ = ARCS_WITH_SERVICING;
83 }
else if (words[0] ==
"LISTA_ARISTAS_NOREQ") {
85 section_ = ARCS_WITHOUT_SERVICING;
87 if (!ParseMetadataLine(words)) {
88 LOG(ERROR) <<
"Error when parsing the following metadata line: "
96 case ARCS_WITH_SERVICING:
97 if (!ParseEdge(line,
true)) {
98 LOG(ERROR) <<
"Could not parse line in LISTA_ARISTAS_REQ: " << line;
102 case ARCS_WITHOUT_SERVICING:
103 if (!ParseEdge(line,
false)) {
104 LOG(ERROR) <<
"Could not parse line in LISTA_ARISTAS_NOREQ: "
110 LOG(ERROR) <<
"Could not parse line outside edge lists: " << line;
116 return !servicing_demands_.empty();
120std::optional<int64_t> ParseNodeIndex(std::string_view text);
123bool CarpParser::ParseMetadataLine(absl::Span<const std::string> words) {
124 if (words[0] ==
"NOMBRE") {
125 name_ = absl::StrJoin(words.begin() + 1, words.end(),
" ");
126 }
else if (words[0] ==
"COMENTARIO") {
127 comment_ = absl::StrJoin(words.begin() + 1, words.end(),
" ");
128 }
else if (words[0] ==
"VERTICES") {
130 if (number_of_nodes_ <= 0) {
131 LOG(ERROR) <<
"Error when parsing the number of nodes: " << words[1];
134 }
else if (words[0] ==
"ARISTAS_REQ") {
135 number_of_edges_with_servicing_ =
137 if (number_of_edges_with_servicing_ <= 0) {
138 LOG(ERROR) <<
"Error when parsing the number of edges with servicing: "
142 }
else if (words[0] ==
"ARISTAS_NOREQ") {
143 number_of_edges_without_servicing_ =
145 if (number_of_edges_without_servicing_ < 0) {
148 LOG(ERROR) <<
"Error when parsing the number of edges without servicing: "
152 }
else if (words[0] ==
"VEHICULOS") {
154 if (n_vehicles_ <= 0) {
155 LOG(ERROR) <<
"Error when parsing the number of vehicles: " << words[1];
158 }
else if (words[0] ==
"CAPACIDAD") {
160 if (capacity_ <= 0) {
161 LOG(ERROR) <<
"Error when parsing the capacity: " << words[1];
164 }
else if (words[0] ==
"TIPO_COSTES_ARISTAS") {
165 if (words[1] !=
"EXPLICITOS") {
167 LOG(ERROR) <<
"Value of TIPO_COSTES_ARISTAS is unexpected, only "
168 "EXPLICITOS is supported, but "
169 << words[1] <<
" was found";
172 }
else if (words[0] ==
"COSTE_TOTAL_REQ") {
174 if (total_servicing_cost_ == -1) {
175 LOG(ERROR) <<
"Error when parsing the total servicing cost: " << words[1];
178 }
else if (words[0] ==
"DEPOSITO") {
180 const std::optional<int64_t>
depot = ParseNodeIndex(words[1]);
181 if (!
depot.has_value()) {
182 LOG(ERROR) <<
"Error when parsing the depot: " << words[1];
185 depot_ =
depot.value();
190bool CarpParser::ParseEdge(std::string_view line,
bool with_servicing) {
191 const std::vector<std::string> words =
192 absl::StrSplit(line, absl::ByAnyChar(
" :\t(),"), absl::SkipEmpty());
195 std::optional<int64_t> opt_head = ParseNodeIndex(words[0]);
196 if (!opt_head.has_value()) {
197 LOG(ERROR) <<
"Error when parsing the head node: " << words[0];
200 const int64_t head = opt_head.value();
202 std::optional<int64_t> opt_tail = ParseNodeIndex(words[1]);
203 if (!opt_tail.has_value()) {
204 LOG(ERROR) <<
"Error when parsing the tail node: " << words[1];
207 const int64_t tail = opt_tail.value();
210 LOG(ERROR) <<
"The head and tail nodes are identical: " << line;
215 if (words[2] !=
"coste") {
216 LOG(ERROR) <<
"Unexpected keyword: " << words[2];
220 traversing_costs_[{tail, head}] = cost;
223 if (with_servicing) {
224 if (words[4] !=
"demanda") {
225 LOG(ERROR) <<
"Unexpected keyword: " << words[2];
229 servicing_demands_[{tail, head}] = servicing;
233 const int64_t next_id = (with_servicing) ? 6 : 4;
234 if (words.size() > next_id) {
235 LOG(ERROR) <<
"Extraneous elements in line, starting with: "
244std::optional<int64_t> ParseNodeIndex(std::string_view text) {
247 LOG(ERROR) <<
"Could not parse node index: " << text;