From 2fc0df0b66309314534d1f92e2146ea34b59f8e2 Mon Sep 17 00:00:00 2001
From: awenjb <126257927+awenjb@users.noreply.github.com>
Date: Fri, 28 Feb 2025 15:57:32 +0100
Subject: [PATCH] Update Code

- revised some parts of the code
- add some comments
- add config.h and types.h
- data init with the list of Pair
- Solution init and link with constraints
---
 CMakeLists.txt                                |   3 +-
 src/config.h                                  |   3 +
 src/input/data.cpp                            |   4 +-
 src/input/data.h                              |   5 +-
 src/input/json_parser.cpp                     |   5 +-
 src/input/location.cpp                        |  17 ++-
 src/input/location.h                          |  27 +++-
 src/input/pair.cpp                            |  26 +++-
 src/input/pair.h                              |  19 ++-
 src/input/pdptw_data.cpp                      |  39 +++++-
 src/input/pdptw_data.h                        |  27 ++--
 src/input/time_window.cpp                     |   7 -
 src/input/time_window.h                       |  15 +--
 .../capacity/capacity_constraint.h            |  10 +-
 src/lns/constraints/constraint.cpp            |   2 +-
 src/lns/constraints/constraint.h              |  16 ++-
 .../time_window/time_window_constraint.cpp    | 119 +++++++++++++----
 .../time_window/time_window_constraint.h      |  14 +-
 src/lns/modification/atomic_destruction.h     |   3 +-
 src/lns/modification/atomic_modification.h    |   5 +
 src/lns/modification/atomic_recreation.h      |   1 +
 src/lns/modification/pair/insert_pair.cpp     |  37 +++---
 src/lns/modification/pair/insert_pair.h       |  23 ++--
 src/lns/modification/pair/remove_pair.cpp     |  27 ++--
 src/lns/modification/pair/remove_pair.h       |  25 ++--
 src/lns/modification/route/insert_route.cpp   |   4 +-
 src/lns/modification/route/insert_route.h     |  10 +-
 src/lns/modification/route/remove_route.cpp   |   9 +-
 src/lns/modification/route/remove_route.h     |  18 +--
 src/lns/solution/route.h                      |   3 +-
 src/lns/solution/solution.cpp                 |  91 +++++++++++--
 src/lns/solution/solution.h                   |  73 +++++++++--
 src/main.cpp                                  |  96 --------------
 src/mains/main.cpp                            | 123 ++++++++++++++++++
 src/mains/main_interface.cpp                  |  41 ++++++
 src/mains/main_interface.h                    |   8 ++
 src/types.h                                   |  23 ++++
 37 files changed, 691 insertions(+), 287 deletions(-)
 create mode 100644 src/config.h
 delete mode 100644 src/main.cpp
 create mode 100644 src/mains/main.cpp
 create mode 100644 src/mains/main_interface.cpp
 create mode 100644 src/mains/main_interface.h
 create mode 100644 src/types.h

diff --git a/CMakeLists.txt b/CMakeLists.txt
index b53e89f..9f66893 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -19,7 +19,8 @@ find_package(spdlog REQUIRED)
 
 
 
