diff --git a/CMakeLists.txt b/CMakeLists.txt
index 888b4e7243a2a953d117a96c16dafdb934172b81..f8a955139444e0e665ed16ec92f2cc1a3d7a5944 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -28,6 +28,7 @@ add_executable(pdptw src/mains/main.cpp
                 src/lns/solution/solution.cpp
                 src/lns/constraints/constraint.cpp
                 src/lns/constraints/capacity/capacity_constraint.cpp
+                src/lns/constraints/time_window/forward_time_slack.cpp
                 src/lns/constraints/time_window/time_window_constraint.cpp
                 src/lns/modification/pair/insert_pair.cpp 
                 src/lns/modification/pair/remove_pair.cpp
diff --git a/src/config.h b/src/config.h
index 886eae394f4365f2fd93665616595ba2fc329d23..967603c0225653fd5396c98d021520b46557e65b 100644
--- a/src/config.h
+++ b/src/config.h
@@ -1,5 +1,3 @@
-
-
 const int EXCLUSION_PENALTY = 100;
 
 const int RANDOM_SEED = 100;
diff --git a/src/input/data.cpp b/src/input/data.cpp
index a5dc436ea3aab8f884da6eff0009cc5beb1cd0ea..817d0be461f9bd5b51411a2acc3187d87188e910 100644
--- a/src/input/data.cpp
+++ b/src/input/data.cpp
@@ -24,11 +24,11 @@ double data::routeCost(PDPTWData const & data, Route const & route)
 {
     const Matrix & matrix = data.getMatrix();
     const std::vector<int> & routeIDs = route.getRoute();
-    double cost = 0;
+    double cost = 0.0;
 
     if (routeIDs.empty())
     {
-        return 0;
+        return 0.0;
     }
     // cost from and to the depot
     cost +=  matrix.at(0).at(routeIDs.at(0));
diff --git a/src/lns/constraints/capacity/capacity_constraint.cpp b/src/lns/constraints/capacity/capacity_constraint.cpp
index 7ff89d58d1b005d6408437dba0f62cccae177255..2827d98c1537c24d522afc7439ca63b49d72e95a 100644
--- a/src/lns/constraints/capacity/capacity_constraint.cpp
+++ b/src/lns/constraints/capacity/capacity_constraint.cpp
@@ -1,94 +1,94 @@
 #include "capacity_constraint.h"
 
-
 CapacityConstraint::CapacityConstraint(Solution const &solution) : Constraint(solution)
 {
     // Init an empty vector of reach time for all routes
-    //std::vector<CapacityVector> routeCapacities(getSolution().getRoutes().size(), CapacityVector());
     routeCapacities.resize(getSolution().getRoutes().size());
 }
 
-std::unique_ptr<Constraint> CapacityConstraint::clone(Solution const &newOwningSolution) const {
+std::unique_ptr<Constraint> CapacityConstraint::clone(Solution const &newOwningSolution) const
+{
     std::unique_ptr<CapacityConstraint> clonePtr = std::make_unique<CapacityConstraint>(newOwningSolution);
     clonePtr->routeCapacities = routeCapacities;
     return clonePtr;
 }
 
-
-void CapacityConstraint::initCapacities()
+void CapacityConstraint::initRouteCapacities()
 {
-    routeCapacities = std::vector<CapacityVector>();
-    for (const Route& route : getSolution().getRoutes()) 
+    routeCapacities.clear();
+    for (Route const &route: getSolution().getRoutes())
     {
         CapacityVector capacities;
         int currentCapacity = 0;
-        
-        for (int locationID : route.getRoute()) 
+
+        for (int locationID: route.getRoute())
         {
             currentCapacity += getSolution().getData().getLocation(locationID).getDemand();
             capacities.push_back(currentCapacity);
         }
-        
+
         routeCapacities.push_back(capacities);
     }
 }
 
 
-std::vector<int> const & CapacityConstraint::getRouteCapacities(int routeIndex) const
+std::vector<int> const &CapacityConstraint::getRouteCapacities(int routeIndex) const
 {
     return routeCapacities.at(routeIndex);
 }
 
-// check for every location between the pickupPosition and the deliveryPosition
-// not ideal
+/*
+ *  Check if an insertion is feasible by computing new capacity values between the PickupPosition and DeliveryPosition.
+ *  Assume the constraint is valid beforehand.
+ *  O(n), n the size of the route 
+ */
 bool CapacityConstraint::checkModif(Pair const &pair, int routeIndex, int PickupPosition, int DeliveryPosition) const
 {
     int max_capacity = getSolution().getData().getCapacity();
+    int demand = pair.getPickup().getDemand();
+    CapacityVector const &routeCapacity = getRouteCapacities(routeIndex);
 
-    // guardrail
-    if (pair.getPickup().getDemand() > max_capacity)
+    // if PickupPosition != DeliveryPosition, check from pickup-1 to delivery-1
+    // if PickupPosition is 0, don't check -1 ...
+    for (int i = std::max(0, PickupPosition - 1); i < DeliveryPosition; i++)
     {
-        return false;
-    }
-
-    // check if the disponible capacity is enough are not
-    for (int i = PickupPosition; i <= DeliveryPosition; ++i) {
-        
-        if ((i!=0) && (getRouteCapacities(routeIndex).at(i-1) + pair.getPickup().getDemand() >= max_capacity))
+        if (routeCapacity.at(i) + demand > max_capacity)
         {
             return false;
         }
-    } 
+    }
     return true;
 }
 
 // update the route and the weight
-// not ideal
-void CapacityConstraint::applyModif(Pair const &pair, int routeIndex, int PickupPosition,  int DeliveryPosition, bool addPair)
+void CapacityConstraint::applyModif(Pair const &pair, int routeIndex, int PickupPosition, int DeliveryPosition,
+                                    bool addPair)
 {
     if (addPair)
-    { 
+    {
         // Insert new values
-        routeCapacities.at(routeIndex).insert(routeCapacities.at(routeIndex).begin()+DeliveryPosition, 0);
+        routeCapacities.at(routeIndex).insert(routeCapacities.at(routeIndex).begin() + DeliveryPosition, 0);
         if (DeliveryPosition != 0)
         {
-            routeCapacities.at(routeIndex).at(DeliveryPosition) += routeCapacities.at(routeIndex).at(DeliveryPosition-1);
+            routeCapacities.at(routeIndex).at(DeliveryPosition) +=
+                    routeCapacities.at(routeIndex).at(DeliveryPosition - 1);
         }
-        routeCapacities.at(routeIndex).insert(routeCapacities.at(routeIndex).begin()+PickupPosition, pair.getPickup().getDemand());
+        routeCapacities.at(routeIndex)
+                .insert(routeCapacities.at(routeIndex).begin() + PickupPosition, pair.getPickup().getDemand());
         if (PickupPosition != 0)
         {
-            routeCapacities.at(routeIndex).at(PickupPosition) += routeCapacities.at(routeIndex).at(PickupPosition-1);
+            routeCapacities.at(routeIndex).at(PickupPosition) += routeCapacities.at(routeIndex).at(PickupPosition - 1);
         }
 
         // Update value
-        for (int i = PickupPosition + 1; i < DeliveryPosition + 1; ++i) 
+        for (int i = PickupPosition + 1; i < DeliveryPosition + 1; ++i)
         {
             routeCapacities.at(routeIndex).at(i) += pair.getPickup().getDemand();
-        } 
+        }
     }
-    else 
+    else
     {
-        for (int i = PickupPosition + 1; i < DeliveryPosition; ++i) 
+        for (int i = PickupPosition + 1; i < DeliveryPosition; ++i)
         {
             routeCapacities.at(routeIndex).at(i) += pair.getDelivery().getDemand();
         }
@@ -96,48 +96,48 @@ void CapacityConstraint::applyModif(Pair const &pair, int routeIndex, int Pickup
         // remove pair
         routeCapacities.at(routeIndex).erase(routeCapacities.at(routeIndex).begin() + DeliveryPosition);
         routeCapacities.at(routeIndex).erase(routeCapacities.at(routeIndex).begin() + PickupPosition);
-    }    
+    }
 }
 
-
 bool CapacityConstraint::check(InsertPair const &op) const
 {
     //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);
 }
 
-
 bool CapacityConstraint::check(InsertRoute const &op) const
 {
     return true;
 }
+
 void CapacityConstraint::apply(InsertRoute const &op)
 {
     // add new empty route
     routeCapacities.emplace_back();
-}   
-
+}
 
 bool CapacityConstraint::check(RemovePair const &op) const
 {
     // Remove a pair (always true)
     return true;
 }
+
 void CapacityConstraint::apply(RemovePair const &op)
 {
     applyModif(op.getPair(), op.getRouteIndex(), op.getPickupDeletion(), op.getDeliveryDeletion(), false);
 }
 
-
 bool CapacityConstraint::check(RemoveRoute const &op) const
 {
     return true;
-}   
+}
+
 void CapacityConstraint::apply(RemoveRoute const &op)
 {
     // add new empty route
@@ -148,10 +148,10 @@ void CapacityConstraint::print() const
 {
     std::cout << "Used capacity : \n";
     int i = 0;
-    for (const auto& capaVector : routeCapacities)
+    for (auto const &capaVector: routeCapacities)
     {
         std::cout << "#" << i << " : ";
-        for (const int capa : capaVector)
+        for (int const capa: capaVector)
         {
             std::cout << capa << ", ";
         }
@@ -159,4 +159,3 @@ void CapacityConstraint::print() const
         i++;
     }
 }
-
diff --git a/src/lns/constraints/capacity/capacity_constraint.h b/src/lns/constraints/capacity/capacity_constraint.h
index 1ae640370102d3c9bf2684ed2ab84cc45fd402b3..059bdd3dc91289a55a0184430ac94281747b7411 100644
--- a/src/lns/constraints/capacity/capacity_constraint.h
+++ b/src/lns/constraints/capacity/capacity_constraint.h
@@ -1,25 +1,25 @@
 #pragma once
-#include <vector>
-
 #include "lns/constraints/constraint.h"
-
-#include "lns/solution/solution.h"
 #include "lns/modification/pair/insert_pair.h"
 #include "lns/modification/pair/remove_pair.h"
 #include "lns/modification/route/insert_route.h"
 #include "lns/modification/route/remove_route.h"
+#include "lns/solution/solution.h"
+
+#include <vector>
 
 /**
  * Capacity constraint.
- * To check this, we keep track of the sum of all requests and check it against the max capacity.
- * TO DO, verification in O(1) by storing a matrix !
  */
 class CapacityConstraint : public Constraint
 {
 public:
     using CapacityVector = std::vector<int>;
-private:
 
+private:
+    /**
+     * Store the used capacity value when leaving one location in each route.
+     */
     std::vector<CapacityVector> routeCapacities;
 
     void apply(InsertPair const &op) override;
@@ -31,22 +31,21 @@ private:
     bool check(InsertRoute const &op) const override;
     bool check(RemovePair const &op) const override;
     bool check(RemoveRoute const &op) const override;
-public:
 
+public:
     explicit CapacityConstraint(Solution const &);
     CapacityConstraint(CapacityConstraint const &) = default;
 
     std::unique_ptr<Constraint> clone(Solution const &newOwningSolution) const override;
 
     /*
-    *   Given the solution, calculate the capacities when leaving each location
-    *   Modify the routeCapacities vector !
-    */
-    void initCapacities();
+     *  Compute from scratch the routeCapacities vector.
+     */
+    void initRouteCapacities();
 
     /*
-    *   Return capacity vector of a route
-    */
+     *  Return capacity vector of a route
+     */
     CapacityVector const &getRouteCapacities(int routeIndex) const;
 
     /*
@@ -62,7 +61,7 @@ public:
     /*
     *   Update the weight
     */
-    void applyModif(Pair const &pair, int routeIndex, int PickupPosition,  int DeliveryPosition, bool addPair);
+    void applyModif(Pair const &pair, int routeIndex, int PickupPosition, int DeliveryPosition, bool addPair);
 
     void print() const override;
 };
\ No newline at end of file
diff --git a/src/lns/constraints/time_window/forward_time_slack.cpp b/src/lns/constraints/time_window/forward_time_slack.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..8225ee764943ad8f3b1dbc1d11a1803524f8ee53
--- /dev/null
+++ b/src/lns/constraints/time_window/forward_time_slack.cpp
@@ -0,0 +1,301 @@
+#include "forward_time_slack.h"
+
+#include "input/data.h"
+#include "lns/solution/solution.h"
+
+std::vector<TimeInteger> const &ForwardTimeSlack::getFTS() const
+{
+    return FTS;
+}
+
+std::vector<TimeInteger> const &ForwardTimeSlack::getEarliestArrival() const
+{
+    return earliestArrival;
+}
+
+std::vector<TimeInteger> const &ForwardTimeSlack::getLatestArrival() const
+{
+    return latestArrival;
+}
+
+void ForwardTimeSlack::initFTS(PDPTWData const &data, Route const &route)
+{
+    int n = route.getSize();
+    std::vector<int> const &routeIDs = route.getRoute();
+
+    earliestArrival = std::vector<TimeInteger>(n + 1, 0);
+    latestArrival = std::vector<TimeInteger>(n + 1, 0);
+    FTS = std::vector<TimeInteger>(n + 1, 0);
+
+    // Compute arrival times
+    double depotStart = data.getDepot().getTimeWindow().getStart();
+    double firstLocationStart = data.getLocation(routeIDs.at(0)).getTimeWindow().getStart();
+    double depotToFirst = data::TravelTime(data, 0, routeIDs.at(0));
+
+    earliestArrival.at(0) = std::max(firstLocationStart, depotStart + depotToFirst);
+
+    for (int i = 1; i < n; ++i)
+    {
+        double start = data.getLocation(routeIDs.at(i)).getTimeWindow().getStart();
+        double service = data.getLocation(routeIDs.at(i - 1)).getServiceDuration();
+        double travelTime = data::TravelTime(data, routeIDs.at(i - 1), routeIDs.at(i));
+
+        earliestArrival.at(i) = std::max(start, earliestArrival.at(i - 1) + service + travelTime);
+    }
+
+    // Compute earliest arrival at depot after last location
+    double lastService = data.getLocation(routeIDs.at(n - 1)).getServiceDuration();
+    double lastToDepot = data::TravelTime(data, routeIDs.at(n - 1), 0);
+    earliestArrival.at(n) = earliestArrival.at(n - 1) + lastService + lastToDepot;
+
+    // Compute latest arrival times
+    latestArrival.at(n - 1) = data.getLocation(routeIDs.at(n - 1)).getTimeWindow().getEnd();
+
+    for (int i = n - 2; i >= 0; --i)
+    {
+        double end = data.getLocation(routeIDs.at(i)).getTimeWindow().getEnd();
+        double service = data.getLocation(routeIDs.at(i)).getServiceDuration();
+        double travelTime = data::TravelTime(data, routeIDs.at(i), routeIDs.at(i + 1));
+
+        latestArrival.at(i) = std::min(latestArrival.at(i + 1) - service - travelTime, end);
+    }
+
+    // latest arrival at depot
+    latestArrival.at(n) = data.getDepot().getTimeWindow().getEnd();
+
+    // Compute FTS
+    for (int i = 0; i <= n; ++i)
+    {
+        FTS.at(i) = latestArrival.at(i) - earliestArrival.at(i);
+    }
+}
+
+bool ForwardTimeSlack::isPickupDeliveryInsertionValid(PDPTWData const &data, Route const &route, int pickupID,
+                                                      int deliveryID, int insertPickupIndex,
+                                                      int insertDeliveryIndex) const
+{
+    std::vector<int> const &routeIDs = route.getRoute();
+    int n = route.getSize();
+
+    // safety
+    if (insertPickupIndex > insertDeliveryIndex)
+    {
+        return false;
+    }
+
+    // if the route is empty, only check de time window
+    if (routeIDs.empty())
+    {
+        double startTW = data.getLocation(pickupID).getTimeWindow().getStart();
+        double endTW = data.getLocation(deliveryID).getTimeWindow().getEnd();
+
+        return (insertPickupIndex == 0) && (insertDeliveryIndex == 0) &&
+               (!(startTW > data.getDepot().getTimeWindow().getEnd() ||
+                  endTW < data.getDepot().getTimeWindow().getStart()));
+    }
+
+
+    // Algo
+
+    // Pickup
+    // two specific cases, insertion in first or last
+    int prev = (insertPickupIndex == 0) ? 0 : routeIDs.at(insertPickupIndex - 1);
+    int next = (insertPickupIndex == n) ? 0 : routeIDs.at(insertPickupIndex);
+
+    double arrivalPrev =
+            (prev == 0) ? data.getDepot().getTimeWindow().getStart() : getEarliestArrival().at(insertPickupIndex - 1);
+    double travelToNew = data::TravelTime(data, prev, pickupID);
+    double serviceNew = data.getLocation(pickupID).getServiceDuration();
+    double travelNewToNext = data::TravelTime(data, pickupID, next);
+
+    double newArrival = std::max(data.getLocation(pickupID).getTimeWindow().getStart(),
+                                 arrivalPrev + data.getLocation(prev).getServiceDuration() + travelToNew);
+
+
+    // Check TW
+    if (!(data.getLocation(pickupID).getTimeWindow().isValid(newArrival)))
+    {
+        return false;
+    }
+
+    // Calculate the pickup duration
+    double arrivalNext =
+            std::max(data.getLocation(next).getTimeWindow().getStart(), newArrival + serviceNew + travelNewToNext);
+
+    double pickupDuration = arrivalNext - earliestArrival.at(insertPickupIndex);
+    // Check FTS
+    if (/*next != 0 &&*/ pickupDuration >= getFTS().at(insertPickupIndex))
+    {
+        return false;
+    }
+
+    // Delivery
+    // if insertDeliveryIndex == insertPickupIndex, then Pickup is just before Delivery in the route
+    int prevDelivery = (insertDeliveryIndex == insertPickupIndex) ? pickupID : routeIDs.at(insertDeliveryIndex - 1);
+    int nextDelivery = (insertDeliveryIndex >= n) ? 0 : routeIDs.at(insertDeliveryIndex);
+
+    // We have to take into account the duration of the pickup
+    // (previous earliest arrival) + (time taken by the pickup) - (time of traveling between prev and next)
+    double arrivalPrevDelivery =
+            (prevDelivery == pickupID) ? newArrival : getEarliestArrival().at(insertDeliveryIndex - 1) + pickupDuration;
+
+    double travelToDelivery = data::TravelTime(data, prevDelivery, deliveryID);
+    double serviceDelivery = data.getLocation(deliveryID).getServiceDuration();
+    double travelDeliveryToNext = data::TravelTime(data, deliveryID, nextDelivery);
+    double newArrivalDelivery =
+            std::max(data.getLocation(deliveryID).getTimeWindow().getStart(),
+                     arrivalPrevDelivery + data.getLocation(prevDelivery).getServiceDuration() + travelToDelivery);
+
+    // Check TW
+    if (!(data.getLocation(deliveryID).getTimeWindow().isValid(newArrivalDelivery)))
+    {
+        return false;
+    }
+
+    // Calculate the delivery duration
+    double arrivalNextDelivery = std::max(data.getLocation(nextDelivery).getTimeWindow().getStart(),
+                                          newArrivalDelivery + serviceDelivery + travelDeliveryToNext);
+    double deliveryDuration = arrivalNextDelivery - earliestArrival.at(insertDeliveryIndex);
+
+    // Check FTS validity
+    if (/*nextDelivery != 0 &&*/ deliveryDuration >= getFTS().at(insertDeliveryIndex))
+    {
+        return false;
+    }
+
+    return true;
+}
+
+// TO DO some cuts in the loop to avoid recalculate everything
+void ForwardTimeSlack::updateFTSAfterInsertion(PDPTWData const &data, Route const &route, int insertPickupIndex,
+                                               int insertDeliveryIndex)
+{
+    int n = route.getSize();
+    std::vector<int> const &routeIDs = route.getRoute();
+
+    // Resize vectors to match the updated route size
+    earliestArrival.resize(n + 1, 0);
+    latestArrival.resize(n + 1, 0);
+    FTS.resize(n + 1, 0);
+
+    // Recalculate earliest arrival times
+    for (int i = insertPickupIndex; i <= n; ++i)
+    {
+        if (i == 0)// specific case for the first element
+        {
+            double depotStart = data.getDepot().getTimeWindow().getStart();
+            double firstLocationStart = data.getLocation(routeIDs.at(0)).getTimeWindow().getStart();
+            double depotToFirst = data::TravelTime(data, 0, routeIDs.at(0));
+            earliestArrival.at(0) = std::max(firstLocationStart, depotStart + depotToFirst);
+        }
+        else
+        {
+            int prev = routeIDs.at(i - 1);
+            int curr = (i == n) ? 0 : routeIDs.at(i);// specific case for the last element
+            double start = data.getLocation(curr).getTimeWindow().getStart();
+            double service = data.getLocation(prev).getServiceDuration();
+            double travelTime = data::TravelTime(data, prev, curr);
+
+            earliestArrival.at(i) = std::max(start, earliestArrival.at(i - 1) + service + travelTime);
+        }
+    }
+
+    // try add element in front then recalculate from the delivery index
+    // Recalculate latest arrival times
+    latestArrival.at(n) = data.getDepot().getTimeWindow().getEnd();
+    latestArrival.at(n - 1) = data.getLocation(routeIDs.at(n - 1)).getTimeWindow().getEnd();
+    for (int i = n - 2; i >= 0; --i)
+    {
+        double end = data.getLocation(routeIDs.at(i)).getTimeWindow().getEnd();
+        double service = data.getLocation(routeIDs.at(i)).getServiceDuration();
+        double travelTime = data::TravelTime(data, routeIDs.at(i), routeIDs.at(i + 1));
+
+        latestArrival.at(i) = std::min(latestArrival.at(i + 1) - service - travelTime, end);
+    }
+
+    // Recalculate FTS
+    for (int i = 0; i <= n; ++i)
+    {
+        FTS.at(i) = latestArrival.at(i) - earliestArrival.at(i);
+    }
+}
+
+// TO DO some cuts in the loop to avoid recalculate everything
+void ForwardTimeSlack::updateFTSAfterDeletion(PDPTWData const &data, Route const &route, int removePickupIndex,
+                                              int removeDeliveryIndex)
+{
+    int n = route.getSize();
+    std::vector<int> const &routeIDs = route.getRoute();
+
+    // empty route
+    if (n == 0)
+    {
+        earliestArrival.clear();
+        latestArrival.clear();
+        FTS.clear();
+        return;
+    }
+
+    // Resize vectors to match the updated route size
+    earliestArrival.resize(n + 1, 0);
+    latestArrival.resize(n + 1, 0);
+    FTS.resize(n + 1, 0);
+
+    // Recalculate earliest arrival times
+    for (int i = 0; i <= n; ++i)
+    {
+        if (i == 0)// Specific case for the first element
+        {
+            double depotStart = data.getDepot().getTimeWindow().getStart();
+            double firstLocationStart = data.getLocation(routeIDs.at(0)).getTimeWindow().getStart();
+            double depotToFirst = data::TravelTime(data, 0, routeIDs.at(0));
+            earliestArrival.at(0) = std::max(firstLocationStart, depotStart + depotToFirst);
+        }
+        else
+        {
+            int prev = routeIDs.at(i - 1);
+            int curr = (i == n) ? 0 : routeIDs.at(i);
+            double start = data.getLocation(curr).getTimeWindow().getStart();
+            double service = data.getLocation(prev).getServiceDuration();
+            double travelTime = data::TravelTime(data, prev, curr);
+
+            earliestArrival.at(i) = std::max(start, earliestArrival.at(i - 1) + service + travelTime);
+        }
+    }
+
+    // Recalculate latest arrival times
+    latestArrival.at(n) = data.getDepot().getTimeWindow().getEnd();
+    latestArrival.at(n - 1) = data.getLocation(routeIDs.at(n - 1)).getTimeWindow().getEnd();
+    for (int i = n - 2; i >= 0; --i)
+    {
+        double end = data.getLocation(routeIDs.at(i)).getTimeWindow().getEnd();
+        double service = data.getLocation(routeIDs.at(i)).getServiceDuration();
+        double travelTime = data::TravelTime(data, routeIDs.at(i), routeIDs.at(i + 1));
+
+        latestArrival.at(i) = std::min(latestArrival.at(i + 1) - service - travelTime, end);
+    }
+
+    // Recalculate FTS
+    for (int i = 0; i <= n; ++i)
+    {
+        FTS.at(i) = latestArrival.at(i) - earliestArrival.at(i);
+    }
+}
+
+void ForwardTimeSlack::print() const
+{
+    for (TimeInteger timeVal: earliestArrival)
+    {
+        std::cout << timeVal << " ";
+    }
+    std::cout << std::endl;
+    for (TimeInteger timeVal: latestArrival)
+    {
+        std::cout << timeVal << " ";
+    }
+    std::cout << std::endl;
+    for (TimeInteger ftsVal: FTS)
+    {
+        std::cout << ftsVal << " ";
+    }
+}
\ No newline at end of file
diff --git a/src/lns/constraints/time_window/forward_time_slack.h b/src/lns/constraints/time_window/forward_time_slack.h
new file mode 100644
index 0000000000000000000000000000000000000000..041be4bd5d6c1ab58fff1562848a4af62ff60bb9
--- /dev/null
+++ b/src/lns/constraints/time_window/forward_time_slack.h
@@ -0,0 +1,50 @@
+#pragma once
+
+#include "lns/solution/route.h"
+#include "types.h"
+
+/*
+ *  Represent the forward time slack of a route.
+ */
+class ForwardTimeSlack
+{
+private:
+    std::vector<TimeInteger> earliestArrival;
+    std::vector<TimeInteger> latestArrival;
+    std::vector<TimeInteger> FTS;
+
+public:
+    explicit ForwardTimeSlack() = default;
+
+    /*
+     *  Check if the insertion of a new pickup/delivery pair is feasible.
+     *  ForwardTimeSlack is supposed to be correct. Only check FTS and Time windows.
+     */
+    bool isPickupDeliveryInsertionValid(PDPTWData const &data, Route const &route, int pickupID, int deliveryID,
+                                        int insertPickupIndex, int insertDeliveryIndex) const;
+
+    /*
+     *  Compute FTS values from scratch.
+     */
+    void initFTS(PDPTWData const &data, Route const &route);
+
+    /*
+     *  Update FTS.
+     *  Suppose the route has already been updated (but not the FTS)
+     */
+    void updateFTSAfterInsertion(PDPTWData const &data, Route const &route, int insertPickupIndex,
+                                 int insertDeliveryIndex);
+    /*
+     *  Update FTS.
+     *  Suppose the route has already been updated (but not the FTS)
+     */
+    void updateFTSAfterDeletion(PDPTWData const &data, Route const &route, int removePickupIndex,
+        int removeDeliveryIndex);
+
+
+    std::vector<TimeInteger> const &getFTS() const;
+    std::vector<TimeInteger> const &getEarliestArrival() const;
+    std::vector<TimeInteger> const &getLatestArrival() const;
+
+    void print() const;
+};
\ 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 7211e4cec720d7a92975003c30cee0ba62a5cde3..3126599b82b66b897269a4f1869d938742f10391 100644
--- a/src/lns/constraints/time_window/time_window_constraint.cpp
+++ b/src/lns/constraints/time_window/time_window_constraint.cpp
@@ -3,6 +3,7 @@
 #include "input/data.h"
 #include "input/pdptw_data.h"
 #include "input/time_window.h"
+#include "lns/constraints/time_window/forward_time_slack.h"
 #include "lns/modification/pair/insert_pair.h"
 #include "lns/modification/pair/remove_pair.h"
 #include "lns/modification/route/remove_route.h"
@@ -10,181 +11,71 @@
 
 TimeWindowConstraint::TimeWindowConstraint(Solution const &solution) : Constraint(solution)
 {
-    allRouteReachTimes.clear();
-    for (unsigned int i = 0; i < solution.getRoutes().size(); ++i)
+    FTSContainer.clear();
+    for (Route const &route: solution.getRoutes())
     {
-        allRouteReachTimes.emplace_back();
+        FTSContainer.emplace_back();
     }
 }
 
 TimeWindowConstraint::~TimeWindowConstraint()
 {
-    allRouteReachTimes.clear();
+    //allRouteReachTimes.clear();
+    FTSContainer.clear();
 }
 
 std::unique_ptr<Constraint> TimeWindowConstraint::clone(Solution const &newOwningSolution) const
 {
     std::unique_ptr<TimeWindowConstraint> clonePtr = std::make_unique<TimeWindowConstraint>(newOwningSolution);
-    clonePtr->allRouteReachTimes = allRouteReachTimes;
+    //clonePtr->allRouteReachTimes = allRouteReachTimes;
+    clonePtr->FTSContainer = FTSContainer;
     return clonePtr;
 }
 
-void TimeWindowConstraint::computeReachTimes(PDPTWData const &data, std::vector<int> const &routeIDs,
-                                             ReachTimeVector &reachTimes) const
+void TimeWindowConstraint::initFTS()
 {
-    // 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)
-    {
-        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();
-        TimeInteger startTW = data.getLocation(routeIDs.at(i - 1)).getTimeWindow().getStart();
-
-        reachTimes.at(i) = std::max(reachTimes.at(i - 1), startTW) + serviceTime + travelTime;
-    }
-}
-
-void TimeWindowConstraint::initReachTimes()
-{
-    allRouteReachTimes = std::vector<ReachTimeVector>();
+    FTSContainer = std::vector<ForwardTimeSlack>();
+    //reserve
     int i = 0;
     for (Route const &route: getSolution().getRoutes())
     {
-        // init and calculate reach time value
-        allRouteReachTimes.emplace_back();
-        computeReachTimes(getSolution().getData(), route.getRoute(), allRouteReachTimes.at(i));
+        FTSContainer.emplace_back();
+        FTSContainer.at(i).initFTS(getSolution().getData(), route);
         ++i;
     }
 }
 
-// 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(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());
-    // 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)
-    // {
-    //     std::cout << pos << " ";
-    // }
-    // std::cout << "\n";
-
-    // Compute new reach time
-    computeReachTimes(data, route, newReachTimes);
-
-    // std::cout << "\n";
-    // for (auto pos : newReachTimes)
-    // {
-    //     std::cout << pos << " ";
-    // }
-    // std::cout << "\n";
-
-    // Check Time Windows
-    for (int i = 0; i < newReachTimes.size(); ++i)
-    {
-        if (!data.getLocation(route.at(i)).getTimeWindow().isValid(newReachTimes.at(i)))
-        {
-            return false;
-        }
-    }
-    return true;
+    return FTSContainer.at(routeIndex)
+            .isPickupDeliveryInsertionValid(data,
+                                            getSolution().getRoute(routeIndex),
+                                            pair.getPickup().getId(),
+                                            pair.getDelivery().getId(),
+                                            pickupPos,
+                                            deliveryPos);
 }
 
