33void CarpParser::Initialize() {
37 number_of_edges_with_servicing_ = 0;
38 number_of_edges_without_servicing_ = 0;
39 total_servicing_cost_ = 0;
41 traversing_costs_.clear();
42 servicing_demands_.clear();
50 return ParseFile(file_name);
53bool CarpParser::ParseFile(absl::string_view file_name) {
54 static auto section_headers = std::array<const char*, 12>({
62 "TIPO_COSTES_ARISTAS",
65 "LISTA_ARISTAS_NOREQ",
69 for (
const std::string& line :
71 const std::vector<std::string> words =
72 absl::StrSplit(line, absl::ByAnyChar(
" :\t"), absl::SkipEmpty());
74 if (absl::c_linear_search(section_headers, words[0])) {
76 if (words[0] ==
"LISTA_ARISTAS_REQ") {
79 section_ = ARCS_WITH_SERVICING;
80 }
else if (words[0] ==
"LISTA_ARISTAS_NOREQ") {
82 section_ = ARCS_WITHOUT_SERVICING;
84 if (!ParseMetadataLine(words)) {
85 LOG(ERROR) <<
"Error when parsing the following metadata line: "
93 case ARCS_WITH_SERVICING:
94 if (!ParseEdge(line,
true)) {
95 LOG(ERROR) <<
"Could not parse line in LISTA_ARISTAS_REQ: " << line;
99 case ARCS_WITHOUT_SERVICING:
100 if (!ParseEdge(line,
false)) {
101 LOG(ERROR) <<
"Could not parse line in LISTA_ARISTAS_NOREQ: "
107 LOG(ERROR) <<
"Could not parse line outside edge lists: " << line;
113 return !servicing_demands_.empty();
117std::optional<int64_t> ParseNodeIndex(std::string_view text);
120bool CarpParser::ParseMetadataLine(absl::Span<const std::string> words) {
121 if (words[0] ==
"NOMBRE") {
122 name_ = absl::StrJoin(words.begin() + 1, words.end(),
" ");
123 }
else if (words[0] ==
"COMENTARIO") {
124 comment_ = absl::StrJoin(words.begin() + 1, words.end(),
" ");
125 }
else if (words[0] ==
"VERTICES") {
127 if (number_of_nodes_ <= 0) {
128 LOG(ERROR) <<
"Error when parsing the number of nodes: " << words[1];
131 }
else if (words[0] ==
"ARISTAS_REQ") {
132 number_of_edges_with_servicing_ =
134 if (number_of_edges_with_servicing_ <= 0) {
135 LOG(ERROR) <<
"Error when parsing the number of edges with servicing: "
139 }
else if (words[0] ==
"ARISTAS_NOREQ") {
140 number_of_edges_without_servicing_ =
142 if (number_of_edges_without_servicing_ < 0) {
145 LOG(ERROR) <<
"Error when parsing the number of edges without servicing: "
149 }
else if (words[0] ==
"VEHICULOS") {
151 if (n_vehicles_ <= 0) {
152 LOG(ERROR) <<
"Error when parsing the number of vehicles: " << words[1];
155 }
else if (words[0] ==
"CAPACIDAD") {
157 if (capacity_ <= 0) {
158 LOG(ERROR) <<
"Error when parsing the capacity: " << words[1];
161 }
else if (words[0] ==
"TIPO_COSTES_ARISTAS") {
162 if (words[1] !=
"EXPLICITOS") {
164 LOG(ERROR) <<
"Value of TIPO_COSTES_ARISTAS is unexpected, only "
165 "EXPLICITOS is supported, but "
166 << words[1] <<
" was found";
169 }
else if (words[0] ==
"COSTE_TOTAL_REQ") {
171 if (total_servicing_cost_ == -1) {
172 LOG(ERROR) <<
"Error when parsing the total servicing cost: " << words[1];
175 }
else if (words[0] ==
"DEPOSITO") {
177 const std::optional<int64_t>
depot = ParseNodeIndex(words[1]);
178 if (!
depot.has_value()) {
179 LOG(ERROR) <<
"Error when parsing the depot: " << words[1];
182 depot_ =
depot.value();
187bool CarpParser::ParseEdge(std::string_view line,
bool with_servicing) {
188 const std::vector<std::string> words =
189 absl::StrSplit(line, absl::ByAnyChar(
" :\t(),"), absl::SkipEmpty());
192 std::optional<int64_t> opt_head = ParseNodeIndex(words[0]);
193 if (!opt_head.has_value()) {
194 LOG(ERROR) <<
"Error when parsing the head node: " << words[0];
197 const int64_t head = opt_head.value();
199 std::optional<int64_t> opt_tail = ParseNodeIndex(words[1]);
200 if (!opt_tail.has_value()) {
201 LOG(ERROR) <<
"Error when parsing the tail node: " << words[1];
204 const int64_t tail = opt_tail.value();
207 LOG(ERROR) <<
"The head and tail nodes are identical: " << line;
212 if (words[2] !=
"coste") {
213 LOG(ERROR) <<
"Unexpected keyword: " << words[2];
217 traversing_costs_[{tail, head}] = cost;
220 if (with_servicing) {
221 if (words[4] !=
"demanda") {
222 LOG(ERROR) <<
"Unexpected keyword: " << words[2];
226 servicing_demands_[{tail, head}] = servicing;
230 const int64_t next_id = (with_servicing) ? 6 : 4;
231 if (words.size() > next_id) {
232 LOG(ERROR) <<
"Extraneous elements in line, starting with: "
241std::optional<int64_t> ParseNodeIndex(std::string_view text) {
244 LOG(ERROR) <<
"Could not parse node index: " << text;