-add_executable(pdptw src/main.cpp 
+add_executable(pdptw src/mains/main.cpp
+                src/mains/main_interface.cpp
                 src/input/data.cpp
                 src/input/location.cpp
                 src/input/pair.cpp
diff --git a/src/config.h b/src/config.h
new file mode 100644
index 0000000..bf368d8
--- /dev/null
+++ b/src/config.h
@@ -0,0 +1,3 @@
+
+
+const int EXCLUSION_PENALTY = 100;
\ No newline at end of file
diff --git a/src/input/data.cpp b/src/input/data.cpp
index ded7518..59448dc 100644
--- a/src/input/data.cpp
+++ b/src/input/data.cpp
@@ -41,9 +41,9 @@ double data::routeCost(PDPTWData const & data, Route const & route)
     return cost;
 }
 
-double data::TravelCost(PDPTWData const &data, int index1, int index2)
+double data::TravelCost(PDPTWData const &data, int from, int to)
 {
-    return data.getMatrix()[index1][index2];
+    return data.getMatrix()[from][to];
 }
 
 double data::TravelTime(PDPTWData const &data, int from, int to)
diff --git a/src/input/data.h b/src/input/data.h
index 7277150..a0b2e2e 100644
--- a/src/input/data.h
+++ b/src/input/data.h
@@ -3,7 +3,8 @@
 #include "time_window.h"
 #include "pdptw_data.h"
 #include "location.h"
-#include "../lns/solution/route.h"
+#include "lns/solution/solution.h"
+
 
 /**
  * Functions for PDPTWData
@@ -38,7 +39,7 @@ namespace data
      * Return the travel cost between two location
      * (take location id in parameters)
      */
-    double TravelCost(PDPTWData const &data, int index1, int index2);
+    double TravelCost(PDPTWData const &data, int from, int to);
 
     /**
      * Return the travel time between two location
diff --git a/src/input/json_parser.cpp b/src/input/json_parser.cpp
index 52c7ecf..31d221c 100644
--- a/src/input/json_parser.cpp
+++ b/src/input/json_parser.cpp
@@ -51,7 +51,7 @@ PDPTWData parsing::parseJson(std::string filepath)
 PDPTWData json_to_data(const json& j)
 {
    
-    unsigned int size = j.at("size").get<unsigned int>();
+    int size = j.at("size").get<int>();
     int capacity = j.at("capacity").get<int>();
     
     auto depot_json = j.at("depot");
@@ -68,7 +68,6 @@ PDPTWData json_to_data(const json& j)
         LocType::DEPOT
     );
     
-
     std::vector<Location> locations;
 
     for (const auto& loc : j.at("locations")) 
@@ -90,5 +89,5 @@ PDPTWData json_to_data(const json& j)
 
     Matrix distance_matrix = j.at("distance_matrix").get<Matrix>();
 
-    return PDPTWData(size, capacity, depot, locations, distance_matrix);
+    return {size, capacity, depot, locations, distance_matrix};
 }
diff --git a/src/input/location.cpp b/src/input/location.cpp
index 8ccec5f..c012701 100644
--- a/src/input/location.cpp
+++ b/src/input/location.cpp
@@ -1,9 +1,9 @@
 #include "location.h"
 
 
-Location::Location(unsigned int id, double lon, double lat, int dem, TimeWindow tw, double service, unsigned int pairId, LocType type)
-    : id(id), longitude(lon), latitude(lat), demand(dem), timeWindow(tw), serviceDuration(service), pairedLocation(pairId), locType(type) {}
-
+Location::Location(int id, double lon, double lat, int dem, TimeWindow tw, double service, int pairId, LocType type)
+    : id(id), longitude(lon), latitude(lat), demand(dem), timeWindow(tw), serviceDuration(service), pairedLocationID(pairId), locType(type) 
+{}
 
 double Location::getLongitude() const {
     return longitude;
@@ -17,12 +17,12 @@ double Location::getServiceDuration() const {
     return serviceDuration;
 }
 
-unsigned int Location::getId() const {
+int Location::getId() const {
     return id;
 }
 
-unsigned int Location::getPair() const {
-    return pairedLocation;
+int Location::getPair() const {
+    return pairedLocationID;
 }
 
 int Location::getDemand() const {
@@ -37,7 +37,7 @@ TimeWindow Location::getTimeWindow() const {
     return timeWindow;
 }
 
-std::string Location::LocTypeToString(LocType type) const
+std::string Location::LocTypeToString(LocType type)
 {
     switch (type) {
         case LocType::DEPOT: return "Depot";
@@ -47,11 +47,10 @@ std::string Location::LocTypeToString(LocType type) const
     }
 }
 
-
 void Location::print() const
 {
     std::cout << "Location ID: " << id << ", Coordinates: (" << longitude << ", " << latitude << ")\n";
-    std::cout << "Location Type : " <<  Location::LocTypeToString(locType) << ", Associated location : " << pairedLocation << "\n";
+    std::cout << "Location Type : " <<  Location::LocTypeToString(locType) << ", Associated location : " << pairedLocationID << "\n";
     std::cout << "Demand : " <<  demand << "\n";
     timeWindow.print();
 }
\ No newline at end of file
diff --git a/src/input/location.h b/src/input/location.h
index 8aac218..e7a1646 100644
--- a/src/input/location.h
+++ b/src/input/location.h
@@ -23,31 +23,46 @@ enum class LocType
  */
 class Location
 {
-    unsigned int id;
+    /*
+    *   The location ID 
+    */
+    int id;
     double longitude;
     double latitude;
+    /*
+    *   Represent the capacity used by that location.
+    *   The location demand must be positive if it is a PICKUP, negative if it is a DELIVERY and 0 for a DEPOT.
+    */
     int demand;
     double serviceDuration;
-    unsigned int pairedLocation;
+    /*
+    *   The location ID associated to form a pickup and delivery pair.
+    *   (the same ID if the location is a depot)
+    */
+    int pairedLocationID;
+    /*
+    *   The type of the location (PICKUP, DELIVERY, DEPOT).
+    */
     LocType locType;
     TimeWindow timeWindow;
 
 public:
 
-    Location(unsigned int id, double lon, double lat, int dem, TimeWindow tw, double service, unsigned int pairId,  LocType type);
+    Location(int id, double lon, double lat, int dem, TimeWindow tw, double service, int pairId,  LocType type);
 
     double getLongitude() const;
     double getLatitude() const;
     double getServiceDuration() const;
-    unsigned getId() const;
-    unsigned int getPair() const;
+    int getId() const;
+    int getPair() const;
     int getDemand() const;
     LocType getLocType() const;
     TimeWindow getTimeWindow() const;
 
     void print() const;
-    std::string LocTypeToString(LocType type) const;
 
+    static std::string LocTypeToString(LocType type);
+    
     // Json parsing
     friend void from_json(nlohmann::json const &json, Location &location);
 };
\ No newline at end of file
diff --git a/src/input/pair.cpp b/src/input/pair.cpp
index ccdccb0..fa7223d 100644
--- a/src/input/pair.cpp
+++ b/src/input/pair.cpp
@@ -1,7 +1,7 @@
 #include "pair.h"
 
-Pair::Pair(const Location& pickupLoc, const Location& deliveryLoc)
-: pickup(pickupLoc), delivery(deliveryLoc) {}
+Pair::Pair(const Location& pickup, const Location& delivery, int pairID)
+: pickup(pickup), delivery(delivery), pairID(pairID) {}
 
 const Location& Pair::getPickup() const 
 {
@@ -11,4 +11,26 @@ const Location& Pair::getPickup() const
 const Location& Pair::getDelivery() const 
 {
     return delivery.get();
+}
+
+const Location& Pair::getP() const 
+{
+    return pickup.get();
+}
+
+const Location& Pair::getD() const 
+{
+    return delivery.get();
+}
+
+int Pair::getID() const 
+{
+    return pairID;
+}
+
+void Pair::print() const
+{
+    pickup.get().print();
+    std::cout << "\n";
+    delivery.get().print();
 }
\ No newline at end of file
diff --git a/src/input/pair.h b/src/input/pair.h
index 4183a20..b7dfc6b 100644
--- a/src/input/pair.h
+++ b/src/input/pair.h
@@ -2,16 +2,31 @@
 
 #include "location.h"
 
-// Represent a pair pickup/delivery of location
+/**
+ *  Represent a pair pickup/delivery of location
+ *  The pair ID is the pickup ID
+ */ 
 class Pair
 {
 private:
     std::reference_wrapper<Location const> pickup;
     std::reference_wrapper<Location const> delivery;
+    int pairID;
 
 public:
-    Pair(const Location& pickupLoc, const Location& deliveryLoc);
+    Pair(const Location& pickup, const Location& delivery, int pairID);
 
     const Location& getPickup() const;
     const Location& getDelivery() const;
+    /**
+    *   getPickup() but shorter
+    */
+    const Location& getP() const;
+    /**
+    *   getDelivery() but shorter
+    */
+    const Location& getD() const;
+    int getID() const;
+
+    void print() const;
 };
\ No newline at end of file
diff --git a/src/input/pdptw_data.cpp b/src/input/pdptw_data.cpp
index 6b819c6..142fbde 100644
--- a/src/input/pdptw_data.cpp
+++ b/src/input/pdptw_data.cpp
@@ -2,12 +2,10 @@
 
 #include <iostream>
 #include <fstream>
-#include <vector>
-#include <nlohmann/json.hpp>
 #include <spdlog/spdlog.h>
 
 
-unsigned int PDPTWData::getSize()
+int PDPTWData::getSize() const
 {
     return size;
 }
@@ -22,6 +20,11 @@ std::vector<Location> const &PDPTWData::getLocations() const
     return locations;
 }
 
+std::vector<Pair> const &PDPTWData::getPairs() const 
+{
+    return pairs;
+}
+
 Location const &PDPTWData::getDepot() const
 {
     return depot;
@@ -29,7 +32,12 @@ Location const &PDPTWData::getDepot() const
 
 Location const &PDPTWData::getLocation(int id) const
 {
-    return locations[id];
+    if (id==0)
+    {
+        return getDepot();
+    }
+    // location index from 0 to n-1
+    return locations.at(id -1);
 }
 
 Matrix const &PDPTWData::getMatrix() const
@@ -37,8 +45,20 @@ Matrix const &PDPTWData::getMatrix() const
     return distanceMatrix;
 }
 
-PDPTWData::PDPTWData(unsigned int size, int capacity, Location depot, std::vector<Location> location, Matrix distanceMatrix)
-    : size(size), capacity(capacity), depot(depot), locations(std::move(location)), distanceMatrix(std::move(distanceMatrix)) {}
+PDPTWData::PDPTWData(int size, int capacity, Location depot, std::vector<Location> locations, Matrix distanceMatrix)
+    : 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)
+    {
+        if( loc.getLocType() == LocType::PICKUP )
+        {
+            // vector indexed from 0 / Location indexed from 1
+            pairs.emplace_back(loc, locations[loc.getPair()-1], loc.getId());
+        }
+    }
+}
 
 
 void PDPTWData::print() const 
@@ -60,6 +80,13 @@ void PDPTWData::print() const
         }
         std::cout << "\n";
     }
+
+    std::cout << "Pair IDs:\n";
+    for (const auto& pair : pairs)
+    {;
+        std::cout << pair.getID() << " "; 
+    }
+    std::cout << " \n";
 }
 
 void PDPTWData::checkData() const
diff --git a/src/input/pdptw_data.h b/src/input/pdptw_data.h
index b7a504e..ac0ea57 100644
--- a/src/input/pdptw_data.h
+++ b/src/input/pdptw_data.h
@@ -1,12 +1,13 @@
 #pragma once
 
-#include "location.h"
-#include <functional>
 #include <nlohmann/json_fwd.hpp>
 #include <vector>
 
