diff --git a/src/lns/constraints/capacity/capacity_constraint.cpp b/src/lns/constraints/capacity/capacity_constraint.cpp index b455134178b1b97d0deb2323223a8fe6205a15ca..157c37e8ce954918721b191c89d2338a22b34af6 100644 --- a/src/lns/constraints/capacity/capacity_constraint.cpp +++ b/src/lns/constraints/capacity/capacity_constraint.cpp @@ -43,7 +43,6 @@ std::vector<int> const & CapacityConstraint::getRouteCapacities(int routeIndex) // not ideal bool CapacityConstraint::checkModif(Pair const &pair, int routeIndex, int PickupPosition, int DeliveryPosition) const { - std::cout << "\n"; int max_capacity = getSolution().getData().getCapacity(); // guardrail @@ -67,9 +66,8 @@ bool CapacityConstraint::checkModif(Pair const &pair, int routeIndex, int Pickup // not ideal void CapacityConstraint::applyModif(Pair const &pair, int routeIndex, int PickupPosition, int DeliveryPosition, bool addPair) { - std::cout << "ApplyModif (capa constraint) \n"; if (addPair) - { + { // Insert new values routeCapacities[routeIndex].insert(routeCapacities[routeIndex].begin()+DeliveryPosition, 0); if (DeliveryPosition != 0) @@ -104,11 +102,12 @@ void CapacityConstraint::applyModif(Pair const &pair, int routeIndex, int Pickup bool CapacityConstraint::check(InsertPair const &op) const { - std::cout << "capa constraint \n"; + std::cout << " #Capa Check"; return checkModif(op.getPair(), op.getRouteIndex(), op.getPickupInsertion(), op.getDeliveryInsertion()); } void CapacityConstraint::apply(InsertPair const &op) { + std::cout << "-> Apply Modification on Capacity \n"; applyModif(op.getPair(), op.getRouteIndex(), op.getPickupInsertion(), op.getDeliveryInsertion(), true); } diff --git a/src/lns/constraints/time_window/time_window_constraint.cpp b/src/lns/constraints/time_window/time_window_constraint.cpp index 1886b6f222deb598f70fc7a7193994323b1565ae..8f5cc14111216a3b99f777961fdbb6c3c3fa94db 100644 --- a/src/lns/constraints/time_window/time_window_constraint.cpp +++ b/src/lns/constraints/time_window/time_window_constraint.cpp @@ -138,11 +138,12 @@ void TimeWindowConstraint::ApplyModif(const PDPTWData& data, const Pair & pair, bool TimeWindowConstraint::check(InsertPair const &op) const { - std::cout << "tw constraint \n"; + std::cout << " #TW Check"; 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); } diff --git a/src/lns/modification/atomic_recreation.h b/src/lns/modification/atomic_recreation.h index 7a5384abbcb4066f7124eb0b4c77d0971fec8043..eab65ed9489a53b2c12262eb8963f869c20b32c3 100644 --- a/src/lns/modification/atomic_recreation.h +++ b/src/lns/modification/atomic_recreation.h @@ -24,5 +24,5 @@ public: * @return the pair added to the solution, nullptr if none were added * (why return pointer and not juste a int ?) */ - virtual Pair const *getAddedPairs() const = 0; + virtual int getAddedPairs() const = 0; }; \ No newline at end of file diff --git a/src/lns/modification/pair/insert_pair.cpp b/src/lns/modification/pair/insert_pair.cpp index da5bf4fff088beefcb87201b7d4b2c341efa02bd..82212c58b768db0369c8e7b743f81094889ad12e 100644 --- a/src/lns/modification/pair/insert_pair.cpp +++ b/src/lns/modification/pair/insert_pair.cpp @@ -88,9 +88,9 @@ const Location &InsertPair::getDeliveryLocation() const return deliveryLocation; } -const Pair *InsertPair::getAddedPairs() const +int InsertPair::getAddedPairs() const { - return &pair; + return pair.getID(); } const Pair &InsertPair::getPair() const diff --git a/src/lns/modification/pair/insert_pair.h b/src/lns/modification/pair/insert_pair.h index ceb40455c26d0aa4a136b78cc322ee8a3179d934..86b97b175e31cded2d9733dde521997dcd41e6fb 100644 --- a/src/lns/modification/pair/insert_pair.h +++ b/src/lns/modification/pair/insert_pair.h @@ -55,7 +55,7 @@ public: void modifySolution(Solution &solution) override; double evaluate(Solution const &solution) const override; - Pair const *getAddedPairs() const override; + int getAddedPairs() const override; int getPickupInsertion() const; int getDeliveryInsertion() const; diff --git a/src/lns/modification/route/insert_route.cpp b/src/lns/modification/route/insert_route.cpp index 160722e774ca379892047093fcf2a264d66993bb..bde976891a405d740fbd2748df8f81f71cd4a6a1 100644 --- a/src/lns/modification/route/insert_route.cpp +++ b/src/lns/modification/route/insert_route.cpp @@ -14,9 +14,9 @@ double InsertRoute::evaluate(Solution const &solution) const return 0; } -Pair const *InsertRoute::getAddedPairs() const +int InsertRoute::getAddedPairs() const { - return nullptr; + return -1; } ModificationCheckVariant InsertRoute::asCheckVariant() const diff --git a/src/lns/modification/route/insert_route.h b/src/lns/modification/route/insert_route.h index cbfdb27f627d05339a9b80723667221c616abfaa..05ecdaf5438de575e2cd1140e87ebcb3197f255a 100644 --- a/src/lns/modification/route/insert_route.h +++ b/src/lns/modification/route/insert_route.h @@ -16,7 +16,7 @@ public: void modifySolution(Solution &solution) override; double evaluate(Solution const &solution) const override; - Pair const *getAddedPairs() const override; + int getAddedPairs() const override; ModificationCheckVariant asCheckVariant() const override; }; \ No newline at end of file diff --git a/src/lns/operators/generators/modification_generator.cpp b/src/lns/operators/generators/modification_generator.cpp index 756e7dfc0f695bddf71134bcc6e50b6f964a5223..91399233901b3847f3393c0348a2edcc58632c8e 100644 --- a/src/lns/operators/generators/modification_generator.cpp +++ b/src/lns/operators/generators/modification_generator.cpp @@ -15,21 +15,20 @@ namespace generator std::function<void(ModificationType &&)> addToListIfValidTemplate(Solution const &solution, ModificationContainer &list) { - std::cout << "avant error \n"; return [&](ModificationType &&modification) { - std::cout << "Check Modif \n"; if (solution.checkModification(modification)) { - std::cout << "insert modif to list \n"; + std::cout << " => Insert Modification" << "\n"; list.push_front(std::make_unique<ModificationType>(modification)); } }; + std::cout << " => Insert Modification" << "\n"; } void AllTypedModifications<InsertPair>::populate(Solution const &solution, Pair const &pair, std::forward_list<std::unique_ptr<AtomicRecreation>> &list) { - std::cout << "dans modif_generator \n"; + std::cout << "\n MODIFICATION GENERATOR : \n"; enumeration::enumerateAllInsertPair( solution, pair, addToListIfValidTemplate<InsertPair>(solution, list)); } diff --git a/src/lns/operators/reconstruction/list_heuristic_insertion.hpp b/src/lns/operators/reconstruction/list_heuristic_insertion.hpp index e05e50591094875d5726a15c30e222409441b0b8..31deee6f7d41fdfd8d8f0a1194f903b095491e05 100644 --- a/src/lns/operators/reconstruction/list_heuristic_insertion.hpp +++ b/src/lns/operators/reconstruction/list_heuristic_insertion.hpp @@ -25,7 +25,7 @@ void ListHeuristicInsertion<Strategy, Generator>::reconstructSolution(Solution & recreation = ListHeuristicInsertion::choosingStrategy(solution, pair, blinkRate); if (recreation) { - std::cout << "\n apply recreation "<< " " << "\n \n"; + std::cout << "\n --- Apply recreation --- \n"; solution.applyRecreateSolution(*recreation); } } diff --git a/src/lns/solution/solution.cpp b/src/lns/solution/solution.cpp index 908ce690a65d0957b325c298b3b62953c9aa9494..9677f3adfe2849de8daf715fe2cca0de9c69b073 100644 --- a/src/lns/solution/solution.cpp +++ b/src/lns/solution/solution.cpp @@ -6,7 +6,9 @@ #include "lns/constraints/capacity/capacity_constraint.h" #include "lns/constraints/time_window/time_window_constraint.h" #include "lns/solution/route.h" +#include "output/solution_checker.h" +#include <bits/ranges_util.h> #include <utility> void Solution::initPairBank() @@ -145,25 +147,26 @@ int Solution::requestsFulFilledCount() const bool Solution::checkModification(AtomicRecreation const &modification) const { + std::cout << "--- Check Modification Validity : "; ModificationCheckVariant const &checkVariant = modification.asCheckVariant(); // visitor pattern for (std::unique_ptr<Constraint> const &constraint: constraints) { - std::cout << "in check modif \n"; if (!constraint->checkVariant(checkVariant)) { - std::cout << "return false \n"; + std::cout << "\n"; return false; } } + std::cout << "\n"; return true; - std::cout << "return true \n"; } void Solution::beforeApplyModification(AtomicModification &modification) { - // pre check to do ? + // pre modification check + check(); } void Solution::afterApplyModification(AtomicModification &modification) @@ -177,8 +180,16 @@ void Solution::afterApplyModification(AtomicModification &modification) void Solution::applyRecreateSolution(AtomicRecreation &modification) { - // apply the modification to the solution - std::cout << "not fonctionnal yet \n"; + beforeApplyModification(modification); + + modification.modifySolution(*this); + // we update the request bank + if (int pairID = modification.getAddedPairs()) + { + pairBank.erase(std::ranges::find(pairBank, pairID)); + } + + afterApplyModification(modification); } void Solution::applyDestructSolution(AtomicDestruction &modification) @@ -195,6 +206,11 @@ void Solution::applyDestructSolution(AtomicDestruction &modification) afterApplyModification(modification); } +void Solution::check() const +{ + checker::checkSolutionCoherence(*this, getData()); +} + void Solution::print() const { std::cout << "Cost : " << totalCost << "\n" diff --git a/src/lns/solution/solution.h b/src/lns/solution/solution.h index cb2954aab63d35552ce171cab1c094a9edb422c4..fca2ddcba058ebdd3dd80f59e2727dd5757b898e 100644 --- a/src/lns/solution/solution.h +++ b/src/lns/solution/solution.h @@ -77,6 +77,9 @@ public: */ bool checkModification(AtomicRecreation const &modification) const; + // using solution checker to verify that the solution is correct. Most used for debug as it is correctness oriented and not performance oriented + void check() const; + /** * Pre modification check. * @param modification Must be a valid modification. diff --git a/src/mains/main.cpp b/src/mains/main.cpp index 780bb7d7bd625786cfa160b6a05064bdaa93819e..4f306b84d6dc05a88fe347aa8b4682afa5376508 100644 --- a/src/mains/main.cpp +++ b/src/mains/main.cpp @@ -33,10 +33,10 @@ void printForwardList(const std::forward_list<std::unique_ptr<AtomicRecreation>> for (const auto& item : list) { std::cout << cpt << "{ \n"; // Affichage de l'emplacement ajouté à la solution - const Pair* pair = item->getAddedPairs(); - if (pair != nullptr) { + int pair = item->getAddedPairs(); + if (pair > 0) { std::cout << "Added Location ID: \n"; - pair->print(); + std::cout << pair << "\n"; } else { std::cout << "No location added.\n"; } @@ -68,46 +68,17 @@ int main(int argc, char const *argv[]) std::cout << "--- Empty Solution --- \n"; solution.print(); - sorting_strategy::Shuffle shuffleStrategy(solution); // Créer une instance de la stratégie de tri - auto sortedPairs = shuffleStrategy.sortPairs(); - - for (auto id : sortedPairs) - { - std::cout << id << " "; - } - std::cout << "\n"; - // ListHeuristicInsertion<sorting_strategy::SortingStrategy, generator::ModificationGenerator> operator; - - // double blinkRate = 0.1; // Par exemple, 10% de probabilité d'ignorer l'insertion - // operator.reconstructSolution(emptySol, blinkRate); - - std::cout << "---- \n"; - generator::AllTypedModifications<InsertPair> generator; generator::ModificationContainer modificationList; - - std::cout << "---- \n"; - - int pairID = solution.getBank().front(); - Pair pair = solution.getData().getPair(pairID); - - pair.print(); - - std::cout << "---- \n"; - generator.populate(solution, pair, modificationList); - - // print the pair associated to each modif - printForwardList(modificationList); - std::cout << "\n ---- \n \n"; //ListHeuristicInsertion<std::derived_from<sorting_strategy::SortingStrategy> Strategy, std::derived_from<generator::ModificationGenerator> Generator> double blinkRate = 0; - //operator.reconstructSolution(solution, blinkRate); - ListHeuristicInsertion<sorting_strategy::Shuffle, generator::AllTypedModifications<InsertPair>> operatorInstance; + std::cout << "\n --- Operator <SHUFFLE - ALL_INSERTPAIR> -> reconstruction (NO COST UPDATE)\n"; + ListHeuristicInsertion<sorting_strategy::Shuffle, generator::AllTypedModifications<InsertPair>> operatorInstance; operatorInstance.reconstructSolution(solution, blinkRate); solution.print(); diff --git a/src/output/solution_checker.cpp b/src/output/solution_checker.cpp index 9918138fad80eecbe706c3214bde01e4293ff9f2..b86ab63f46d575f0290c27bdb108f59dbedea007 100644 --- a/src/output/solution_checker.cpp +++ b/src/output/solution_checker.cpp @@ -1,51 +1,67 @@ #include "solution_checker.h" + +#include "input/data.h" #include "input/location.h" #include "input/pdptw_data.h" #include "lns/solution/solution.h" #include "types.h" -#include "input/data.h" #include <spdlog/spdlog.h> +#include <vector> void checker::checkSolutionCoherence(Solution const &sol, PDPTWData const &data) { + std::cout << " --- Solution Coherence checker : "; + bool errorFlag = false; // Vector that will store the route ID serving the location, (-1 if no routes) + // Caution ! check is indexed from 0 to n-1 and Location ID are indexed from 1 to n std::vector<int> check(data.getLocations().size(), -1); // checking routes coherence int routeID = 0; - for (const Route &route : sol.getRoutes()) - { - for (int id : route.getRoute()) + for (Route const &route: sol.getRoutes()) + { + std::cout << "#"; + // skip if it is an empty route + if (!route.getRoute().empty()) { - if (check.at(id) != -1) - { - // Error the location is already attributed (doublon) - spdlog::error("Location {} has already been visited.", id); - errorFlag = true; - } - - check.at(id) = routeID; - - // if the location is a delivery, check if the pickup location has already been visited in the same route - if ((data.getLocation(id).getLocType() == LocType::DELIVERY) - && (check[data.getLocation(id).getPair()] != routeID) ) + for (int LocID: route.getRoute()) { - // Error Pickup and Delivery are not in the same route (wrong route) - // OR Delivery before Pickup (wrong order) - spdlog::error("Pair associated to {} is not consistent (route or order problem).", id); - errorFlag = true; + if (check.at(LocID -1) != -1) + { + std::cout << "#"; + + // Error the location is already attributed (doublon) + spdlog::error("Location {} has already been visited.", LocID); + errorFlag = true; + } + + check.at(LocID -1) = routeID; + + // if the location is a delivery, check if the pickup location has already been visited in the same route + if ((data.getLocation(LocID).getLocType() == LocType::DELIVERY) && + (check.at(data.getLocation(LocID).getPair() - 1) != routeID)) + { + // Error Pickup and Delivery are not in the same route (wrong route) + // OR Delivery before Pickup (wrong order) + spdlog::error("Pair associated to {} is not consistent (route or order problem).", LocID); + errorFlag = true; + } } } ++routeID; } + std::cout << "#"; + // checking PairBank coherence (given the routes) - for (int pairID : sol.getBank()) + std::vector<int> testbank = sol.getBank(); + for (int pairID: sol.getBank()) { - if ((check.at(pairID) != -1) || (data.getLocation(pairID).getPair() != -1)) + // check goes from 0 et n-1 + if ((check.at(pairID - 1) != -1) || (check.at(data.getLocation(pairID).getPair() - 1) != -1)) { // Error Pair in the bank but one location of the pair seems to be visited by a route (doublon) spdlog::error("Pair associated to {} is in a route and in the bank at the same time.", pairID); @@ -55,21 +71,22 @@ void checker::checkSolutionCoherence(Solution const &sol, PDPTWData const &data) if (errorFlag) { + sol.print(); throw SolutionConstraintError("Error in the consistency of the solution.", sol); } + std::cout << " : checker end ---\n"; } - void checker::checkCapacity(Solution const &sol, PDPTWData const &data) -{ +{ bool errorFlag = false; int capa = 0; int routeID = 0; - for (const Route &route : sol.getRoutes() ) + for (Route const &route: sol.getRoutes()) { - for (int id : route.getRoute() ) + for (int id: route.getRoute()) { capa += data.getLocation(id).getDemand(); if (capa > data.getCapacity()) @@ -79,13 +96,13 @@ void checker::checkCapacity(Solution const &sol, PDPTWData const &data) errorFlag = true; } } - if (capa != 0) + if (capa != 0) { // Error, all the capacity is supposed to be free at the end of a route spdlog::error("Some capacity still used at the end of the route {}.", routeID); - errorFlag = true; + errorFlag = true; } - ++ routeID; + ++routeID; } if (errorFlag) @@ -101,39 +118,39 @@ void checker::checkTimeWindows(Solution const &sol, PDPTWData const &data) int routeID = 0; int locID = 0; - for (const Route &route : sol.getRoutes() ) + for (Route const &route: sol.getRoutes()) { // travel to the first location reachTime = data.getDepot().getTimeWindow().getStart() + data::TravelTime(data, 0, route.getRoute().at(0)); - for (int i=0; i < route.getRoute().size() - 1; i++) + for (int i = 0; i < route.getRoute().size() - 1; i++) { locID = route.getRoute().at(i); // check TimeWindow - if (!(data.getLocation(locID).getTimeWindow().isValid(reachTime)) ) + if (!(data.getLocation(locID).getTimeWindow().isValid(reachTime))) { // Error, reach time not valid for the location time window spdlog::error("Reach time not valid for the location {} time window in route {}.", locID, routeID); - errorFlag = true; + errorFlag = true; } - - TimeInteger travelTime = data::TravelTime(data, locID, route.getRoute().at(i+1)); + + TimeInteger travelTime = data::TravelTime(data, locID, route.getRoute().at(i + 1)); TimeInteger serviceTime = data.getLocation(locID).getServiceDuration(); TimeInteger startTW = data.getLocation(locID).getTimeWindow().getStart(); reachTime = std::max(reachTime, startTW) + serviceTime + travelTime; - } + } // check last timeWindow locID = route.getRoute().back(); - if (!(data.getLocation(locID).getTimeWindow().isValid(reachTime)) ) + if (!(data.getLocation(locID).getTimeWindow().isValid(reachTime))) { // Error, reach time not valid for the location time window spdlog::error("Reach time not valid for the location {} time window in route {}.", locID, routeID); - errorFlag = true; + errorFlag = true; } - ++ routeID; + ++routeID; } if (errorFlag) @@ -142,9 +159,8 @@ void checker::checkTimeWindows(Solution const &sol, PDPTWData const &data) } } -void checker::checkAll(Solution const &sol , PDPTWData const &data, bool checkRequests) +void checker::checkAll(Solution const &sol, PDPTWData const &data, bool checkRequests) { - // TO DO, check in the solution if all locations are visited ! (in checkSolutionCoherence ?) if (checkRequests) { @@ -157,11 +173,9 @@ void checker::checkAll(Solution const &sol , PDPTWData const &data, bool checkRe checker::checkSolutionCoherence(sol, data); checker::checkCapacity(sol, data); - checker::checkTimeWindows(sol,data); - + checker::checkTimeWindows(sol, data); } - // No logging yet checker::SolutionInternalError::SolutionInternalError(std::string reason, Solution const &sol)