read() helper that builds a ``ProblemData`` object from the instance attributes of the given parser.
| 340 | |
| 341 | |
| 342 | class _ProblemDataBuilder: |
| 343 | """ |
| 344 | read() helper that builds a ``ProblemData`` object from the instance |
| 345 | attributes of the given parser. |
| 346 | """ |
| 347 | |
| 348 | def __init__(self, parser: _InstanceParser): |
| 349 | self.parser = parser |
| 350 | |
| 351 | def data(self) -> ProblemData: |
| 352 | clients = self._clients() |
| 353 | depots = self._depots() |
| 354 | vehicle_types = self._vehicle_types() |
| 355 | distance_matrices = self._distance_matrices() |
| 356 | groups = self._groups() |
| 357 | |
| 358 | return ProblemData( |
| 359 | clients=clients, |
| 360 | depots=depots, |
| 361 | vehicle_types=vehicle_types, |
| 362 | distance_matrices=distance_matrices, |
| 363 | # VRPLIB instances typically do not have a duration data field, and |
| 364 | # instead assume duration == distance. |
| 365 | duration_matrices=distance_matrices, |
| 366 | groups=groups, |
| 367 | ) |
| 368 | |
| 369 | def _depots(self) -> list[Depot]: |
| 370 | num_depots = self.parser.num_depots |
| 371 | depot_idcs = self.parser.depot_idcs() |
| 372 | |
| 373 | contiguous_lower_idcs = np.arange(num_depots) |
| 374 | if num_depots == 0 or (depot_idcs != contiguous_lower_idcs).any(): |
| 375 | msg = """ |
| 376 | Source file should contain at least one depot in the contiguous |
| 377 | lower indices, starting from 1. |
| 378 | """ |
| 379 | raise ValueError(msg) |
| 380 | |
| 381 | coords = self.parser.coords() |
| 382 | return [ |
| 383 | Depot(x=coords[idx][0], y=coords[idx][1]) |
| 384 | for idx in range(num_depots) |
| 385 | ] |
| 386 | |
| 387 | def _clients(self) -> list[Client]: |
| 388 | groups = self.parser.mutually_exclusive_groups() |
| 389 | num_locs = self.parser.num_locations |
| 390 | |
| 391 | idx2group: list[int | None] = [None for _ in range(num_locs)] |
| 392 | for group, members in enumerate(groups): |
| 393 | for client in members: |
| 394 | idx2group[client] = group |
| 395 | |
| 396 | coords = self.parser.coords() |
| 397 | demands = self.parser.demands() |
| 398 | backhauls = self.parser.backhauls() |
| 399 | service_duration = self.parser.service_times() |