+#include "pair.h"
+#include "location.h"
+#include "types.h"
+
 using json = nlohmann::json;
-using Matrix = std::vector<std::vector<double>>; 
 
 /**
  * Throw this exception after errors in the input has been found.
@@ -20,29 +21,28 @@ public:
     char const *what() const noexcept override;
 };
 
-
-
 class PDPTWData
 {
-    unsigned int size;
+    int size;
     int capacity;
     Location depot;
     std::vector<Location> locations;
+    std::vector<Pair> pairs; // std::unordered_map<int, Pair> pair; if getPair(index) is needed ?
     Matrix distanceMatrix;
 
-
 public:
     PDPTWData();
     PDPTWData(PDPTWData const &rhs) = delete;
     PDPTWData(PDPTWData &&rhs) noexcept;
     PDPTWData &operator=(PDPTWData &&rhs) noexcept;
     PDPTWData &operator=(PDPTWData const &rhs) = delete;
+    ~PDPTWData() = default;
 
     /**
      * Constructs an empty PDPTWData.
      * @see parsing::parseJson
      */
-    PDPTWData(unsigned int size, int capacity, Location depot, std::vector<Location> requests, Matrix distanceMatrix);
+    PDPTWData(int size, int capacity, Location depot, std::vector<Location> locations, Matrix distanceMatrix);
     /**
      * Checks some data coherence
      */
@@ -50,13 +50,20 @@ public:
     bool checkMatrix() const;
     bool checkLocation() const;
 
-    
+
     std::vector<Location> const &getLocations() const;
+    std::vector<Pair> const &getPairs() const;
+
+    /** 
+    *   0 return the depot.
+    *   Other numbers return the associated location.
+    */
     Location const &getLocation(int id) const;
     Location const &getDepot() const;
+
     Matrix const &getMatrix() const;
 
-    unsigned int getSize();
+    int getSize() const;
     int getCapacity() const;
 
     void print() const;
diff --git a/src/input/time_window.cpp b/src/input/time_window.cpp
index 086268c..7f6eb3a 100644
--- a/src/input/time_window.cpp
+++ b/src/input/time_window.cpp
@@ -31,10 +31,3 @@ void TimeWindow::print() const
 {
     std::cout << "Time Window : [" << start << ", " << end << "] \n";
 }
-/*
-TimeInteger TimeWindow::waitingTimeBefore(TimeInteger t) const
-{
-    return std::max<TimeInteger>(0, t - start);
-}
-*/
-
diff --git a/src/input/time_window.h b/src/input/time_window.h
index 594bc1f..ce9d56c 100644
--- a/src/input/time_window.h
+++ b/src/input/time_window.h
@@ -1,14 +1,8 @@
 #pragma once
 
-#include <iostream>
-#include <limits>
 #include <nlohmann/json_fwd.hpp>
 
-/**
- * A point in time or a duration.
- */
-using TimeInteger = double;
-TimeInteger constexpr UNDEF_TIMESTAMP = std::numeric_limits<TimeInteger>::max();
+#include "types.h"
 
 /**
  * Represents a time window [start, end] with some basic utilities.
@@ -29,12 +23,7 @@ public:
     //Checks whether the time t is inside the time window OR before
     bool isValid(TimeInteger t) const;
 
-    /**
-     * return the time to wait from t to the start of this time window.
-     * @return 0 if t is after start, or start - t
-     */
-    //TimeInteger waitingTimeBefore(TimeInteger t) const;
-
     void print() const;
+
     friend void from_json(nlohmann::json const &json, TimeWindow &tw);
 };
\ No newline at end of file
diff --git a/src/lns/constraints/capacity/capacity_constraint.h b/src/lns/constraints/capacity/capacity_constraint.h
index 3114953..c1a668c 100644
--- a/src/lns/constraints/capacity/capacity_constraint.h
+++ b/src/lns/constraints/capacity/capacity_constraint.h
@@ -1,7 +1,13 @@
 #pragma once
+#include <vector>
 
