diff --git a/src/lns/constraints/capacity/capacity_constraint.h b/src/lns/constraints/capacity/capacity_constraint.h index c1a668c2703c483768f734d2fa140a02a5a67bea..1ae640370102d3c9bf2684ed2ab84cc45fd402b3 100644 --- a/src/lns/constraints/capacity/capacity_constraint.h +++ b/src/lns/constraints/capacity/capacity_constraint.h @@ -64,5 +64,5 @@ public: */ void applyModif(Pair const &pair, int routeIndex, int PickupPosition, int DeliveryPosition, bool addPair); - void print() const; + void print() const override; }; \ No newline at end of file diff --git a/src/lns/constraints/constraint.h b/src/lns/constraints/constraint.h index 6e27f9fc680095048b7788239c1584bc2505f23b..deeaf164d9f8297b96ab69091b84bf8fb5c732d7 100644 --- a/src/lns/constraints/constraint.h +++ b/src/lns/constraints/constraint.h @@ -99,4 +99,6 @@ public: * Defaults to no op */ virtual void endOfDestructionCallback() {} + + virtual void print() const = 0; }; \ No newline at end of file diff --git a/src/lns/constraints/time_window/time_window_constraint.cpp b/src/lns/constraints/time_window/time_window_constraint.cpp index 5ad86706f1b494eba943683fcd9ab15251ac7ebc..7421d502024584f65deca9d67e8d4459b6382a59 100644 --- a/src/lns/constraints/time_window/time_window_constraint.cpp +++ b/src/lns/constraints/time_window/time_window_constraint.cpp @@ -8,32 +8,33 @@ #include "lns/modification/route/remove_route.h" #include "lns/solution/solution.h" - -TimeWindowConstraint::TimeWindowConstraint(const Solution& solution) : Constraint(solution) +TimeWindowConstraint::TimeWindowConstraint(Solution const &solution) : Constraint(solution) { allRouteReachTimes.resize(getSolution().getRoutes().size()); } - -TimeWindowConstraint::~TimeWindowConstraint() +TimeWindowConstraint::~TimeWindowConstraint() { allRouteReachTimes.clear(); } -std::unique_ptr<Constraint> TimeWindowConstraint::clone(Solution const &newOwningSolution) const { +std::unique_ptr<Constraint> TimeWindowConstraint::clone(Solution const &newOwningSolution) const +{ std::unique_ptr<TimeWindowConstraint> clonePtr = std::make_unique<TimeWindowConstraint>(newOwningSolution); clonePtr->allRouteReachTimes = allRouteReachTimes; return clonePtr; } -void TimeWindowConstraint::computeReachTimes(const PDPTWData& data, const std::vector<int> & routeIDs, ReachTimeVector & reachTimes) const +void TimeWindowConstraint::computeReachTimes(PDPTWData const &data, std::vector<int> const &routeIDs, + ReachTimeVector &reachTimes) const { // Adjust the size of reachTimes vector reachTimes.resize(routeIDs.size(), 0); // Time to the first location reachTimes.at(0) = data.getDepot().getTimeWindow().getStart() + data::TravelTime(data, 0, routeIDs.at(0)); // Compute other reachTimes (max between arrival and start of the time window + previous service time + travel time) - for (int i = 1; i < routeIDs.size(); ++i) { + for (int i = 1; i < routeIDs.size(); ++i) + { TimeInteger travelTime = data::TravelTime(data, routeIDs.at(i - 1), routeIDs.at(i)); // locations are indexed from 0 to n-1, TimeInteger serviceTime = data.getLocation(routeIDs.at(i - 1)).getServiceDuration(); @@ -47,7 +48,7 @@ void TimeWindowConstraint::initReachTimes() { allRouteReachTimes = std::vector<ReachTimeVector>(); int i = 0; - for (const Route& route : getSolution().getRoutes()) + for (Route const &route: getSolution().getRoutes()) { // init and calculate reach time value allRouteReachTimes.emplace_back(); @@ -56,25 +57,24 @@ void TimeWindowConstraint::initReachTimes() } } - - // Copie le vecteur de reach time de la route concernée // Insère les positions pickup/delivery // refait l'ordo sur le nouveau vecteur -bool TimeWindowConstraint::checkInsertion(const PDPTWData& data, const Pair & pair, int routeIndex, int pickupPos, int deliveryPos) const +bool TimeWindowConstraint::checkInsertion(PDPTWData const &data, Pair const &pair, int routeIndex, int pickupPos, + int deliveryPos) const { - ReachTimeVector const &reachTimes = allRouteReachTimes.at(routeIndex); // COPY route vector - std::vector<int> route(getSolution().getRoute(routeIndex).getRoute().begin(), getSolution().getRoute(routeIndex).getRoute().end()) ; + std::vector<int> route(getSolution().getRoute(routeIndex).getRoute().begin(), + getSolution().getRoute(routeIndex).getRoute().end()); // COPY reachTimes vector ReachTimeVector newReachTimes(reachTimes.begin(), reachTimes.end()); // Insert pickup and delivery route.insert(route.begin() + deliveryPos, pair.getDelivery().getId()); route.insert(route.begin() + pickupPos, pair.getPickup().getId()); - + // std::cout << "\n"; // for (auto pos : route) @@ -94,89 +94,147 @@ bool TimeWindowConstraint::checkInsertion(const PDPTWData& data, const Pair & pa // std::cout << "\n"; // Check Time Windows - for (int i = 0; i < newReachTimes.size(); ++i) + for (int i = 0; i < newReachTimes.size(); ++i) { - if (! data.getLocation(route.at(i)).getTimeWindow().isValid(newReachTimes.at(i)) ) + if (!data.getLocation(route.at(i)).getTimeWindow().isValid(newReachTimes.at(i))) { return false; } } - return true; + return true; } +// A lot of check here because i had problems with this function +void TimeWindowConstraint::ApplyModif(PDPTWData const &data, Pair const &pair, int routeIndex, int pickupPos, + int deliveryPos, bool addPair) +{ + + // Check the routeIndex validity + if (routeIndex < 0 || routeIndex >= getSolution().getRoutes().size()) + { + spdlog::error("Error: routeIndex out of bounds ({})", routeIndex); + return; + } + // Copy of the route vector (problem that cause a duplication of the TW) + std::vector<int> routeIDs = getSolution().getRoute(routeIndex).getRoute(); -void TimeWindowConstraint::ApplyModif(const PDPTWData& data, const Pair & pair, int routeIndex, int pickupPos, int deliveryPos, bool addPair) -{ - // COPY route vector - std::vector<int> routeIDs(getSolution().getRoute(routeIndex).getRoute().begin(), getSolution().getRoute(routeIndex).getRoute().end()); - - // Adjust pickup and delivery - if (addPair) + // // Check Position validity + // if (pickupPos < 0 || pickupPos > routeIDs.size() || + // deliveryPos < 0 || deliveryPos > routeIDs.size()) { + // spdlog::error("Error: Indices pickupPos ({}) or deliveryPos ({}) are invalid for a route size of {}.", + // pickupPos, deliveryPos, routeIDs.size()); + // return; + // } + + // if (addPair) { + // routeIDs.insert(routeIDs.begin() + deliveryPos, pair.getDelivery().getId()); + // routeIDs.insert(routeIDs.begin() + pickupPos, pair.getPickup().getId()); + // } + // else { + // if (deliveryPos < routeIDs.size() && pickupPos < routeIDs.size() && pickupPos != deliveryPos) { + // if (deliveryPos > pickupPos) { + // routeIDs.erase(routeIDs.begin() + deliveryPos); + // routeIDs.erase(routeIDs.begin() + pickupPos); + // } else { + // routeIDs.erase(routeIDs.begin() + pickupPos); + // routeIDs.erase(routeIDs.begin() + deliveryPos); + // } + // } else { + // spdlog::error("Error: Invalid indices for removal (pickupPos: {}, deliveryPos: {}).", pickupPos, deliveryPos); + // return; + // } + // } + + // the route is empty ! + if (routeIDs.empty()) { - routeIDs.insert(routeIDs.begin() + deliveryPos, pair.getDelivery().getId()); - routeIDs.insert(routeIDs.begin() + pickupPos, pair.getPickup().getId()); + allRouteReachTimes.at(routeIndex).clear(); } else { - routeIDs.erase(routeIDs.begin() + deliveryPos); - routeIDs.erase(routeIDs.begin() + pickupPos); - } + allRouteReachTimes.at(routeIndex).resize(routeIDs.size(), 0); - // Adjust the size of reachTimes vector - allRouteReachTimes.at(routeIndex).resize(routeIDs.size(), 0); - // Time to the first location - allRouteReachTimes.at(routeIndex).at(0) = data.getDepot().getTimeWindow().getStart() + data::TravelTime(data, 0, routeIDs.at(0)); - // Compute other reachTimes (max between arrival and start of the time window) - for (int i = 1; i < routeIDs.size(); ++i) { - TimeInteger travelTime = data::TravelTime(data, routeIDs.at(i - 1), routeIDs.at(i)); - TimeInteger serviceTime = data.getLocation(routeIDs.at(i - 1)).getServiceDuration(); - TimeInteger startTW = data.getLocation(routeIDs.at(i - 1)).getTimeWindow().getStart(); - allRouteReachTimes.at(routeIndex).at(i) = std::max(allRouteReachTimes.at(routeIndex).at(i - 1), startTW) + serviceTime + travelTime; + allRouteReachTimes.at(routeIndex).at(0) = + data.getDepot().getTimeWindow().getStart() + data::TravelTime(data, 0, routeIDs.at(0)); + + // Compute reach times + for (size_t i = 1; i < routeIDs.size(); ++i) + { + if (i - 1 >= routeIDs.size() || i >= routeIDs.size()) + { + spdlog::error("Error: Out-of-bounds access to routeIDs in the computation loop."); + return; + } + + TimeInteger travelTime = data::TravelTime(data, routeIDs.at(i - 1), routeIDs.at(i)); + TimeInteger serviceTime = data.getLocation(routeIDs.at(i - 1)).getServiceDuration(); + TimeInteger startTW = data.getLocation(routeIDs.at(i - 1)).getTimeWindow().getStart(); + + allRouteReachTimes.at(routeIndex).at(i) = + std::max(allRouteReachTimes.at(routeIndex).at(i - 1), startTW) + serviceTime + travelTime; + } } } bool TimeWindowConstraint::check(InsertPair const &op) const { std::cout << " #TW Check"; - return checkInsertion(getSolution().getData(), op.getPair(), op.getRouteIndex(), op.getPickupInsertion(), op.getDeliveryInsertion()); + return checkInsertion(getSolution().getData(), + op.getPair(), + op.getRouteIndex(), + op.getPickupInsertion(), + op.getDeliveryInsertion()); } + void TimeWindowConstraint::apply(InsertPair const &op) { std::cout << "-> Apply Modification on Time Windows \n"; - ApplyModif(getSolution().getData(), op.getPair(), op.getRouteIndex(), op.getPickupInsertion(), op.getDeliveryInsertion(), true); + ApplyModif(getSolution().getData(), + op.getPair(), + op.getRouteIndex(), + op.getPickupInsertion(), + op.getDeliveryInsertion(), + true); } bool TimeWindowConstraint::check(InsertRoute const &op) const { return true; } + void TimeWindowConstraint::apply(InsertRoute const &op) { allRouteReachTimes.emplace_back(); } - bool TimeWindowConstraint::check(RemovePair const &op) const { return true; } + void TimeWindowConstraint::apply(RemovePair const &op) { - ApplyModif(getSolution().getData(), op.getPair(), op.getRouteIndex(), op.getPickupDeletion(), op.getDeliveryDeletion(), false); + ApplyModif(getSolution().getData(), + op.getPair(), + op.getRouteIndex(), + op.getPickupDeletion(), + op.getDeliveryDeletion(), + false); } - bool TimeWindowConstraint::check(RemoveRoute const &op) const { return true; } + void TimeWindowConstraint::apply(RemoveRoute const &op) { allRouteReachTimes.erase(allRouteReachTimes.begin() + op.getRouteIndex()); } -const std::vector<TimeWindowConstraint::ReachTimeVector>& TimeWindowConstraint::getallRouteReachTimes() const { +std::vector<TimeWindowConstraint::ReachTimeVector> const &TimeWindowConstraint::getallRouteReachTimes() const +{ return allRouteReachTimes; } @@ -184,17 +242,22 @@ void TimeWindowConstraint::print() const { std::cout << "Reach Times : \n"; int i = 0; - for (const auto& reachTimes : getallRouteReachTimes()) + for (auto const &reachTimes: getallRouteReachTimes()) { //std::cout << reachTimes.size() << ", "; std::cout << "#" << i << " : "; - for (const TimeInteger reachTime : reachTimes) + for (const TimeInteger reachTime: reachTimes) { std::cout << reachTime << ", "; } + std::cout << "\n"; + std::cout << "#" << i << " : "; + for (int locID: getSolution().getRoute(i).getRoute()) + { + std::cout << locID << ", "; + } std::cout << "\n "; i++; } std::cout << "\n"; } - diff --git a/src/lns/constraints/time_window/time_window_constraint.h b/src/lns/constraints/time_window/time_window_constraint.h index 6b0582b032f957e85dbca7448f584b1808b6be21..915d6f8417f96e190564c98d1a58533dac0b11a7 100644 --- a/src/lns/constraints/time_window/time_window_constraint.h +++ b/src/lns/constraints/time_window/time_window_constraint.h @@ -29,7 +29,7 @@ public: const std::vector<ReachTimeVector> & getallRouteReachTimes() const; - void print() const; + void print() const override; private: /** diff --git a/src/lns/modification/pair/insert_pair.cpp b/src/lns/modification/pair/insert_pair.cpp index 5a7f401f8a54691de0663b34a02f519b4f67a2ab..3917b72fe0cd24ecc18d46b90a6ef9718ae40fee 100644 --- a/src/lns/modification/pair/insert_pair.cpp +++ b/src/lns/modification/pair/insert_pair.cpp @@ -105,5 +105,5 @@ Index InsertPair::getIndex() const ModificationApplyVariant InsertPair::asApplyVariant() const { - return (*this); + return *this; } \ No newline at end of file diff --git a/src/lns/modification/pair/remove_pair.cpp b/src/lns/modification/pair/remove_pair.cpp index 11472a8a38982d786c9a7743ac6716b4b933219a..07e8a227da3fdecc1f7a47695ce47fc17a833da6 100644 --- a/src/lns/modification/pair/remove_pair.cpp +++ b/src/lns/modification/pair/remove_pair.cpp @@ -91,5 +91,5 @@ Index RemovePair::getIndex() const ModificationApplyVariant RemovePair::asApplyVariant() const { - return (*this); + return *this; } \ No newline at end of file diff --git a/src/lns/operators/destruction/random_destroy.cpp b/src/lns/operators/destruction/random_destroy.cpp index 975e1a469e4d5465957c0b0c728cde248e3f8396..fb3fdec0c38057acf6c23179f92d0882ea065334 100644 --- a/src/lns/operators/destruction/random_destroy.cpp +++ b/src/lns/operators/destruction/random_destroy.cpp @@ -9,53 +9,65 @@ void RandomDestroy::destroySolution(Solution &solution) const { + std::cout << " --- Random Destroy --- \n"; int nbRequests = solution.requestsFulFilledCount(); int actualNumberOfPairsToDestroy = std::min(nbRequests, numberOfPairsToDestroy); int remainingPairToDelete = actualNumberOfPairsToDestroy; - while (remainingPairToDelete < 0) + while (remainingPairToDelete > 0) { // too complicated // Other (simpler) option -> choose random route then choose random pair ? - // choose a random pair - int pairNumber = util::getRandomInt(0, remainingPairToDelete * 2 - 1); + // choose a random location + int locationNumber = util::getRandomInt(0, remainingPairToDelete * 2 - 1); + + // test + // locationNumber = nbRequests * 2 - 1; + // std::cout << " " << locationNumber << " \n"; + // int pairID = 0; int routeID = 0; - int count = 0; + int position = 0; Index index = std::make_tuple(0,0,0); // retrieve index (route and position) for (const Route &route : solution.getRoutes()) { - count += route.getSize(); - if (pairNumber < count) + position += route.getSize(); + if (locationNumber < position) { - count = count - pairNumber; + // calculate the location position + position = route.getSize() - (position - locationNumber); - std::get<0>(index) = routeID; - std::get<1>(index) = count; - std::get<2>(index) = route.getPairLocationPosition(count, solution.getData()); + // get location associated to the position + Location loc = solution.getData().getLocation(route.getRoute().at(position)); // retrieve pickupID (= PairID) - if (solution.getData().getLocation(route.getRoute().at(count)).getLocType() == LocType::PICKUP ) + if (loc.getLocType() == LocType::PICKUP ) { - pairID = route.getRoute().at(count); + pairID = route.getRoute().at(position); + std::get<1>(index) = position; + std::get<2>(index) = route.getPairLocationPosition(position, solution.getData()); } else { - pairID = route.getRoute().at(std::get<2>(index)); + pairID = loc.getPair(); + std::get<1>(index) = route.getPairLocationPosition(position, solution.getData()); + std::get<2>(index) = position; } + + std::get<0>(index) = routeID; + break; } ++routeID; } - + RemovePair remPair = RemovePair(index, solution.getData().getPair(pairID)); - // appliquer la modif (via solution method -> update correctement la solution) solution.applyDestructSolution(remPair); // update les compteurs diff --git a/src/lns/solution/solution.cpp b/src/lns/solution/solution.cpp index e9e7b548e27fa5522fecf0ae53c931398e738c2f..dbbb005c2555f8e935c41248250d11815181a5d9 100644 --- a/src/lns/solution/solution.cpp +++ b/src/lns/solution/solution.cpp @@ -190,6 +190,8 @@ void Solution::applyRecreateSolution(AtomicRecreation &modification) } afterApplyModification(modification); + std::cout << "\n --- \n"; + this->print(); } void Solution::applyDestructSolution(AtomicDestruction &modification) @@ -204,6 +206,7 @@ void Solution::applyDestructSolution(AtomicDestruction &modification) pairBank.insert(pairBank.end(), deletedPair.begin(), deletedPair.end()); afterApplyModification(modification); + this->print(); } void Solution::check() const @@ -227,5 +230,11 @@ void Solution::print() const { std::cout << id << ", "; } + + std::cout << "\nConstraints : \n"; + for (const std::unique_ptr<Constraint> &constraint: constraints) + { + constraint->print(); + } std::cout << "\n"; } \ No newline at end of file diff --git a/src/mains/main.cpp b/src/mains/main.cpp index c3ed313e0f985dd797044b2a8f55842e32e779d2..3d63ca676d35a1e66fa20b7eabafe1c92b7817aa 100644 --- a/src/mains/main.cpp +++ b/src/mains/main.cpp @@ -14,6 +14,7 @@ #include "input/data.h" #include "lns/constraints/capacity/capacity_constraint.h" #include "lns/constraints/time_window/time_window_constraint.h" +#include "lns/operators/destruction/random_destroy.h" #include "lns/operators/reconstruction/list_heuristic_cost_oriented.h" #include "lns/solution/solution.h" #include "lns/modification/pair/insert_pair.h" @@ -83,7 +84,20 @@ int main(int argc, char const *argv[]) heuristic.reconstructSolution(solution, blinkRate, strategy, enumeration); solution.print(); + + solution.print(); + + + std::cout << " --- supr !!! --- \n "; + + RandomDestroy randomdestroy = RandomDestroy(5); + randomdestroy.destroySolution(solution); + + //Index index = std::make_tuple(0,7,9); + //RemovePair remPair = RemovePair(index, solution.getData().getPair(2)); + //solution.applyDestructSolution(remPair); - output::exportToJson(solution); + //solution.print(); + //output::exportToJson(solution); return 0; }