-// 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();
-
-    // // 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())
+    if (addPair)
     {
-        allRouteReachTimes.at(routeIndex).clear();
+        FTSContainer.at(routeIndex)
+                .updateFTSAfterInsertion(data, getSolution().getRoute(routeIndex), pickupPos, deliveryPos);
     }
     else
     {
-        allRouteReachTimes.at(routeIndex).resize(routeIDs.size(), 0);
-
-        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;
-        }
+        FTSContainer.at(routeIndex)
+                .updateFTSAfterDeletion(data, getSolution().getRoute(routeIndex), pickupPos, deliveryPos);
     }
+
 }
 
 bool TimeWindowConstraint::check(InsertPair const &op) const
 {
-    //std::cout << " #TW Check";
     return checkInsertion(getSolution().getData(),
                           op.getPair(),
                           op.getRouteIndex(),
@@ -194,7 +85,6 @@ bool TimeWindowConstraint::check(InsertPair const &op) const
 
 void TimeWindowConstraint::apply(InsertPair const &op)
 {
-    //std::cout << "-> Apply Modification on Time Windows \n";
     ApplyModif(getSolution().getData(),
                op.getPair(),
                op.getRouteIndex(),
@@ -210,7 +100,7 @@ bool TimeWindowConstraint::check(InsertRoute const &op) const
 
 void TimeWindowConstraint::apply(InsertRoute const &op)
 {
-    allRouteReachTimes.emplace_back();
+    FTSContainer.emplace_back();
 }
 
 bool TimeWindowConstraint::check(RemovePair const &op) const
@@ -235,27 +125,18 @@ bool TimeWindowConstraint::check(RemoveRoute const &op) const
 
 void TimeWindowConstraint::apply(RemoveRoute const &op)
 {
-    allRouteReachTimes.erase(allRouteReachTimes.begin() + op.getRouteIndex());
-}
-
-std::vector<TimeWindowConstraint::ReachTimeVector> const &TimeWindowConstraint::getallRouteReachTimes() const
-{
-    return allRouteReachTimes;
+    FTSContainer.erase(FTSContainer.begin() + op.getRouteIndex());
 }
 
 void TimeWindowConstraint::print() const
 {
-    std::cout << "Reach Times : \n";
+    std::cout << "Time Window : Earliest / Latest / FTS" << std::endl;
     int i = 0;
-    for (auto const &reachTimes: getallRouteReachTimes())
+    for (ForwardTimeSlack FTS: FTSContainer)
     {
-        //std::cout << reachTimes.size() << ", ";
-        std::cout << "#" << i << " : ";
-        for (const TimeInteger reachTime: reachTimes)
-        {
-            std::cout << reachTime << ", ";
-        }
-        std::cout << "\n";
+        std::cout << "#" << i << std::endl;
+        FTS.print();
+        std::cout << std::endl;
         i++;
     }
 }
diff --git a/src/lns/constraints/time_window/time_window_constraint.h b/src/lns/constraints/time_window/time_window_constraint.h
index 915d6f8417f96e190564c98d1a58533dac0b11a7..bb4555801f3fa9eda0be4bb99f7d3a0c1491c437 100644
--- a/src/lns/constraints/time_window/time_window_constraint.h
+++ b/src/lns/constraints/time_window/time_window_constraint.h
@@ -1,9 +1,11 @@
 #pragma once
 
-#include "lns/constraints/constraint.h"
 #include "input/pair.h"
 #include "input/time_window.h"
+#include "lns/constraints/constraint.h"
+#include "lns/constraints/time_window/forward_time_slack.h"
 #include "lns/solution/route.h"
+
 #include <vector>
 
 /**
@@ -17,59 +19,44 @@ class TimeWindowConstraint : public Constraint
 public:
     using ReachTimeVector = std::vector<TimeInteger>;
 
+
     explicit TimeWindowConstraint(Solution const &);
     TimeWindowConstraint(TimeWindowConstraint const &) = default;
     ~TimeWindowConstraint() override;
 
-    // Given the solution, calculate the reachTimes of each location.
-    // Modify the routeCapacities vector !
-    void initReachTimes();
+
+    /**
+     *  Initialize the FTS vectors
+     */
+    void initFTS();
 
     std::unique_ptr<Constraint> clone(Solution const &newOwningSolution) const override;
-    
-    const std::vector<ReachTimeVector> & getallRouteReachTimes() const;
 
-    void print() const override;
-private:
 
-    /**
-    *   For each route, store the reach time of each location
-    */
-    std::vector<ReachTimeVector> allRouteReachTimes;  
-
-    // Recalcul tous les reachTimes pour une route
-    ReachTimeVector computeReachTimes(const Route& route) const;
-    bool updateReachTimes(const PDPTWData& data, Pair & pair,int routeIndex, int pickupPos, int deliveryPos);
+    void print() const override;
 
-    /**
-    *   Check if the insertion of a pair pickup/delivery is valid or not.
-    *   COPY the route where we insert the pair !
-    */
-    bool checkInsertion(const PDPTWData& data, const Pair & pair, int routeIndex, int pickupPos, int deliveryPos) const; 
+private:
+    std::vector<ForwardTimeSlack> FTSContainer;
 
     /**
-    *   Given route IDs, compute the reachTimes of the route.
-    *   If a vehicule is in advance, set the reach time to start of the timeWindow.
-    *   Modify reachTimes vector !
-    */
-    void computeReachTimes(const PDPTWData& data, const std::vector<int> & routeIDs, ReachTimeVector & reachTimes) const;
+     *  Check if the insertion of a pair pickup/delivery is valid or not.
+     *  COPY the route where we insert the pair !
+     */
+    bool checkInsertion(PDPTWData const &data, Pair const &pair, int routeIndex, int pickupPos, int deliveryPos) const;
 
     /**
-    *   Given route IDs, modify the reachTimes
-    */
-    void ApplyModif(const PDPTWData& data, const Pair & pair, int routeIndex, int pickupPos, int deliveryPos,  bool addPair);
-
+     *  Apply the modification to the time window constraint
+     */
+    void ApplyModif(PDPTWData const &data, Pair const &pair, int routeIndex, int pickupPos, int deliveryPos,
+                    bool addPair);
 
     void apply(InsertPair const &op) override;
     void apply(InsertRoute const &op) override;
     void apply(RemovePair const &op) override;
     void apply(RemoveRoute const &op) override;
- 
+
     bool check(InsertPair const &op) const override;
     bool check(InsertRoute const &op) const override;
     bool check(RemovePair const &op) const override;
     bool check(RemoveRoute const &op) const override;
-
-public: 
-
 };
\ No newline at end of file
diff --git a/src/lns/lns.cpp b/src/lns/lns.cpp
index c82a637767f7c1727264a8491a636f3eaedaf882..8735e5ea97ca005096fb8e0307dffa57be5273b3 100644
--- a/src/lns/lns.cpp
+++ b/src/lns/lns.cpp
@@ -81,7 +81,7 @@ output::LnsOutput lns::runLns(Solution const &initialSolution, OperatorSelector
     LnsRuntimeData runtime = {actualSolution};
 
     // temporary fixed iteration
-    int iterationMax = 200;
+    int iterationMax = 100;
     while (iterationMax > 0)
     {
         // Init iteration
diff --git a/src/lns/operators/destruction/clean_empty_route.cpp b/src/lns/operators/destruction/clean_empty_route.cpp
index aaeeede3114558cd30f7026e15fe970cd1944520..edd796874a9fa8c100949e5cfcbb63b7f49566e2 100644
--- a/src/lns/operators/destruction/clean_empty_route.cpp
+++ b/src/lns/operators/destruction/clean_empty_route.cpp
@@ -5,6 +5,7 @@ CleanEmptyRoute::CleanEmptyRoute() {}
 
 void CleanEmptyRoute::destroySolution(Solution &solution) const
 {
+    std::cout << "Clean ";
     for (int routeIndex = solution.getRoutes().size() - 1; routeIndex >= 0; --routeIndex)
     {
         if (solution.getRoute(routeIndex).getRoute().empty())
diff --git a/src/lns/solution/solution.cpp b/src/lns/solution/solution.cpp
index 1bb0132f589df8b07343f6a32ea4f4eb310d7a5b..0a975ed32ea38a1d07fbbb70888fdf6073ab2160 100644
--- a/src/lns/solution/solution.cpp
+++ b/src/lns/solution/solution.cpp
@@ -4,6 +4,7 @@
 #include "input/data.h"
 #include "input/time_window.h"
 #include "lns/constraints/capacity/capacity_constraint.h"
+#include "lns/constraints/constraint.h"
 #include "lns/constraints/time_window/time_window_constraint.h"
 #include "lns/solution/route.h"
 #include "output/solution_checker.h"
@@ -50,7 +51,7 @@ void Solution::computeAndStoreSolutionCost()
 
 double Solution::computeSolutionCost() const
 {
-    double cost = 0;
+    double cost = 0.0;
     for (Route const &route: getRoutes())
     {
         cost += data::routeCost(data, route);
@@ -205,6 +206,11 @@ PDPTWData const &Solution::getData() const
     return data.get();
 }
 
+std::vector<std::unique_ptr<Constraint>> const &Solution::getConstraints() const
+{
+    return constraints;
+}
+
 int Solution::requestsFulFilledCount() const
 {
     int count = 0;
diff --git a/src/lns/solution/solution.h b/src/lns/solution/solution.h
index 874c74186ad96bb9c2d2a18fc656fd1cc10f2815..4ad16c4f7e240e525629eca2297b9a63d7ebcf14 100644
--- a/src/lns/solution/solution.h
+++ b/src/lns/solution/solution.h
@@ -77,6 +77,7 @@ public:
     double getRawCost() const;
     double getCost() const;
     unsigned int missingPairCount() const;
+    std::vector<std::unique_ptr<Constraint>> const &getConstraints() const;
 
     /**
      *  Return the route index associated to the given location ID.
diff --git a/src/mains/main.cpp b/src/mains/main.cpp
index ddbdd0189ca0019f3ae6845a773d860189949878..1b4227b9cf26a8ff2ae75e3569834a7d28d8885f 100644
--- a/src/mains/main.cpp
+++ b/src/mains/main.cpp
@@ -6,6 +6,7 @@
 #include "input/time_window.h"
 #include "lns/acceptance/threshold_acceptance.h"
 #include "lns/constraints/capacity/capacity_constraint.h"
+#include "lns/constraints/time_window/forward_time_slack.h"
 #include "lns/constraints/time_window/time_window_constraint.h"
 #include "lns/lns.h"
 #include "lns/modification/pair/insert_pair.h"
@@ -24,11 +25,15 @@
 #include "lns/operators/sorting_strategy.h"
 #include "lns/solution/solution.h"
 #include "mains/main_interface.h"
+#include "output/solution_checker.h"
 #include "output/solution_exporter.h"
+#include "types.h"
 
 #include <filesystem>
 #include <fstream>
+#include <iomanip>
 #include <iostream>
+#include <limits>
 #include <nlohmann/json.hpp>
 #include <spdlog/spdlog.h>
 #include <string>
@@ -51,40 +56,28 @@ void simpleLNS(PDPTWData const &data, Solution &startingSolution)
     SimpleOperatorSelector RandomDestroy_BestInsert;
     addAllReconstructor(RandomDestroy_BestInsert);
     RandomDestroy_BestInsert.addDestructor(RandomDestroy(pairs));
-    RandomDestroy_BestInsert.addDestructor(StringRemoval(10,10));
-    RandomDestroy_BestInsert.addDestructor(CleanEmptyRoute());
+    RandomDestroy_BestInsert.addDestructor(StringRemoval(10, 10));
 
     SimpleOperatorSelector largeSelector;
     addAllReconstructor(largeSelector);
     largeSelector.addDestructor(RandomDestroy(manyPairs));
-    largeSelector.addDestructor(StringRemoval(10,10));
-    largeSelector.addDestructor(CleanEmptyRoute());
+    largeSelector.addDestructor(StringRemoval(10, 10));
 
-    // SimpleOperatorSelector veryLargeSelector;
-    // addAllReconstructor(veryLargeSelector);
-    // veryLargeSelector.addDestructor(RandomDestroy(pairs));
-
-    // SimpleOperatorSelector hugeSelector;
-    // addAllReconstructor(hugeSelector);
-    // hugeSelector.addDestructor(RandomDestroy(pairs));
-
-    // SimpleOperatorSelector lastSelector;
-    // addAllReconstructor(lastSelector);
-    // lastSelector.addDestructor(RandomDestroy(manyPairs));
 
     std::vector<SmallLargeOperatorSelector::StepSelector> selectors;
     selectors.emplace_back(10, std::move(RandomDestroy_BestInsert));
     selectors.emplace_back(50, std::move(largeSelector));
-    // selectors.emplace_back(2, std::move(veryLargeSelector));
-    // selectors.emplace_back(2, std::move(hugeSelector));
-    // selectors.emplace_back(2, std::move(lastSelector));
+
     SmallLargeOperatorSelector smallLargeSelector(std::move(selectors));
 
     // run lns
     output::LnsOutput result = lns::runLns(startingSolution, smallLargeSelector, acceptor);
-    
-    result.getBestSolution().print();
-    std::cout << result.getNumberOfIteration() << " " << result.getTimeSpent() << std::endl;
+
+    Solution sol = result.getBestSolution();
+
+    CleanEmptyRoute clean = CleanEmptyRoute();
+    clean.destroySolution(sol);
+    sol.print();
 }
 
 int main(int argc, char **argv)
@@ -93,35 +86,14 @@ int main(int argc, char **argv)
 
     ///////////////////////////////////////////////////////////////////////
 
-    //std::string filepath = "/home/a24jacqb/Documents/Code/pdptw-main/data_in/n100/bar-n100-1.json";
-    std::string filepath = "/home/a24jacqb/Documents/Code/pdptw-main/data_in/pdp_100/lrc201.json";
+    std::string filepath = "/home/a24jacqb/Documents/Code/pdptw-main/data_in/n100/bar-n100-1.json";
+    //std::string filepath = "/home/a24jacqb/Documents/Code/pdptw-main/data_in/pdp_100/lc102.json";
     //std::string filepath = "/home/a24jacqb/Documents/Code/pdptw-main/data_in/Nantes_1.json";
     //std::string filepath = "/home/a24jacqb/Documents/Code/pdptw-main/data_in/n5000/bar-n5000-1.json";
 
     PDPTWData data = parsing::parseJson(filepath);
     Solution startingSolution = Solution::emptySolution(data);
-
-    startingSolution.print();
-
-    //data.print();
-
     simpleLNS(data, startingSolution);
 
-
-    ///
-    // std::cout << "===== TEST ===== \n";
-    // Solution testSolution = Solution::emptySolution(data);
-    // ListHeuristicCostOriented reconstruction = ListHeuristicCostOriented(SortingStrategyType::SHUFFLE, EnumerationType::ALL_INSERT_PAIR);
-    // reconstruction.reconstructSolution(testSolution, 0.01);
-
-    // testSolution.print();
-
-    // std::cout << "============ \n";
-
-    // StringRemoval StringRemoval(10,10);
-    // StringRemoval.destroySolution(testSolution);
-
-    // testSolution.print();
-
     return 0;
 }
diff --git a/src/output/solution_checker.cpp b/src/output/solution_checker.cpp
index f1663b919cece492b73338619fbae47e4af50f8b..6be2f13471e5daa5b6c8f7540776bad87b2075a5 100644
--- a/src/output/solution_checker.cpp
+++ b/src/output/solution_checker.cpp
@@ -3,6 +3,7 @@
 #include "input/data.h"
 #include "input/location.h"
 #include "input/pdptw_data.h"
+#include "lns/operators/destruction/clean_empty_route.h"
 #include "lns/solution/solution.h"
 #include "types.h"
 
@@ -64,7 +65,6 @@ void checker::checkSolutionCoherence(Solution const &sol, PDPTWData const &data)
 
     if (errorFlag)
     {
-        sol.print();
         throw SolutionConstraintError("Error in the consistency of the solution.", sol);
     }
 }