-#include "./../constraint.h"
-#include "./../../../input/pair.h"
+#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"
 
 /**
  * Capacity constraint.
diff --git a/src/lns/constraints/constraint.cpp b/src/lns/constraints/constraint.cpp
index 51f375e..23d9315 100644
--- a/src/lns/constraints/constraint.cpp
+++ b/src/lns/constraints/constraint.cpp
@@ -1,5 +1,5 @@
 #include "constraint.h"
-
+#include "lns/solution/solution.h"
 
 Constraint::Constraint(Solution const &solution) : solution(solution) {}
 
diff --git a/src/lns/constraints/constraint.h b/src/lns/constraints/constraint.h
index f41e778..6e27f9f 100644
--- a/src/lns/constraints/constraint.h
+++ b/src/lns/constraints/constraint.h
@@ -1,12 +1,16 @@
 #pragma once
+
+#include <memory>
+#include <stdexcept>
 #include <variant>
-#include "./../solution/solution.h"
 
-// all modifications
-#include "./../modification/pair/insert_pair.h"
-#include "./../modification/pair/remove_pair.h"
-#include "./../modification/route/insert_route.h"
-#include "./../modification/route/remove_route.h"
+// forward declaration of all modifications
+class InsertPair;
+class RemovePair;
+class InsertRoute;
+class RemoveRoute;
+class Solution;
+class PDPTWData;
 
 
 using ModificationApplyVariant =
diff --git a/src/lns/constraints/time_window/time_window_constraint.cpp b/src/lns/constraints/time_window/time_window_constraint.cpp
index fe4134e..b350692 100644
--- a/src/lns/constraints/time_window/time_window_constraint.cpp
+++ b/src/lns/constraints/time_window/time_window_constraint.cpp
@@ -1,13 +1,23 @@
 #include "time_window_constraint.h"
+
 #include "input/data.h"
 #include "input/pdptw_data.h"
 #include "input/time_window.h"
+#include "lns/modification/pair/insert_pair.h"
+#include "lns/modification/pair/remove_pair.h"
+#include "lns/modification/route/remove_route.h"
 #include "lns/solution/solution.h"
 
 
-TimeWindowConstraint::TimeWindowConstraint(Solution const &solution) : Constraint(solution)
+TimeWindowConstraint::TimeWindowConstraint(const Solution& solution) : Constraint(solution)
+{
+    allRouteReachTimes.resize(getSolution().getRoutes().size());
+}
+
+
+TimeWindowConstraint::~TimeWindowConstraint() 
 {
-    // Empty
+    allRouteReachTimes.clear();
 }
 
 std::unique_ptr<Constraint> TimeWindowConstraint::clone(Solution const &newOwningSolution) const {
@@ -16,6 +26,37 @@ std::unique_ptr<Constraint> TimeWindowConstraint::clone(Solution const &newOwnin
     return clonePtr;
 }
 
+void TimeWindowConstraint::computeReachTimes(const PDPTWData& data, const std::vector<int> & routeIDs, ReachTimeVector & reachTimes) const
+{
+    // Adjust the size of reachTimes vector
+    reachTimes.resize(routeIDs.size(), 0);
+    // Time to the first location
+    reachTimes[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[i - 1], routeIDs[i]);
+        // locations are indexed from 0 to n-1,
+        TimeInteger serviceTime = data.getLocation(routeIDs[i - 1]).getServiceDuration();
+        TimeInteger startTW = data.getLocation(routeIDs[i - 1]).getTimeWindow().getStart();
+
+        reachTimes[i] = std::max(reachTimes[i - 1], startTW) + serviceTime + travelTime;
+    }
+}
+
+void TimeWindowConstraint::initReachTimes()
+{
+    allRouteReachTimes = std::vector<ReachTimeVector>();
+    int i = 0;
+    for (const Route& route : getSolution().getRoutes()) 
+    {
+        // init and calculate reach time value
+        allRouteReachTimes.emplace_back();
+        computeReachTimes(getSolution().getData(), route.getRoute(), allRouteReachTimes.at(i));
+        ++i;
+    }
+}
+
+
 
 // Copie le vecteur de reach time de la route concernée
 // Insère les positions pickup/delivery
@@ -30,14 +71,29 @@ bool TimeWindowConstraint::checkInsertion(const PDPTWData& data, const Pair & pa
     ReachTimeVector newReachTimes(reachTimes.begin(), reachTimes.end());
 
     // Insert pickup and delivery
-    route.insert(route.begin() + pickupPos, pair.getPickup().getId());
     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 < reachTimes.size(); ++i) 
+    for (int i = 0; i < newReachTimes.size(); ++i) 
     {
         if (! data.getLocation(route[i]).getTimeWindow().isValid(newReachTimes.at(i)) )
         {
@@ -47,20 +103,6 @@ bool TimeWindowConstraint::checkInsertion(const PDPTWData& data, const Pair & pa
     return true;    
 }
 
-void TimeWindowConstraint::computeReachTimes(const PDPTWData& data, const std::vector<int> & routeIDs, ReachTimeVector & reachTimes) const
-{
-    // Adjust the size of reachTimes vector
-    reachTimes.resize(routeIDs.size(), 0);
-    // Time to the first location
-    reachTimes[0] = data.getDepot().getTimeWindow().getStart() + data::TravelTime(data, 0, routeIDs.at(0));
-    // Compute other reachTimes (max between arrival and start of the time window)
-    for (int i = 1; i < routeIDs.size(); ++i) {
-        TimeInteger travelTime = data::TravelTime(data, routeIDs[i - 1], routeIDs[i]);
-        TimeInteger serviceTime = data.getLocation(routeIDs[i - 1]).getServiceDuration();
-        TimeInteger startTW = data.getLocation(routeIDs[i]).getTimeWindow().getStart();
-        reachTimes[i] = std::max(reachTimes[i - 1] + serviceTime + travelTime, startTW);
-    }
-}
 
 
 void TimeWindowConstraint::ApplyModif(const PDPTWData& data, const Pair & pair, int routeIndex, int pickupPos, int deliveryPos, bool addPair)
@@ -71,8 +113,8 @@ void TimeWindowConstraint::ApplyModif(const PDPTWData& data, const Pair & pair,
     // Adjust pickup and delivery
     if (addPair)
     {
-        routeIDs.insert(routeIDs.begin() + pickupPos, pair.getPickup().getId());
         routeIDs.insert(routeIDs.begin() + deliveryPos, pair.getDelivery().getId());
+        routeIDs.insert(routeIDs.begin() + pickupPos, pair.getPickup().getId());
     }
     else
     {
@@ -88,11 +130,25 @@ void TimeWindowConstraint::ApplyModif(const PDPTWData& data, const Pair & pair,
     for (int i = 1; i < routeIDs.size(); ++i) {
         TimeInteger travelTime = data::TravelTime(data, routeIDs[i - 1], routeIDs[i]);
         TimeInteger serviceTime = data.getLocation(routeIDs[i - 1]).getServiceDuration();
-        TimeInteger startTW = data.getLocation(routeIDs[i]).getTimeWindow().getStart();
-        allRouteReachTimes[routeIndex][i] = std::max(allRouteReachTimes[routeIndex][i - 1] + serviceTime + travelTime, startTW);
+        TimeInteger startTW = data.getLocation(routeIDs[i - 1]).getTimeWindow().getStart();
+        allRouteReachTimes[routeIndex][i] = std::max(allRouteReachTimes[routeIndex][i - 1], startTW) + serviceTime + travelTime;
     }
 }
+/*
+    // Adjust the size of reachTimes vector
+    reachTimes.resize(routeIDs.size(), 0);
+    // Time to the first location
+    reachTimes[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[i - 1], routeIDs[i]);
+        // locations are indexed from 0 to n-1,
+        TimeInteger serviceTime = data.getLocation(routeIDs[i - 1]).getServiceDuration();
+        TimeInteger startTW = data.getLocation(routeIDs[i - 1]).getTimeWindow().getStart();
 
+        reachTimes[i] = std::max(reachTimes[i - 1], startTW) + serviceTime + travelTime;
+    }
+*/
 
 bool TimeWindowConstraint::check(InsertPair const &op) const
 {
@@ -132,6 +188,25 @@ void TimeWindowConstraint::apply(RemoveRoute const &op)
     allRouteReachTimes.erase(allRouteReachTimes.begin() + op.getRouteIndex());
 }
 
+const std::vector<TimeWindowConstraint::ReachTimeVector>& TimeWindowConstraint::getallRouteReachTimes() const {
+    return allRouteReachTimes;
+}
 
-
+void TimeWindowConstraint::print() const
+{
+    std::cout << "Reach Times : \n";
+    int i = 0;
+    for (const auto& reachTimes : getallRouteReachTimes())
+    {
+        //std::cout << reachTimes.size() << ", ";
+        std::cout << "#" << i << " : ";
+        for (const TimeInteger reachTime : reachTimes)
+        {
+            std::cout << reachTime << ", ";
+        }
+        std::cout << "\n ";
+        i++;
+    }
+    std::cout << "\n";
+}
 
diff --git a/src/lns/constraints/time_window/time_window_constraint.h b/src/lns/constraints/time_window/time_window_constraint.h
index 89bc055..6b0582b 100644
--- a/src/lns/constraints/time_window/time_window_constraint.h
+++ b/src/lns/constraints/time_window/time_window_constraint.h
@@ -3,6 +3,7 @@
 #include "lns/constraints/constraint.h"
 #include "input/pair.h"
 #include "input/time_window.h"
+#include "lns/solution/route.h"
 #include <vector>
 
 /**
@@ -14,15 +15,22 @@
 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();
 
     std::unique_ptr<Constraint> clone(Solution const &newOwningSolution) const override;
     
-private:
-    using ReachTimeVector = std::vector<TimeInteger>;
-    
+    const std::vector<ReachTimeVector> & getallRouteReachTimes() const;
 
+    void print() const;
+private:
 
     /**
     *   For each route, store the reach time of each location
diff --git a/src/lns/modification/atomic_destruction.h b/src/lns/modification/atomic_destruction.h
index c396ca6..f2ad02f 100644
--- a/src/lns/modification/atomic_destruction.h
+++ b/src/lns/modification/atomic_destruction.h
@@ -1,7 +1,7 @@
 #pragma once
 
 #include "atomic_modification.h"
-#include <vector>
+
 
 class Location;
 
@@ -11,6 +11,7 @@ class Location;
 class AtomicDestruction : public AtomicModification
 {
 public:
+    ~AtomicDestruction() override = default;
     /**
      * @return the location ID removed from the solution.
      */
diff --git a/src/lns/modification/atomic_modification.h b/src/lns/modification/atomic_modification.h
index 835ef39..c189594 100644
--- a/src/lns/modification/atomic_modification.h
+++ b/src/lns/modification/atomic_modification.h
@@ -1,5 +1,8 @@
 #pragma once
 
