diff --git a/CMakeLists.txt b/CMakeLists.txt
index 1501935cd61d4bfdd042afe7a07ce369e3d852ea..673f879fd84c4500889c760bc545d691693ac8f6 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -39,6 +39,7 @@ add_executable(pdptw src/mains/main.cpp
                 src/output/solution_exporter.cpp
                 src/lns/operators/sorting_strategy.cpp
                 src/lns/operators/destruction/random_destroy.cpp
+                src/lns/operators/destruction/string_removal.cpp
                 src/lns/operators/reconstruction/enumerate.cpp
                 src/lns/operators/reconstruction/list_heuristic_insertion.cpp
                 src/lns/operators/reconstruction/list_heuristic_cost_oriented.cpp
diff --git a/src/input/pdptw_data.cpp b/src/input/pdptw_data.cpp
index 9542f7e1253d4230018e53cb1697f616ef11b8f3..d226a7dce24a25d14d39ae62ad9766ff94a677a9 100644
--- a/src/input/pdptw_data.cpp
+++ b/src/input/pdptw_data.cpp
@@ -1,10 +1,13 @@
 #include "pdptw_data.h"
 
-#include <iostream>
+#include "data.h"
+
+#include <algorithm>
 #include <fstream>
+#include <iostream>
+#include <numeric>
 #include <spdlog/spdlog.h>
 
-
 int PDPTWData::getSize() const
 {
     return size;
@@ -15,12 +18,12 @@ int PDPTWData::getCapacity() const
     return capacity;
 }
 
-std::vector<Location> const &PDPTWData::getLocations() const 
+std::vector<Location> const &PDPTWData::getLocations() const
 {
     return locations;
 }
 
-std::vector<Pair> const &PDPTWData::getPairs() const 
+std::vector<Pair> const &PDPTWData::getPairs() const
 {
     return pairs;
 }
@@ -37,12 +40,12 @@ std::string PDPTWData::getDataName() const
 
 Location const &PDPTWData::getLocation(int id) const
 {
-    if (id==0)
+    if (id == 0)
     {
         return getDepot();
     }
     // location index from 0 to n-1
-    return locations.at(id -1);
+    return locations.at(id - 1);
 }
 
 Matrix const &PDPTWData::getMatrix() const
@@ -50,24 +53,28 @@ Matrix const &PDPTWData::getMatrix() const
     return distanceMatrix;
 }
 
-PDPTWData::PDPTWData(std::string dataName, int size, int capacity, Location depot, std::vector<Location> locations, Matrix distanceMatrix)
-    : dataName(dataName), size(size), capacity(capacity), depot(depot), locations(std::move(locations)), distanceMatrix(std::move(distanceMatrix)) 
+PDPTWData::PDPTWData(std::string dataName, int size, int capacity, Location depot, std::vector<Location> locations,
+                     Matrix distanceMatrix)
+    : dataName(dataName), size(size), capacity(capacity), depot(depot), locations(std::move(locations)),
+      distanceMatrix(std::move(distanceMatrix))
 {
     // Associate pair of locations
     pairs.clear();
-    for (const Location & loc : this->locations)
+    for (Location const &loc: this->locations)
     {
-        if( loc.getLocType() == LocType::PICKUP )
+        if (loc.getLocType() == LocType::PICKUP)
         {
             // vector indexed from 0 / Location indexed from 1
-            pairs.emplace_back(loc, this->locations.at(loc.getPair()-1), loc.getId());
+            pairs.emplace_back(loc, this->locations.at(loc.getPair() - 1), loc.getId());
         }
     }
+    // Compute closest location matrix
+    initClosestLocations();
 }
 
