| 32 | } // namespace |
| 33 | |
| 34 | Trip::Trip(ProblemData const &data, |
| 35 | Visits visits, |
| 36 | size_t vehicleType, |
| 37 | std::optional<size_t> startDepot, |
| 38 | std::optional<size_t> endDepot) |
| 39 | : visits_(std::move(visits)), |
| 40 | delivery_(data.numLoadDimensions(), 0), |
| 41 | pickup_(data.numLoadDimensions(), 0), |
| 42 | load_(data.numLoadDimensions(), 0), |
| 43 | excessLoad_(data.numLoadDimensions(), 0), |
| 44 | vehicleType_(vehicleType) |
| 45 | { |
| 46 | auto const &vehData = data.vehicleType(vehicleType_); |
| 47 | startDepot_ = startDepot.value_or(vehData.startDepot); |
| 48 | endDepot_ = endDepot.value_or(vehData.endDepot); |
| 49 | |
| 50 | if (!canStartAt(vehData, startDepot_)) |
| 51 | throw std::invalid_argument("Vehicle cannot start from start_depot."); |
| 52 | |
| 53 | if (!canEndAt(vehData, endDepot_)) |
| 54 | throw std::invalid_argument("Vehicle cannot end at end_depot."); |
| 55 | |
| 56 | for (auto const client : visits_) |
| 57 | if (client < data.numDepots() || client >= data.numLocations()) |
| 58 | { |
| 59 | std::ostringstream msg; |
| 60 | msg << "Client " << client << " is not understood."; |
| 61 | throw std::invalid_argument(msg.str()); |
| 62 | } |
| 63 | |
| 64 | auto const &distances = data.distanceMatrix(vehData.profile); |
| 65 | auto const &durations = data.durationMatrix(vehData.profile); |
| 66 | |
| 67 | ProblemData::Depot const &depot = data.location(startDepot_); |
| 68 | service_ += depot.serviceDuration; |
| 69 | |
| 70 | for (size_t prevClient = startDepot_; auto const client : visits_) |
| 71 | { |
| 72 | distance_ += distances(prevClient, client); |
| 73 | travel_ += durations(prevClient, client); |
| 74 | |
| 75 | ProblemData::Client const &clientData = data.location(client); |
| 76 | |
| 77 | service_ += clientData.serviceDuration; |
| 78 | release_ = std::max(release_, clientData.releaseTime); |
| 79 | prizes_ += clientData.prize; |
| 80 | |
| 81 | centroid_.first += static_cast<double>(clientData.x) / size(); |
| 82 | centroid_.second += static_cast<double>(clientData.y) / size(); |
| 83 | |
| 84 | prevClient = client; |
| 85 | } |
| 86 | |
| 87 | auto const last = empty() ? startDepot_ : visits_.back(); |
| 88 | distance_ += distances(last, endDepot_); |
| 89 | travel_ += durations(last, endDepot_); |
| 90 | |
| 91 | for (size_t dim = 0; dim != data.numLoadDimensions(); ++dim) |