+#include <vector>
+
+#include "lns/constraints/constraint.h"
 class Solution;
 
 /**
@@ -10,6 +13,8 @@ class Solution;
 class AtomicModification
 {
 public:
+    virtual ~AtomicModification() = default;
+
     /**
      * Return the cost of the operation.
      * @return a positive number if the solution cost is bigger after the modification.
diff --git a/src/lns/modification/atomic_recreation.h b/src/lns/modification/atomic_recreation.h
index f554a25..1d726a4 100644
--- a/src/lns/modification/atomic_recreation.h
+++ b/src/lns/modification/atomic_recreation.h
@@ -10,6 +10,7 @@ class Location;
 class AtomicRecreation : public AtomicModification
 {
 public:
+    ~AtomicRecreation() override = default;
 
     /**
      * @return the pickup location added to the solution, nullptr if none were added
diff --git a/src/lns/modification/pair/insert_pair.cpp b/src/lns/modification/pair/insert_pair.cpp
index 206d66f..b3f9d4b 100644
--- a/src/lns/modification/pair/insert_pair.cpp
+++ b/src/lns/modification/pair/insert_pair.cpp
@@ -1,24 +1,22 @@
 #include "insert_pair.h"
-#include "./../../../input/data.h"
+#include "input/data.h"
 
 
-InsertPair::InsertPair(int routeIndex, int pickupInsertion, int deliveryInsertion,
-    Location const &pickupLocation, Location const &deliveryLocation)
-    : routeIndex(routeIndex), 
-      pickupInsertion(pickupInsertion), 
-      deliveryInsertion(deliveryInsertion), 
-      pickupLocation(pickupLocation), 
-      deliveryLocation(deliveryLocation),
-      pair(Pair(pickupLocation, deliveryLocation)) {}
+InsertPair::InsertPair(int routeIndex, int pickupInsertion, int deliveryInsertion, Pair const &pair) : 
+    routeIndex(routeIndex), 
+    pickupInsertion(pickupInsertion), 
+    deliveryInsertion(deliveryInsertion), 
+    pickupLocation(pair.getPickup()), 
+    deliveryLocation(pair.getDelivery()),
+    pair(pair) {}
 
-InsertPair::InsertPair(int routeIndex, int pickupInsertion, int deliveryInsertion, 
-    Pair const &pair) 
-    : routeIndex(routeIndex), 
-      pickupInsertion(pickupInsertion), 
-      deliveryInsertion(deliveryInsertion), 
-      pickupLocation(pair.getPickup()), 
-      deliveryLocation(pair.getDelivery()),
-      pair(pair) {}
+InsertPair::InsertPair(Index position, Pair const &pair) :
+    routeIndex(std::get<0>(position)), 
+    pickupInsertion(std::get<1>(position)), 
+    deliveryInsertion(std::get<2>(position)), 
+    pickupLocation(pair.getPickup()), 
+    deliveryLocation(pair.getDelivery()),
+    pair(pair) {}
 
 
 void InsertPair::modifySolution(Solution &solution) 
@@ -94,4 +92,7 @@ const Pair &InsertPair::getPair() const
     return pair;
 }
 
-
+Index InsertPair::getIndex() const 
+{
+    return std::make_tuple(routeIndex, pickupInsertion, deliveryInsertion);
+}
\ No newline at end of file
diff --git a/src/lns/modification/pair/insert_pair.h b/src/lns/modification/pair/insert_pair.h
index ddeea7f..d806765 100644
--- a/src/lns/modification/pair/insert_pair.h
+++ b/src/lns/modification/pair/insert_pair.h
@@ -1,12 +1,14 @@
 #pragma once
 
-#include "./../atomic_recreation.h"
-#include "./../../solution/solution.h"
-#include "./../../../input/location.h"
-#include "./../../../input/pair.h"
 #include <functional>
+#include <tuple>
+
+#include "lns/modification/atomic_recreation.h"
+#include "lns/solution/solution.h"
+#include "input/location.h"
+#include "input/pair.h"
+#include "types.h"
 
-class Route;
 
 /**
  * A modification that will insert a pair (pickup/delivery) of location in a route at the given index.
@@ -24,6 +26,7 @@ class InsertPair : public AtomicRecreation
      * Index at which the insertion must be made
      */
     int pickupInsertion;
+
     /**
      * Index at which the insertion must be made
      */
@@ -33,6 +36,7 @@ class InsertPair : public AtomicRecreation
      * The pickup location to insert
      */
     Location const & pickupLocation;
+
     /**
      * The delivery location to insert
      */
@@ -41,11 +45,15 @@ class InsertPair : public AtomicRecreation
     Pair const & pair;
 
 public:
-    InsertPair(int routeIndex, int pickupInsertion, int deliveryInsertion, Location const &pickupLocation, Location const &deliveryLocation);
+    
     InsertPair(int routeIndex, int pickupInsertion, int deliveryInsertion, Pair const &pair);
+    InsertPair(Index position, Pair const &pair);
+
+    ~InsertPair() override = default;
 
     void modifySolution(Solution &solution) override;
     double evaluate(Solution const &solution) const override;
+    Location const *getAddedLocation() const override;
 
     int getPickupInsertion() const;
     int getDeliveryInsertion() const;
@@ -53,7 +61,6 @@ public:
     Location const &getPickupLocation() const;
     Location const &getDeliveryLocation() const;
     Pair const &getPair() const;
+    Index getIndex() const;
 
-    Location const *getAddedLocation() const override;
-    
 };  
\ No newline at end of file
diff --git a/src/lns/modification/pair/remove_pair.cpp b/src/lns/modification/pair/remove_pair.cpp
index fcb2fb4..1a1c808 100644
--- a/src/lns/modification/pair/remove_pair.cpp
+++ b/src/lns/modification/pair/remove_pair.cpp
@@ -1,25 +1,25 @@
 #include "remove_pair.h"
-#include "../../../input/data.h"
+#include "input/data.h"
 
 
-RemovePair::RemovePair(int routeIndex, int pickupDeletion, int deliveryDeletion, 
-    Location const &pickupLocation, Location const &deliveryLocation) :
+RemovePair::RemovePair(int routeIndex, int pickupDeletion, int deliveryDeletion, Pair const &pair) :
     routeIndex(routeIndex), 
     pickupDeletion(pickupDeletion), 
     deliveryDeletion(deliveryDeletion), 
-    pickupLocation(pickupLocation), 
-    deliveryLocation(deliveryLocation),
-    pair(Pair(pickupLocation, deliveryLocation)) {}
+    pickupLocation(pair.getPickup()), 
+    deliveryLocation(pair.getDelivery()),
+    pair(pair) {}
 
-RemovePair::RemovePair(int routeIndex, int pickupDeletion, int deliveryDeletion, 
-    Pair const &pair) :
-    routeIndex(routeIndex), 
-    pickupDeletion(pickupDeletion), 
-    deliveryDeletion(deliveryDeletion), 
+
+RemovePair::RemovePair(Index position, Pair const &pair) :
+    routeIndex(std::get<0>(position)), 
+    pickupDeletion(std::get<1>(position)), 
+    deliveryDeletion(std::get<2>(position)), 
     pickupLocation(pair.getPickup()), 
     deliveryLocation(pair.getDelivery()),
     pair(pair) {}
 