-const Pair &PDPTWData::getPair(int id) const
+Pair const &PDPTWData::getPair(int id) const
 {
-    for (const Pair &pair : pairs)
+    for (Pair const &pair: pairs)
     {
         if (id == pair.getID())
         {
@@ -83,8 +90,12 @@ int PDPTWData::getPairCount() const
     return getPairs().size();
 }
 
+int PDPTWData::getLocationCount() const
+{
+    return getLocations().size();
+}
 
-void PDPTWData::print() const 
+void PDPTWData::print() const
 {
     std::cout << "Instance name : " << dataName << "\n";
     std::cout << "Instance size: " << size << "\n";
@@ -93,22 +104,36 @@ void PDPTWData::print() const
     depot.print();
 
     std::cout << "Locations:\n";
-    for (const auto& loc : locations) {
+    for (auto const &loc: locations)
+    {
         loc.print();
     }
 
     std::cout << "Distance Matrix:\n";
-    for (const auto& row : distanceMatrix) {
-        for (const auto& dist : row) {
+    for (auto const &row: distanceMatrix)
+    {
+        for (auto const &dist: row)
+        {
             std::cout << dist << " ";
         }
         std::cout << "\n";
     }
 
+    std::cout << "Closest Matrix (no depot):\n";
+    for (auto const &row: closestLocations)
+    {
+        for (auto const &ID: row)
+        {
+            std::cout << ID << " ";
+        }
+        std::cout << "\n";
+    }
+
     std::cout << "Pair IDs:\n";
-    for (const auto& pair : pairs)
-    {;
-        std::cout << pair.getID() << " "; 
+    for (auto const &pair: pairs)
+    {
+        ;
+        std::cout << pair.getID() << " ";
     }
     std::cout << " \n";
 }
@@ -127,14 +152,13 @@ void PDPTWData::checkData() const
     }
 }
 
-
 bool PDPTWData::checkMatrix() const
 {
     // square matrix
-    
-    for (const auto& row : getMatrix()) 
+
+    for (auto const &row: getMatrix())
     {
-        if (row.size() != size) 
+        if (row.size() != size)
         {
             return true;
         }
@@ -161,22 +185,23 @@ bool PDPTWData::checkMatrix() const
 
 bool PDPTWData::checkLocation() const
 {
-
     // check if location id equals the position in the location vector
-    for (size_t i = 0; i < size-1; ++i) {
-        if (locations.at(i).getId() != static_cast<int>(i)+1) {
+    for (size_t i = 0; i < size - 1; ++i)
+    {
+        if (locations.at(i).getId() != static_cast<int>(i) + 1)
+        {
             return true;
         }
     }
-    
+
     // check if pair of location are well made (type, id, demand, timeWindow)
-    for(const Location& loc : getLocations()) 
+    for (Location const &loc: getLocations())
     {
         if (loc.getLocType() == LocType::PICKUP)
-        {   
-            if ( (getLocations().at(loc.getPair()-1).getLocType() != LocType::DELIVERY) 
-            || (loc.getDemand() != - getLocations().at(loc.getPair()-1).getDemand()) 
-            || (loc.getId() != getLocations().at(loc.getPair()-1).getPair()) )
+        {
+            if ((getLocations().at(loc.getPair() - 1).getLocType() != LocType::DELIVERY) ||
+                (loc.getDemand() != -getLocations().at(loc.getPair() - 1).getDemand()) ||
+                (loc.getId() != getLocations().at(loc.getPair() - 1).getPair()))
             {
                 return true;
             }
@@ -191,6 +216,40 @@ bool PDPTWData::checkLocation() const
     return false;
 }
 
+void PDPTWData::initClosestLocations()
+{
+    closestLocations.reserve(getLocationCount());
+    for (Location const &location: locations)
+    {
+        // sorting from closest to furthest using indexes
+        std::vector<int> closestLocationsIndexes(getLocationCount());
+        std::iota(closestLocationsIndexes.begin(), closestLocationsIndexes.end(), 0);
+
+        // Do the sorting
+        std::ranges::sort(closestLocationsIndexes, {}, [this, &location](int index) {
+            return data::TravelTime(*this, location.getId(), locations.at(index).getId());
+        });
+
+        // we store the indexes in the final container
+        closestLocations.emplace_back();
+        closestLocations.back().reserve(getLocationCount());
+        std::ranges::transform(closestLocationsIndexes, std::back_inserter(closestLocations.back()), [this](int index) {
+            return std::cref(locations.at(index)).get().getId();
+        });
+    }
+}
+
+std::vector<int> const &PDPTWData::getClosestLocationsID(int id) const
+{
+    // sanity check
+    if (id < 1 || id > getLocationCount())
+    {
+        spdlog::error("getClosestLocationsID: Location ID {} is out of valid range [1, {}]", id, getLocationCount());
+        throw std::out_of_range("Error: Location ID is out of valid range [1, " + std::to_string(getLocationCount()) +
+                                "]");
+    }
+    return closestLocations.at(id - 1);// vector indexed from 0
+}
 
 InputJsonException::InputJsonException(std::string_view reason)
     : reason(fmt::format("Input JSON file is incorrect : {}", reason))
diff --git a/src/input/pdptw_data.h b/src/input/pdptw_data.h
index 735cecb85a99ac9630e4829221d942cd4293a875..348e1e98b4caf8f097278080d29adf5e143f4a6c 100644
--- a/src/input/pdptw_data.h
+++ b/src/input/pdptw_data.h
@@ -30,6 +30,11 @@ class PDPTWData
     std::vector<Location> locations;
     std::vector<Pair> pairs;// std::unordered_map<int, Pair> pair; if getPair(index) is needed ?
     Matrix distanceMatrix;
+    // stores the list of locations ID from closest to furthest for every location (no depot).
+    std::vector<std::vector<int>> closestLocations;
+
+    void initClosestLocations();
+
 
 public:
     PDPTWData();
@@ -54,19 +59,25 @@ public:
 
 
     std::vector<Location> const &getLocations() const;
+    int getLocationCount() const;
     std::vector<Pair> const &getPairs() const;
     int getPairCount() const;
     Pair const &getPair(int id) const;
 
     /** 
-    *   0 return the depot.
-    *   Other numbers return the associated location.
-    */
+     *  0 return the depot.
+     *  Other numbers return the associated location.
+     */
     Location const &getLocation(int id) const;
     Location const &getDepot() const;
 
     Matrix const &getMatrix() const;
 
+    /** 
+     *  Given a location ID, return a list of location id sorted by proximity.
+     */
+    std::vector<int> const &getClosestLocationsID(int id) const;
+
     int getSize() const;
     int getCapacity() const;
     std::string getDataName() const;
diff --git a/src/lns/modification/pair/remove_pair.cpp b/src/lns/modification/pair/remove_pair.cpp
index 07e8a227da3fdecc1f7a47695ce47fc17a833da6..14a0144a6b47b39e9c61e25167c90bac6d027294 100644
--- a/src/lns/modification/pair/remove_pair.cpp
+++ b/src/lns/modification/pair/remove_pair.cpp
@@ -1,6 +1,7 @@
 #include "remove_pair.h"
 
 #include "input/data.h"
+#include "lns/solution/solution.h"
 
 RemovePair::RemovePair(int routeIndex, int pickupDeletion, int deliveryDeletion, Pair const &pair)
     : routeIndex(routeIndex), pickupDeletion(pickupDeletion), deliveryDeletion(deliveryDeletion),
diff --git a/src/lns/operators/destruction/random_destroy.cpp b/src/lns/operators/destruction/random_destroy.cpp
index 819029f8ca53928571d4cdb2b9bec765af1f099e..cb75473392e3b7f4cf166cf70e8197b26be77fe9 100644
--- a/src/lns/operators/destruction/random_destroy.cpp
+++ b/src/lns/operators/destruction/random_destroy.cpp
@@ -18,7 +18,7 @@ void RandomDestroy::destroySolution(Solution &solution) const
     while (remainingPairToDelete > 0)
     {
         // too complicated
-        // Other (simpler) option -> choose random route then choose random pair ?
+        // Other (simpler) option -> choose random route then choose random pair ? (does not respect equiprobability)
      
         // choose a random location
         int locationNumber = util::getRandomInt(0, remainingPairToDelete * 2 - 1);
diff --git a/src/lns/operators/destruction/string_removal.cpp b/src/lns/operators/destruction/string_removal.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..7ee2859dbdb55e53b63be128333d2d99e51192f5
--- /dev/null
+++ b/src/lns/operators/destruction/string_removal.cpp
@@ -0,0 +1,212 @@
+#include "string_removal.h"
+
+#include "input/location.h"
+#include "input/pair.h"
+#include "input/pdptw_data.h"
+#include "lns/modification/pair/remove_pair.h"
+#include "utils.h"
+
+#include <vector>
+
+namespace
+{
+
+    double computeAverageCardinality(std::vector<Route> const &routes)
+    {
+        if (routes.empty())
+        {
+            return 0;
+        }
+        int total_cardinality = 0;
+        for (Route const &route: routes)
+        {
+            total_cardinality += route.getSize();
+        }
+
+        return static_cast<double>(total_cardinality) / routes.size();
+    }
+
+    /**
+     *  Compute equations (8) and (9) from the SISR paper.
+     *  (8) Maximum cardinality of a string
+     *  (9) Cardinality of string to be removed
+     *  @return pair of (global maximum of string size, Cardinality of the string to be removed)
+     */
+    std::pair<unsigned int, unsigned int> computeStringsData(unsigned int maxStringSize, unsigned int routeSize)
+    {
+        // (8) "The maximum cardinality of each string is limited by the initial limit lmax_s and the tour’s cardinality |t|"
+        unsigned int maxSizeOfString = std::min(maxStringSize, routeSize);
+
+        // (9) "the cardinality for the string to be removed from tour t is obtained by rounding down a real value selected from U(Lmin, lmax_t+1)"
+        unsigned int actualSizeOfString = util::getRandomInt(1, maxSizeOfString);
+
+        return {maxSizeOfString, actualSizeOfString};
+    }
+
+    // t, l_t, c^*_t
+    /**
+     * Remove a string in the solution
+     * For now it uses startLocation as the center of the string
+     * @param pathIndex the path on which the removal happens
+     * @param stringLength the number of requests to remove, expect it to be inferior to the number of requests in the path
+     * @param startLocation the location found to start the string, does not mean it will the smallest index removed
+     */
+    void removeString(Solution &solution, int routeIndex, unsigned int stringLength, int startLocation)
+    {
+        std::cout << "remove string" << std::endl;
+        // ID of pair to remove
+        std::vector<int> toRemove;
+        toRemove.reserve(stringLength);
+
+        PDPTWData const &data = solution.getData();
+        Route const &route = solution.getRoute(routeIndex);
+        std::vector<int> const &routeLocationIDs = route.getRoute();
+
+        // Position in the route of the first location
+        int startPosition = route.getIndex(startLocation);
+
+        // the location is not in a route
+        if (startPosition == -1)
+        {
+            return;
+        }
+
+        int left = std::max(0, startPosition - ((int) stringLength / 2));
+        int right = left + (int) stringLength - 1;
+
+        // we don't want to go out of bound
+        if (right >= routeLocationIDs.size())
+        {
+            right = routeLocationIDs.size() - 1;
+            left = std::max(0, right - (int) stringLength + 1);// keep a number of stringLength elements
+        }
+
+        ////////////////////:
+        // try : get the left index and remove stringLength times on the left index
+
+        // collect each locationID and store the pairID in the toRemove vector
+        for (int i = left; i <= right; ++i)
+        {
+            // pickupID = pairID
+            // if pickup and not already in the list
+            if (data.getLocation(routeLocationIDs.at(i)).getLocType() == LocType::PICKUP &&
+                std::find(toRemove.begin(), toRemove.end(), routeLocationIDs.at(i)) == toRemove.end())
+            {
+                toRemove.emplace_back(routeLocationIDs.at(i));
+            }
+            // or if delivery and pairID not already in the list
+            else if (data.getLocation(routeLocationIDs.at(i)).getLocType() == LocType::DELIVERY &&
+                     std::find(toRemove.begin(), toRemove.end(), data.getLocation(routeLocationIDs.at(i)).getPair()) ==
+                             toRemove.end())
+            {
+                toRemove.emplace_back(data.getLocation(routeLocationIDs.at(i)).getPair());
+            }
+        }
+
+        std::cout << std::endl << "PairID (pickup):" << std::endl;
+        for (int i: toRemove)
+        {
+            std::cout << i << " ";
+        }
+        std::cout << std::endl;
+
+        //remove the collected pairID
+        for (int pairID: toRemove)
+        {
+            // get index and Pair
+            int position = solution.getRoute(routeIndex).getIndex(pairID);
+            Index index = std::make_tuple(routeIndex, position, route.getPairLocationPosition(position, data));
+            Pair const &pair = data.getPair(pairID);
+            
+            // apply remove
+            RemovePair removePair(index, pair);
+            solution.applyDestructSolution(removePair);
+        }
+    }
+}// namespace
+
+
+// Procedure RUIN(s, Lmax, c^bar)
+//   1. Compute lmax_s, kmax_s, k_s according to equations (5), (6), and (7)
+//   2. cseed_s ← RandomClient(s)
+//   3. R ← ∅  // Set of affected tours
+//   4. For each client c in Adjacent(cseed_s) Do
+//       5. If c ∉ A and |R| < k_s Then
+//           6. c*_t ← c
+//           7. Compute lmax_t, lt according to equations (8) and (9)
+//           8. A ← A ∪ RemoveClient(T, lt, c*_t)
+//           9. R ← R ∪ {t}
+//       10. End If
+//   11. End For
+// End Procedure
+
+
+/**
+ *  Ruin procedure from the SISR paper.
+ *  c^bar = averageNumberRemovedElement.
+ *  L^max = maxStringSize.
+ */
+void SISRsRuin(Solution &solution, unsigned int maxStringSize, unsigned int averageNumberRemovedElement)
+{
+    // |t∈T| average number of location by route
+    unsigned int averageRouteCardinality = computeAverageCardinality(solution.getRoutes());
+
+    // compute equation (5) (6) and (7) from the SISR paper.
+    // (5) lmax_s
+    unsigned int maxSizeOfString =
+            std::min(static_cast<std::size_t>(maxStringSize), static_cast<std::size_t>(averageRouteCardinality));
+    // (6) kmax_s
+    unsigned int maxNumberOfString = (4 * averageNumberRemovedElement) / (1 + maxSizeOfString) - 1;
+    // (7) k_s
+    unsigned int numberOfString = util::getRandomInt(1, maxNumberOfString + 1);
+
+    // get Location ID of the location seed
+    int locationSeed = util::getRandomInt(1, solution.getData().getLocationCount());
+
+    // store the index of routes where a string was removed
+    std::vector<int> routeIndexUsed;
+    routeIndexUsed.reserve(numberOfString);
+
+    std::cout << "locationSeed : " << locationSeed << std::endl;
+
+    // getClosestLocationsID returns the list of all location sorted from the closest to furthest
+    for (int neighbor: solution.getData().getClosestLocationsID(locationSeed))
+    {
+        // recover the routeIndex associated to the locationID, returns -1 if in the bank
+        int routeIndex = solution.getRouteIDOf(neighbor);
+
+        // verif de validité
+        // -> pas dans pairBank
+        // -> route pas déjà modifiée
+        if (routeIndex != -1 && std::ranges::find(routeIndexUsed, routeIndex) == routeIndexUsed.end())
+        {
+            std::cout << "in" << std::endl;
+
+            // (8) lmax_t
+            unsigned int maxSizeOfThisString =
+                    std::min(static_cast<int>(maxSizeOfString), solution.getRoute(routeIndex).getSize());
+            // (9) l_t
+            unsigned int actualSizeOfThisString = util::getRandomInt(1, maxSizeOfThisString);
+
+            std::cout << "actualSizeOfThisString " << actualSizeOfThisString << " neighbor " << neighbor << std::endl;
+
+            // string removal
+            removeString(solution, routeIndex, actualSizeOfThisString, neighbor);
+
+            // update routeIndexUsed
+            routeIndexUsed.emplace_back(routeIndex);
+
+            if (routeIndexUsed.size() >= numberOfString)
+            {
+                break;
+            }
+        }
+    }
+}
+
+// namespace
+
+void StringRemoval::destroySolution(Solution &solution) const
+{
+    SISRsRuin(solution, maxCardinalityOfString, averageNumberRemovedElement);
+}
diff --git a/src/lns/operators/destruction/string_removal.h b/src/lns/operators/destruction/string_removal.h
new file mode 100644
index 0000000000000000000000000000000000000000..163166badeab2c72f2edd0b49a112faf9e45bc8e
--- /dev/null
+++ b/src/lns/operators/destruction/string_removal.h
@@ -0,0 +1,26 @@
+#pragma once
+
+#include "lns/operators/abstract_operator.h"
+
+class StringRemoval : public DestructionOperator
+{
+public:
+    explicit StringRemoval(unsigned int maxCardinalityOfString, unsigned int averageNumberRemovedElement)
+        : maxCardinalityOfString(maxCardinalityOfString), averageNumberRemovedElement(averageNumberRemovedElement)
+    {}
+
+    // Each string has a max number of requests: MAX_CARDINALITY_OF_STRING
+    // L_max in the paper.
+    unsigned int maxCardinalityOfString = 10;
+    // This operator will remove in average AVERAGE_CUSTOMER_REMOVAL of requests
+    // c with a bar on top in the paper
+    unsigned int averageNumberRemovedElement = 10;
+
+    /**
+     * This operator removes numberOfPairsToDestroy pairs randomly in the solution.
+     */
+    void destroySolution(Solution &solution) const override;
+
+private:
+    int numberOfPairsToDestroy;
+};
diff --git a/src/lns/operators/reconstruction/list_heuristic_cost_oriented.cpp b/src/lns/operators/reconstruction/list_heuristic_cost_oriented.cpp
index 7a5b95def9a0d326afbd401653e70abe9ff04c3a..e58ad0562633e3e7097e47d28743e0f73d0d2ec2 100644
--- a/src/lns/operators/reconstruction/list_heuristic_cost_oriented.cpp
+++ b/src/lns/operators/reconstruction/list_heuristic_cost_oriented.cpp
@@ -16,6 +16,36 @@ void ListHeuristicCostOriented::reconstructSolution(Solution &solution, double b
             sortedPairs = sorting_strategy::Shuffle(solution).sortPairs();
             break;
         }
+        case SortingStrategyType::DEMAND: {
+            std::cout << "D";
+            sortedPairs = sorting_strategy::Demand(solution).sortPairs();
+            break;
+        }
+        case SortingStrategyType::CLOSE: {
+            std::cout << "C";
+            sortedPairs = sorting_strategy::Close(solution).sortPairs();
+            break;
+        }
+        case SortingStrategyType::FAR: {
+            std::cout << "F";
+            sortedPairs = sorting_strategy::Far(solution).sortPairs();
+            break;
+        }
+        case SortingStrategyType::TWWIDTH: {
+            std::cout << "TWW";
+            sortedPairs = sorting_strategy::TimeWindowWidth(solution).sortPairs();
+            break;
+        }
+        case SortingStrategyType::TWSTART: {
+            std::cout << "TWS";
+            sortedPairs = sorting_strategy::TimeWindowStart(solution).sortPairs();
+            break;
+        }
+        case SortingStrategyType::TWEND: {
+            std::cout << "TWE";
+            sortedPairs = sorting_strategy::TimeWindowEnd(solution).sortPairs();
+            break;
+        }
         default:
             spdlog::error("Error, invalid strategy selected.");
             throw std::invalid_argument("Invalid sorting strategy selected.");
diff --git a/src/lns/solution/route.cpp b/src/lns/solution/route.cpp
index 9ac3c6651fce5a19b52b4b6b2f75f75135437440..01ba660c361064421b29a6c4497d4a70552791a3 100644
--- a/src/lns/solution/route.cpp
+++ b/src/lns/solution/route.cpp
@@ -61,6 +61,14 @@ int Route::getSize() const
     return route.size();
 }
 
+int Route::getIndex(int locationID) const 
+{
+    auto it = std::find(route.begin(), route.end(), locationID);
+    if (it != route.end()) {
+        return std::distance(route.begin(), it);
+    }
+    return -1;
+}
 
 int Route::getPairLocationPosition(int position, const PDPTWData &data) const
 {
diff --git a/src/lns/solution/route.h b/src/lns/solution/route.h
index 32010af46aefd7c2cab0c8737aeb19fb33c392a2..c4c30e3bafd920c48bb11ce9522d5baad3edd9c4 100644
--- a/src/lns/solution/route.h
+++ b/src/lns/solution/route.h
@@ -27,6 +27,11 @@ public:
     // get Location
     int getLocation(int index) const;    
 
+    /**
+     *  Given a locationID, return the Index in the route.
+     *  return -1 if no such location.
+     */
+    int getIndex(int locationID) const;
     
     /**
      *  Given the position of a location in a route, return the paired location position.
diff --git a/src/lns/solution/solution.cpp b/src/lns/solution/solution.cpp
index fae1ffe5f400336f0ed02e8ea8987d774dd21e4c..fcb7ec173b2c083c65c0d3816799427920a62537 100644
--- a/src/lns/solution/solution.cpp
+++ b/src/lns/solution/solution.cpp
@@ -8,9 +8,12 @@
 #include "lns/solution/route.h"
 #include "output/solution_checker.h"
 
+#include <algorithm>
 #include <bits/ranges_algo.h>
 #include <bits/ranges_util.h>
+#include <ranges>
 #include <utility>
+#include <vector>
 
 void Solution::initPairBank()
 {
@@ -209,6 +212,22 @@ int Solution::requestsFulFilledCount() const
     return count;
 }
 
+int Solution::getRouteIDOf(int locationID) const
+{
+    int routeIndex = 0;
+    for (Route const &route: getRoutes())
+    {
+        std::vector<int> const &routeLocationIDs = route.getRoute();
+        if (std::ranges::find(routeLocationIDs, locationID) != routeLocationIDs.end())
+        {
+            return routeIndex;
+        }
+        ++routeIndex;
+    }
+    // no routes contain the location
+    return -1;
+}
+
 bool Solution::checkModification(AtomicRecreation const &modification) const
 {
     //std::cout << "--- Check Modification Validity : ";
diff --git a/src/lns/solution/solution.h b/src/lns/solution/solution.h
index 776a0ad2e6105348c9174b264db7e5e7a66787a4..7c06e5b1cac7a0547fe775b34a17b548c9826fb1 100644
--- a/src/lns/solution/solution.h
+++ b/src/lns/solution/solution.h
@@ -76,6 +76,12 @@ public:
     PDPTWData const &getData() const;
     double getRawCost() const;
     double getCost() const;
+    
+    /**
+     *  Return the route index associated to the given location ID.
+     *  -1 if the location is not in a route.
+     */
+    int getRouteIDOf(int locationID) const;
 
     /**
      *  Return the number of fullfilled requests.
diff --git a/src/mains/main.cpp b/src/mains/main.cpp
index 948b5cf79e357a942c4b50b56cbba765a2853334..83071eb6282e18064adc6173cb0bce97a9e7e8ec 100644
--- a/src/mains/main.cpp
+++ b/src/mains/main.cpp
@@ -14,6 +14,7 @@
 #include "lns/modification/route/remove_route.h"
 #include "lns/operators/abstract_operator.h"
 #include "lns/operators/destruction/random_destroy.h"
+#include "lns/operators/destruction/string_removal.h"
 #include "lns/operators/reconstruction/enumerate.h"
 #include "lns/operators/reconstruction/list_heuristic_cost_oriented.h"
 #include "lns/operators/reconstruction/list_heuristic_insertion.h"
@@ -83,30 +84,31 @@ int main(int argc, char **argv)
 {
     //return mainInterface(argc, argv, &simpleLNS);
 
+    ///////////////////////////////////////////////////////////////////////
 
-    ///////////////////////////////////////////////////////////////////////::
-
-    //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/Nantes_1.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/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);
+    //Solution startingSolution = Solution::emptySolution(data);
+
+    //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);
+    ListHeuristicCostOriented reconstruction = ListHeuristicCostOriented(SortingStrategyType::SHUFFLE, EnumerationType::ALL_INSERT_PAIR);
+    reconstruction.reconstructSolution(testSolution, 0.01);
 
     testSolution.print();
-    sorting_strategy::Shuffle(testSolution).sortPairs();
 
-    testSolution.print();
-    
-    sorting_strategy::TimeWindowStart(testSolution).sortPairs();
+    std::cout << "============ \n";
+
+    StringRemoval StringRemoval(10,10);
+    StringRemoval.destroySolution(testSolution);
 
     testSolution.print();