+
 void RemovePair::modifySolution(Solution &solution)
 {
     Route &route = solution.getRoute(routeIndex);
@@ -93,4 +93,9 @@ std::vector<int> const & RemovePair::getDeletedRequests() const
 Pair const &RemovePair::getPair() const
 {
     return pair;
+}
+
+Index RemovePair::getIndex() const 
+{
+    return std::make_tuple(routeIndex, pickupDeletion, deliveryDeletion);
 }
\ No newline at end of file
diff --git a/src/lns/modification/pair/remove_pair.h b/src/lns/modification/pair/remove_pair.h
index cb543e7..ef9dbdb 100644
--- a/src/lns/modification/pair/remove_pair.h
+++ b/src/lns/modification/pair/remove_pair.h
@@ -1,12 +1,12 @@
 #pragma once
 
-#include "./../atomic_destruction.h"
-#include "./../../solution/solution.h"
-#include "./../../../input/location.h"
-#include "./../../../input/pair.h"
 #include <functional>
 
-class Route;
+#include "lns/modification/atomic_destruction.h"
+#include "lns/solution/solution.h"
+#include "input/location.h"
+#include "input/pair.h"
+#include "types.h"
 
 /**
  * A modification that will remove a pair (pickup/delivery) of location from the solution.
@@ -22,6 +22,7 @@ class RemovePair : public AtomicDestruction
      * Index at which the deletion must be made
      */
     int pickupDeletion;
+
     /**
      * Index at which the deletion must be made
      */
@@ -31,6 +32,7 @@ class RemovePair : public AtomicDestruction
      * The pickup location to remove
      */
     Location const & pickupLocation;
+    
     /**
      * The delivery location to remove
      */
@@ -45,23 +47,24 @@ class RemovePair : public AtomicDestruction
 
 public:
     
-    RemovePair(int routeIndex, int pickupDeletion, int deliveryDeletion, Location const &pickupLocation, Location const &deliveryLocation);
     RemovePair(int routeIndex, int pickupDeletion, int deliveryDeletion, Pair const &pair);
+    RemovePair(Index position, Pair const &pair);
+    ~RemovePair() override = default;
 
     void modifySolution(Solution &solution) override;
     double evaluate(Solution const &solution) const override;
+    /**
+     *  Return the location ID of location that has been deleted
+     */
+    std::vector<int> const &getDeletedRequests() const override;
 
     int getPickupDeletion() const;
     int getDeliveryDeletion() const;
     int getRouteIndex() const;
     Location const &getPickupLocation() const;
     Location const &getDeliveryLocation() const;
-
     Pair const &getPair() const;
+    Index getIndex() const;
 
-    /**
-     *  Return the location ID of location that has been deleted
-     */
-    std::vector<int> const &getDeletedRequests() const override;
 };  
 
diff --git a/src/lns/modification/route/insert_route.cpp b/src/lns/modification/route/insert_route.cpp
index 5b0b04e..96cf368 100644
--- a/src/lns/modification/route/insert_route.cpp
+++ b/src/lns/modification/route/insert_route.cpp
@@ -1,12 +1,12 @@
 #include "insert_route.h"
 
 
-InsertRoute::InsertRoute() {}
+InsertRoute::InsertRoute() = default;
 
 void InsertRoute::modifySolution(Solution &solution)
 {
     std::vector<Route> &routes = solution.getRoutes();
-    routes.push_back(Route());
+    routes.emplace_back();
 }
 
 double InsertRoute::evaluate(Solution const &solution) const
diff --git a/src/lns/modification/route/insert_route.h b/src/lns/modification/route/insert_route.h
index 1196526..e5d6413 100644
--- a/src/lns/modification/route/insert_route.h
+++ b/src/lns/modification/route/insert_route.h
@@ -1,11 +1,8 @@
 #pragma once
 
-#include "./../atomic_recreation.h"
-#include "./../../solution/solution.h"
-#include "./../../../input/location.h"
-#include <functional>
-
-class Route;
+#include "lns/modification/atomic_recreation.h"
+#include "lns/solution/solution.h"
+#include "input/location.h"
 
 /**
  * Insert a new empty route in the solution
@@ -20,5 +17,4 @@ public:
     void modifySolution(Solution &solution) override;
     double evaluate(Solution const &solution) const override;
     Location const *getAddedLocation() const override;
-    
 };  
\ No newline at end of file
diff --git a/src/lns/modification/route/remove_route.cpp b/src/lns/modification/route/remove_route.cpp
index 8dd22bd..006d5df 100644
--- a/src/lns/modification/route/remove_route.cpp
+++ b/src/lns/modification/route/remove_route.cpp
@@ -1,9 +1,13 @@
 #include "remove_route.h"
-#include "../../../input/data.h"
+
+#include <utility>
+
 
 RemoveRoute::RemoveRoute() : routeIndex(-1), removedLocationID({}) {}
 RemoveRoute::RemoveRoute(int routeIndex) : routeIndex(routeIndex), removedLocationID({}) {}
-RemoveRoute::RemoveRoute(int routeIndex, std::vector<int> removedLocationID) : routeIndex(routeIndex), removedLocationID(removedLocationID) {}
+RemoveRoute::RemoveRoute(int routeIndex, std::vector<int> removedLocationID) : 
+    routeIndex(routeIndex), 
+    removedLocationID(std::move(removedLocationID)) {}
 
 void RemoveRoute::modifySolution(Solution &solution)
 {
@@ -27,7 +31,6 @@ int RemoveRoute::getRouteIndex() const
     return routeIndex;
 }
 
-
 std::vector<int> const &RemoveRoute::getDeletedRequests() const
 {
     return removedLocationID;
diff --git a/src/lns/modification/route/remove_route.h b/src/lns/modification/route/remove_route.h
index 83f67c6..be981e8 100644
--- a/src/lns/modification/route/remove_route.h
+++ b/src/lns/modification/route/remove_route.h
@@ -1,10 +1,11 @@
 #pragma once
 
-#include "./../atomic_destruction.h"
-#include "./../../solution/solution.h"
-#include "./../../../input/location.h"
 #include <functional>
 
+#include "input/data.h"
+#include "input/location.h"
+#include "lns/modification/atomic_destruction.h"
+#include "lns/solution/solution.h"
 
 /**
  * A modification that will remove a route from the solution.
@@ -25,16 +26,15 @@ class RemoveRoute : public AtomicDestruction
 public:
 
     RemoveRoute();
-    RemoveRoute(int routeIndex);
+    explicit RemoveRoute(int routeIndex);
     RemoveRoute(int routeIndex, std::vector<int> removedLocationID);
 
     void modifySolution(Solution &solution) override;
     double evaluate(Solution const &solution) const override;
-
-    int getRouteIndex() const;
-
     /**
-     *  Return the location ID of location that has been deleted
-     */
+    *  Return the location ID of location that has been deleted
+    */
     std::vector<int> const &getDeletedRequests() const override;
+
+    int getRouteIndex() const;
 };
\ No newline at end of file
diff --git a/src/lns/solution/route.h b/src/lns/solution/route.h
index 67686cf..aac7992 100644
--- a/src/lns/solution/route.h
+++ b/src/lns/solution/route.h
@@ -1,7 +1,8 @@
 #pragma once
 
 #include <vector>
-#include "./../../input/time_window.h"
+
+#include "input/time_window.h"
 
 /**
  * Represent a route for the PDPTW
diff --git a/src/lns/solution/solution.cpp b/src/lns/solution/solution.cpp
index 03864d8..8c3bf53 100644
--- a/src/lns/solution/solution.cpp
+++ b/src/lns/solution/solution.cpp
@@ -1,22 +1,91 @@
 #include "solution.h"
-#include <iostream>
-#include <spdlog/spdlog.h>
 
+#include <utility>
 
-Solution::Solution(const PDPTWData &data) 
-    : data(data), totalCost(0) {
+#include "input/data.h"
+#include "input/time_window.h"
+#include "lns/constraints/capacity/capacity_constraint.h"
+#include "lns/constraints/time_window/time_window_constraint.h"
 
-    bank = RequestBank();
-    routes = std::vector<Route>();
+#include "config.h"
+#include "lns/solution/route.h"
+
+void Solution::initPairBank()
+{   
+    pairBank.clear();
+    for (const Pair & pair : getData().getPairs())
+    {
+        pairBank.push_back(pair.getID());
+    }
+}
+
+void Solution::initRoutes()
+{
+    routes.clear();
+}
+
+void Solution::initConstraints()
+{
+    constraints.clear();
+    constraints.push_back(std::make_unique<CapacityConstraint>(*this));
+    constraints.push_back(std::make_unique<TimeWindowConstraint>(*this));
 }
 
+void Solution::computeAndStoreSolutionCost()
+{
+    routeCost = computeSolutionCost();
+
+    // add penalty for solution in the pairBank ? 
+    totalCost = routeCost + computePenalization();
+}
 
-Solution::Solution(const PDPTWData &data, RequestBank bank, std::vector<Route> routes, int totalCost)
-    : data(data), bank(bank), routes(routes), totalCost(totalCost) {}
+double Solution::computeSolutionCost() const
+{
+    double cost = 0;
+    for (const Route & route : getRoutes())
+    {
+        cost += data::routeCost(data, route);
+    }
+    std::cout << "le cout " << cost << " \n";
+    return cost;
+}
+
+double Solution::computePenalization() const
+{
+    return getBank().size() * EXCLUSION_PENALTY;
+}
+
+
+void Solution::init()
+{
+    initPairBank();
+    initRoutes();
+    initConstraints();
+    computeAndStoreSolutionCost();
+}
+
+
+Solution::Solution(const PDPTWData &data, Solution::PairBank pairbank, std::vector<Route> routes, double routeCost, double totalCost) :
+    data(data), 
+    pairBank(std::move(pairbank)), 
+    routes(std::move(routes)), 
+    routeCost(routeCost),
+    totalCost(totalCost) {}
+
+Solution::Solution(const PDPTWData &data) : data(data)
+{
+    init();
+}
+
+Solution Solution::emptySolution(const PDPTWData &data)
+{
+    Solution s = Solution(data);
+    return s;
+}
 
-const std::vector<int> & Solution::getBank() const
+const Solution::PairBank & Solution::getBank() const
 {
-    return bank;
+    return pairBank;
 }
 
 const std::vector<Route> & Solution::getRoutes() const
@@ -49,7 +118,7 @@ const Route & Solution::getRoute(int routeIndex) const
     return routes[routeIndex];
 }
 
-int Solution::getCost()
+double Solution::getCost() const
 {
     return totalCost;
 }
diff --git a/src/lns/solution/solution.h b/src/lns/solution/solution.h
index 453a4f8..48bffda 100644
--- a/src/lns/solution/solution.h
+++ b/src/lns/solution/solution.h
@@ -1,8 +1,19 @@
 #pragma once
 
 #include <vector>
+#include <iostream>
+#include <spdlog/spdlog.h>
+
+
+#include "lns/constraints/constraint.h"
 #include "route.h"
-#include "./../../input/pdptw_data.h"
+#include "input/pair.h"
+
+class AtomicModification;
+class AtomicRecreation;
+class AtomicDestruction;
+class TimeWindowConstraint;
+class CapacityConstraint;
 
 /**
  * Represent a solution of PDPTW
@@ -10,33 +21,71 @@
 class Solution
 {
 public:
-    using RequestBank = std::vector<int>;
+    using PairBank = std::vector<int>;
 
 private:
     PDPTWData const & data;
-    RequestBank bank;
+    /*
+    *   Store IDs of a pairs (Pickup & Delivery) that are not assigned yet to a route.
+    */
+    PairBank pairBank;
+    /*
+    *   Vector of routes representing the solution
+    */
     std::vector<Route> routes;
-    int totalCost;
-
-    static PDPTWData dummy;
+    double routeCost;
+    double totalCost;
+    std::vector<std::unique_ptr<Constraint>> constraints;
 
 public:
-    Solution(const PDPTWData &data);
-    Solution(const PDPTWData &data, RequestBank bank, std::vector<Route> routes, int totalCost);
 
-    RequestBank const & getBank() const;
+    /**
+    *   Expected way to construct a solution.
+    */
+    static Solution emptySolution(const PDPTWData &data);
+
+    explicit Solution(const PDPTWData &data);
+
+    /**
+    *   For testing/debugging.
+    *   Use emptySolution(const PDPTWData &data) to create an initial empty solution.
+    */
+    Solution(const PDPTWData &data, Solution::PairBank pairbank, std::vector<Route> routes, double routeCost, double totalCost);
+
 
+    PairBank const & getBank() const;
     std::vector<Route> const & getRoutes() const;
     Route const & getRoute(int routeIndex) const; 
-
     const PDPTWData & getData() const;
+    double getCost() const;
 
     // For route modification
     std::vector<Route> & getRoutes();
     Route & getRoute(int routeIndex);
     
+    void print() const;
 
-    int getCost();
 
-    void print() const;
+private :
+
+    /**
+    *   Does the initialisation of the object, called by the constructor
+    */
+    void init();
+
+    /**
+    *   Init/reset the constraints of the problem
+    */
+    void initConstraints();
+    void initRoutes();
+    void initPairBank();
+ 
+    void computeAndStoreSolutionCost();
+    
+    /**
+    *   Compute the cost of the solution (routes cost)
+    */
+    double computeSolutionCost() const;
+    
+    double computePenalization() const;
 };
\ No newline at end of file
diff --git a/src/main.cpp b/src/main.cpp
deleted file mode 100644
index 7c736af..0000000
--- a/src/main.cpp
+++ /dev/null
@@ -1,96 +0,0 @@
-
-#include <nlohmann/json.hpp>
-#include <vector>
-#include <iostream>
-#include <string>
-
-#include <filesystem>
-#include <fstream>
-
-#include <spdlog/spdlog.h>
-
-#include "input/location.h"
-#include "input/time_window.h"
-#include "input/json_parser.h"
-#include "input/data.h"
-#include "lns/constraints/capacity/capacity_constraint.h"
-#include "lns/constraints/time_window/time_window_constraint.h"
-#include "lns/solution/solution.h"
-#include "lns/modification/pair/insert_pair.h"
-#include "lns/modification/route/insert_route.h"
-#include "lns/modification/pair/remove_pair.h"
-#include "lns/modification/route/remove_route.h"
-
-namespace fs = std::filesystem;
-using json = nlohmann::json;
-
-int main(int argc, char const *argv[])
-{
-    //std::string filepath = "/home/a24jacqb/Documents/Code/pdptw-main/data_in/test_inst.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";
-
-    std::cout << filepath << "\n";
-
-    PDPTWData data = parsing::parseJson(filepath);
-    data.checkData();
-
-    /* 
-    * test 
-    */
-    Solution emptySol = Solution(data);
-
-    // SOLUTION 1-6-2-7 (time ; 104)
-
-    Solution::RequestBank bank {3,4,5,8,9,10};
-
-    std::vector<int> path {1,2,6,7};
-    Route route = Route(path, 0);
-    std::vector<Route> routes;
-    routes.push_back(route);
-
-    int totalCost = 0;
-    
-    Solution sol = Solution(data, bank, routes, totalCost);
-
-    sol.print();
-
-
-    // Couple pickup/delivery
-    Location r2P = data.getLocations()[1];
-    Location r2D = data.getLocations()[6];
-    Location r3P = data.getLocations()[2];
-    Location r3D = data.getLocations()[7];
-
-    Pair pair2 = Pair(r2P, r2D);
-    Pair pair3 = Pair(r3P, r3D);
-    
-    // Modification 
-    InsertPair opInsert = InsertPair(0, 2, 2, pair3);
-
-    /*
-
-    CapacityConstraint cap_const = CapacityConstraint(sol);
-    
-
-    cap_const.initCapacities();
-    cap_const.print();
-
-    std::cout << "Is Valid ? : " << cap_const.checkVariant(opInsert) << "\n";
-
-    cap_const.applyVariant(opInsert);
-
-    cap_const.print();
-
-    RemovePair opRemove = RemovePair(0, 2, 3, pair3);
-
-    cap_const.applyVariant(opRemove);
-    
-    cap_const.print();
-    */
-
-
-    TimeWindowConstraint twconst = TimeWindowConstraint(sol);
-    return 0;
-}
diff --git a/src/mains/main.cpp b/src/mains/main.cpp
new file mode 100644
index 0000000..67c7b74
--- /dev/null
+++ b/src/mains/main.cpp
@@ -0,0 +1,123 @@
+
+#include <nlohmann/json.hpp>
+#include <vector>
+#include <iostream>
+#include <string>
+#include <filesystem>
+#include <fstream>
+#include <spdlog/spdlog.h>
+
+#include "input/location.h"
+#include "input/time_window.h"
+#include "input/json_parser.h"
+#include "input/data.h"
+#include "lns/constraints/capacity/capacity_constraint.h"
+#include "lns/constraints/time_window/time_window_constraint.h"
+#include "lns/solution/solution.h"
+#include "lns/modification/pair/insert_pair.h"
+#include "lns/modification/route/insert_route.h"
+#include "lns/modification/pair/remove_pair.h"
+#include "lns/modification/route/remove_route.h"
+
+using json = nlohmann::json;
+
+int main(int argc, char const *argv[])
+{
+    //std::string filepath = "/home/a24jacqb/Documents/Code/pdptw-main/data_in/test_inst.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";
+
+    std::cout << filepath << "\n";
+
+    PDPTWData data = parsing::parseJson(filepath);
+    data.checkData();
+
+    data.print();
+    
+    std::cout << " \n";
+    /* 
+    * test 
+    */
+    Solution emptySol = Solution::emptySolution(data);
+    emptySol.print();
+
+    
+
+    // // SOLUTION 1-6-2-7 (time ; 104)
+
+    // Solution::PairBank bank {3,4,5,8,9,10};
+
+    // std::vector<int> path {1,6,2,7};
+    // Route route = Route(path, 0);
+    // std::vector<Route> routes;
+    // routes.push_back(route);
+
+    // int totalCost = 0;
+    
+    // Solution sol = Solution(data, bank, routes, totalCost);
+
+    // sol.print();
+
+
+    // // Couple pickup/delivery
+    // Location r2P = data.getLocations()[1];
+    // Location r2D = data.getLocations()[6];
+    // Location r3P = data.getLocations()[2];
+    // Location r3D = data.getLocations()[7];
+
+    // Pair pair2 = Pair(r2P, r2D);
+    // Pair pair3 = Pair(r3P, r3D);
+
+
+
+    // /*
+
+    // CapacityConstraint cap_const = CapacityConstraint(sol);
+    
+
+    // cap_const.initCapacities();
+    // cap_const.print();
+
+    // std::cout << "Is Valid ? : " << cap_const.checkVariant(opInsert) << "\n";
+
+    // cap_const.applyVariant(opInsert);
+
+    // cap_const.print();
+
+    // RemovePair opRemove = RemovePair(0, 2, 3, pair3);
+
+    // cap_const.applyVariant(opRemove);
+    
+    // cap_const.print();
+    // */
+
+
+    // TimeWindowConstraint twconst = TimeWindowConstraint(sol);
+
+    // std::cout << "\n --- : \n";
+    
+    // twconst.print();
+
+    // twconst.initReachTimes();
+
+    // twconst.print();
+    
+    // // Modification 
+    // InsertPair opInsert = InsertPair(0, 0, 0, pair3);
+
+    // std::cout << "is valid ? : " << twconst.checkVariant(opInsert) << "\n";
+
+    // twconst.applyVariant(opInsert);
+
+    // twconst.print();
+    // opInsert.modifySolution(sol);
+
+    // RemovePair opRemove = RemovePair(0, 0, 1, pair3);
+
+    // twconst.applyVariant(opRemove);
+    
+    // twconst.print();
+
+    return 0;
+}
diff --git a/src/mains/main_interface.cpp b/src/mains/main_interface.cpp
new file mode 100644
index 0000000..58ad8a7
--- /dev/null
+++ b/src/mains/main_interface.cpp
@@ -0,0 +1,41 @@
+#include "input/json_parser.h"
+#include "input/pdptw_data.h"
+#include "main_interface.h"
+
+#include <fstream>
+#include <nlohmann/json.hpp>
+#include <spdlog/spdlog.h>
+
+int mainInterface(int argc, char **argv, std::function<void(PDPTWData &, Solution &)> function)
+{
+
+    try
+    {
+        if (argc <= 1) 
+        {
+            spdlog::error("No arguments provided. Expected: one command line argument.");
+            throw std::runtime_error("Error : No arguments provided.");
+        }
+
+        if (argc > 2) 
+        {
+            spdlog::error("Too many arguments provided. Expected: one command line argument.");
+            throw std::runtime_error("Error : Too many arguments arguments provided.");
+        }
+
+        std::string filepath = argv[1];
+        PDPTWData data = parsing::parseJson(filepath);
+        Solution startingSolution = Solution::emptySolution(data);
+
+        function(data, startingSolution);
+
+    } 
+    catch (const std::exception& e) 
+    {
+        spdlog::critical("Exception caught : {}", e.what());
+        return 1;
+    }
+
+    spdlog::info("Fin");
+    return 0;
+}
diff --git a/src/mains/main_interface.h b/src/mains/main_interface.h
new file mode 100644
index 0000000..5efebfe
--- /dev/null
+++ b/src/mains/main_interface.h
@@ -0,0 +1,8 @@
+#pragma once
+
+#include "input/pdptw_data.h"
+#include "lns/solution/solution.h"
+
+#include <functional>
+
+int mainInterface(int argc, char **argv, std::function<void(PDPTWData &, Solution &)> function);
diff --git a/src/types.h b/src/types.h
new file mode 100644
index 0000000..00139bf
--- /dev/null
+++ b/src/types.h
@@ -0,0 +1,23 @@
+#pragma once
+
+#include <iostream>
+#include <limits>
+#include <tuple>
+#include <vector>
+
+/**
+ *   Represent a pair (pickup/delivery) position in a solution.
+ *   (Route Index, Pickup Position, Delivery Position).
+ *   Used in insertion/deletion modifications.
+ */
+using Index = std::tuple<int, int, int>;
+
+/**
+ *  A point in time or a duration.
+ */
+using TimeInteger = double;
+TimeInteger constexpr UNDEF_TIMESTAMP = std::numeric_limits<TimeInteger>::max();
+
+
+using Matrix = std::vector<std::vector<double>>; 
+
-- 
GitLab