From 93a7191a1d281ca28c4ffda56dba2ba55633bb40 Mon Sep 17 00:00:00 2001
From: Romain BERNARD <romain.bernard@uca.fr>
Date: Fri, 22 Mar 2024 16:10:43 +0100
Subject: [PATCH 001/327] create time windows struct

---
 src/TimeWindow.cpp | 54 ++++++++++++++++++++++++++++++++++++++++++++++
 src/TimeWindow.h   | 39 +++++++++++++++++++++++++++++++++
 2 files changed, 93 insertions(+)
 create mode 100644 src/TimeWindow.cpp
 create mode 100644 src/TimeWindow.h

diff --git a/src/TimeWindow.cpp b/src/TimeWindow.cpp
new file mode 100644
index 0000000..0e829bc
--- /dev/null
+++ b/src/TimeWindow.cpp
@@ -0,0 +1,54 @@
+//
+// Created by romain on 22/03/24.
+//
+
+#include "TimeWindow.h"
+
+
+TimeWindow TimeWindow::operator+(int rhs) const {
+    return TimeWindow(this->min + rhs, this->max + rhs);
+}
+
+TimeWindow& TimeWindow::operator+=(int rhs) {
+    this->min += rhs;
+    this->max += rhs;
+    return *this;
+}
+
+TimeWindow TimeWindow::operator-(int rhs) const {
+    return TimeWindow(this->min - rhs, this->max - rhs);
+}
+
+TimeWindow& TimeWindow::operator-=(int rhs) {
+    this->min -= rhs;
+    this->max -= rhs;
+    return *this;
+}
+
+TimeWindow TimeWindow::operator+(const TimeWindow& rhs) const {
+    return TimeWindow(this->min + rhs.min, this->max + rhs.max);
+}
+
+TimeWindow& TimeWindow::operator+=(const TimeWindow& rhs) {
+    this->min += rhs.min;
+    this->max += rhs.max;
+    return *this;
+}
+
+TimeWindow TimeWindow::operator-(const TimeWindow& rhs) const {
+    return TimeWindow(this->min - rhs.min, this->max - rhs.max);
+}
+
+TimeWindow& TimeWindow::operator-=(const TimeWindow& rhs) {
+    this->min -= rhs.min;
+    this->max -= rhs.max;
+    return *this;
+}
+
+bool TimeWindow::isInTimeWindow(int instant) const {
+    return this->min <= instant && this->max >= instant;
+}
+
+bool TimeWindow::isInTimeWindow(const TimeWindow &instant) const {
+    return this->isInTimeWindow(instant.min) && this->isInTimeWindow(instant.max);
+}
diff --git a/src/TimeWindow.h b/src/TimeWindow.h
new file mode 100644
index 0000000..ef2f72f
--- /dev/null
+++ b/src/TimeWindow.h
@@ -0,0 +1,39 @@
+//
+// Created by romain on 22/03/24.
+//
+
+#ifndef GREEDYALGORITHM_TIMEWINDOW_H
+#define GREEDYALGORITHM_TIMEWINDOW_H
+
+/**
+ * Represents [min, max] time windows with appropriate operators for TW operations (+,-,isInTimeWindow).
+ * Prefer using +=/-= notations to modify in place, as + and - operators return a new TimeWindow object.
+ */
+struct TimeWindow {
+    int min = 0, max = 0;
+    TimeWindow() = default;
+    TimeWindow(int min, int max) : min(min), max(max) {}
+    /**
+     * Checks if the given instant is inside the [min,max] interval
+     * @return True iff instant is in the time window, false otherwise
+     */
+    [[nodiscard]] bool isInTimeWindow(int instant) const;
+    /**
+    * Checks if the given time window is contained inside the [min,max] interval of this
+    * @return True iff instant is in the time window, false otherwise
+    */
+    [[nodiscard]] bool isInTimeWindow(const TimeWindow& instant) const;
+
+    TimeWindow operator+(int rhs) const;
+    TimeWindow& operator+=(int rhs);
+    TimeWindow operator-(int rhs) const;
+    TimeWindow& operator-=(int rhs);
+    TimeWindow operator+(const TimeWindow& rhs) const;
+    TimeWindow& operator+=(const TimeWindow& rhs);
+    TimeWindow operator-(const TimeWindow& rhs) const;
+    TimeWindow& operator-=(const TimeWindow& rhs);
+    TimeWindow& operator=(const TimeWindow& rhs) = default;
+};
+
+
+#endif //GREEDYALGORITHM_TIMEWINDOW_H
-- 
GitLab


From 449dc4ff92f3a61195aad4f420d228da2c07f0b5 Mon Sep 17 00:00:00 2001
From: Romain BERNARD <romain.bernard@uca.fr>
Date: Fri, 22 Mar 2024 16:46:04 +0100
Subject: [PATCH 002/327] Create VehicleType

---
 src/instance/VehicleType.cpp |  5 +++++
 src/instance/VehicleType.h   | 22 ++++++++++++++++++++++
 2 files changed, 27 insertions(+)
 create mode 100644 src/instance/VehicleType.cpp
 create mode 100644 src/instance/VehicleType.h

diff --git a/src/instance/VehicleType.cpp b/src/instance/VehicleType.cpp
new file mode 100644
index 0000000..0a340bb
--- /dev/null
+++ b/src/instance/VehicleType.cpp
@@ -0,0 +1,5 @@
+//
+// Created by romain on 22/03/24.
+//
+
+#include "VehicleType.h"
diff --git a/src/instance/VehicleType.h b/src/instance/VehicleType.h
new file mode 100644
index 0000000..bf09425
--- /dev/null
+++ b/src/instance/VehicleType.h
@@ -0,0 +1,22 @@
+//
+// Created by romain on 22/03/24.
+//
+
+#ifndef GREEDYALGORITHM_VEHICLETYPE_H
+#define GREEDYALGORITHM_VEHICLETYPE_H
+
+
+class VehicleType {
+private:
+    const int capacity;
+
+public:
+    explicit VehicleType(const int capacity) : capacity(capacity) {}
+
+    [[nodiscard]] int getCapacity() const {
+        return capacity;
+    }
+};
+
+
+#endif //GREEDYALGORITHM_VEHICLETYPE_H
-- 
GitLab


From b87e0b38962eca85e08d5438d4f51c3c85707434 Mon Sep 17 00:00:00 2001
From: Romain BERNARD <romain.bernard@uca.fr>
Date: Fri, 22 Mar 2024 16:53:31 +0100
Subject: [PATCH 003/327] Add new data to Instance

---
 src/instance/Instance.h | 7 +++++++
 1 file changed, 7 insertions(+)

diff --git a/src/instance/Instance.h b/src/instance/Instance.h
index ebf12ec..e99282d 100644
--- a/src/instance/Instance.h
+++ b/src/instance/Instance.h
@@ -4,18 +4,25 @@
 
 #ifndef GREEDYALGORITHM_INSTANCE_H
 #define GREEDYALGORITHM_INSTANCE_H
+#include <utility>
 #include <vector>
 #include "requests/Request.h"
 #include "graph/Graph.h"
+#include "SAEVehicle.h"
 
 class Instance {
 private:
     std::vector<Request> requests;
     Graph graph;
+    int vehicleCapacity;
 
 public:
+    Instance(const std::vector<Request> &requests, Graph graph, const int vehicleCapacity) : requests(
+            requests), graph(std::move(graph)), vehicleCapacity(vehicleCapacity) {}
+
     [[nodiscard]] Graph const & getGraph() const { return graph;}
     [[nodiscard]] std::vector<Request> const & getRequests() const { return requests;}
+    [[nodiscard]] int getVehicleCapacity() const { return vehicleCapacity; }
 };
 
 
-- 
GitLab


From 17119024f79b2f588d51a1a297a1442902de8dc3 Mon Sep 17 00:00:00 2001
From: Romain BERNARD <romain.bernard@uca.fr>
Date: Fri, 22 Mar 2024 16:58:48 +0100
Subject: [PATCH 004/327] Rename VehicleType to prevent confusions

---
 .../{VehicleType.cpp => SAEVehicle.cpp}       |  2 +-
 src/instance/SAEVehicle.h                     | 22 +++++++++++++++++++
 src/instance/VehicleType.h                    | 22 -------------------
 3 files changed, 23 insertions(+), 23 deletions(-)
 rename src/instance/{VehicleType.cpp => SAEVehicle.cpp} (62%)
 create mode 100644 src/instance/SAEVehicle.h
 delete mode 100644 src/instance/VehicleType.h

diff --git a/src/instance/VehicleType.cpp b/src/instance/SAEVehicle.cpp
similarity index 62%
rename from src/instance/VehicleType.cpp
rename to src/instance/SAEVehicle.cpp
index 0a340bb..bac525f 100644
--- a/src/instance/VehicleType.cpp
+++ b/src/instance/SAEVehicle.cpp
@@ -2,4 +2,4 @@
 // Created by romain on 22/03/24.
 //
 
-#include "VehicleType.h"
+#include "SAEVehicle.h"
diff --git a/src/instance/SAEVehicle.h b/src/instance/SAEVehicle.h
new file mode 100644
index 0000000..02962f7
--- /dev/null
+++ b/src/instance/SAEVehicle.h
@@ -0,0 +1,22 @@
+//
+// Created by romain on 22/03/24.
+//
+
+#ifndef GREEDYALGORITHM_SAEVEHICLE_H
+#define GREEDYALGORITHM_SAEVEHICLE_H
+
+
+class SAEVehicle {
+private:
+    const int capacity;
+
+public:
+    explicit SAEVehicle(const int capacity) : capacity(capacity) {}
+
+    [[nodiscard]] int getCapacity() const {
+        return capacity;
+    }
+};
+
+
+#endif //GREEDYALGORITHM_SAEVEHICLE_H
diff --git a/src/instance/VehicleType.h b/src/instance/VehicleType.h
deleted file mode 100644
index bf09425..0000000
--- a/src/instance/VehicleType.h
+++ /dev/null
@@ -1,22 +0,0 @@
-//
-// Created by romain on 22/03/24.
-//
-
-#ifndef GREEDYALGORITHM_VEHICLETYPE_H
-#define GREEDYALGORITHM_VEHICLETYPE_H
-
-
-class VehicleType {
-private:
-    const int capacity;
-
-public:
-    explicit VehicleType(const int capacity) : capacity(capacity) {}
-
-    [[nodiscard]] int getCapacity() const {
-        return capacity;
-    }
-};
-
-
-#endif //GREEDYALGORITHM_VEHICLETYPE_H
-- 
GitLab


From a6970053d558475533ed6848fdee174e6d5ceb9f Mon Sep 17 00:00:00 2001
From: Romain BERNARD <romain.bernard@uca.fr>
Date: Fri, 22 Mar 2024 17:30:30 +0100
Subject: [PATCH 005/327] add data to request objects

---
 CMakeLists.txt                    | 21 +++++++++++++++++++++
 src/instance/requests/Request.cpp |  8 ++++++++
 src/instance/requests/Request.h   | 19 +++++++++++++++++++
 3 files changed, 48 insertions(+)

diff --git a/CMakeLists.txt b/CMakeLists.txt
index 4bea03d..c1ceacf 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -7,6 +7,9 @@ add_definitions(-DDEBUG_TRANSIT_PRECOMPUTE)
 
 add_subdirectory(test)
 
+#set(PYTHON_INCLUDE_DIRS "/usr/include/python3.10/")
+find_package (Python COMPONENTS Interpreter Development)
+
 add_executable(GreedyAlgorithm
         src/instance/graph/Node.cpp
         src/instance/graph/Node.h
@@ -38,4 +41,22 @@ add_executable(GreedyAlgorithm
         src/ShortestPath/Transit/TransitAlgorithmState.h
         src/ShortestPath/Transit/TransitShortestPathContainer.cpp
         src/ShortestPath/Transit/TransitShortestPathContainer.h
+        src/routes/RequestRoute.cpp
+        src/routes/RequestRoute.h
+        src/routes/SAEVRoute.cpp
+        src/routes/SAEVRoute.h
+        src/TimeWindow.cpp
+        src/TimeWindow.h
+        src/routes/KeyPoint.cpp
+        src/routes/KeyPoint.h
+        src/routes/RequestKeyPoint.cpp
+        src/routes/RequestKeyPoint.h
+        src/routes/SAEVKeyPoint.cpp
+        src/routes/SAEVKeyPoint.h
+        src/instance/SAEVehicle.cpp
+        src/instance/SAEVehicle.h
 )
+
+target_include_directories(GreedyAlgorithm PRIVATE ${PYTHON_INCLUDE_DIRS})
+target_link_libraries(GreedyAlgorithm ${PYTHON_LIBRARIES})
+
diff --git a/src/instance/requests/Request.cpp b/src/instance/requests/Request.cpp
index a3625a3..c70e76f 100644
--- a/src/instance/requests/Request.cpp
+++ b/src/instance/requests/Request.cpp
@@ -3,3 +3,11 @@
 //
 
 #include "Request.h"
+
+Request::Request(const int departureNodeIndex, const int arrivalNodeIndex, const TimeWindow &arrivalTw,
+                 const int deltaTime, const int weight) : _departureNodeIndex(departureNodeIndex),
+                                                          _arrivalNodeIndex(arrivalNodeIndex), _arrivalTW(arrivalTw),
+                                                          _deltaTime(deltaTime), _weight(weight) {
+    _currentDeltaTime = deltaTime;
+    _departureTW = _arrivalTW - deltaTime;
+}
diff --git a/src/instance/requests/Request.h b/src/instance/requests/Request.h
index 775006c..420f8cd 100644
--- a/src/instance/requests/Request.h
+++ b/src/instance/requests/Request.h
@@ -6,8 +6,27 @@
 #define GREEDYALGORITHM_REQUEST_H
 
 
+#include "../../TimeWindow.h"
+#include "../../routes/RequestRoute.h"
+
 class Request {
+private:
+    //Request base members (const and initialized on _request creation)
+    const int _departureNodeIndex; //Starting point of the user _request //TODO (?) change this to a Node pointer eventually
+    const int _arrivalNodeIndex; //
+    const TimeWindow _arrivalTW; //[min,max] time window for arrival to the destination node
+    const int _deltaTime; //Base delta time, aka the maximum total duration of the path to serve this _request
+    const int _weight; //How much space the requests takes in the vehicle (defaults to 1)
 
+    //Request helpful members (used for constraint propagation and remember the current state of the _request)
+    int _currentDeltaTime; //deltaTime - currentRouteDuration
+    int _requestServiceStart;
+    int _requestServiceEnd;
+    RequestRoute _currentRoute;
+    TimeWindow _departureTW; //For now, a virtual TW on departures, used for constraint propagation
+public:
+    Request(const int departureNodeIndex, const int arrivalNodeIndex,
+            const TimeWindow &arrivalTw, const int deltaTime, const int weight);
 };
 
 
-- 
GitLab


From 0b17ccfee0912d508e9d490fb8ec084f6df0033d Mon Sep 17 00:00:00 2001
From: Romain BERNARD <romain.bernard@uca.fr>
Date: Fri, 22 Mar 2024 17:31:04 +0100
Subject: [PATCH 006/327] initialize data structures for route creation (TODO :
 tests, add constraint propagation)

---
 src/routes/KeyPoint.cpp        | 43 ++++++++++++++++++++++++++++++++++
 src/routes/KeyPoint.h          | 42 +++++++++++++++++++++++++++++++++
 src/routes/RequestKeyPoint.cpp | 23 ++++++++++++++++++
 src/routes/RequestKeyPoint.h   | 30 ++++++++++++++++++++++++
 src/routes/RequestRoute.cpp    |  5 ++++
 src/routes/RequestRoute.h      | 35 +++++++++++++++++++++++++++
 src/routes/SAEVKeyPoint.cpp    | 21 +++++++++++++++++
 src/routes/SAEVKeyPoint.h      | 26 ++++++++++++++++++++
 src/routes/SAEVRoute.cpp       |  5 ++++
 src/routes/SAEVRoute.h         | 20 ++++++++++++++++
 10 files changed, 250 insertions(+)
 create mode 100644 src/routes/KeyPoint.cpp
 create mode 100644 src/routes/KeyPoint.h
 create mode 100644 src/routes/RequestKeyPoint.cpp
 create mode 100644 src/routes/RequestKeyPoint.h
 create mode 100644 src/routes/RequestRoute.cpp
 create mode 100644 src/routes/RequestRoute.h
 create mode 100644 src/routes/SAEVKeyPoint.cpp
 create mode 100644 src/routes/SAEVKeyPoint.h
 create mode 100644 src/routes/SAEVRoute.cpp
 create mode 100644 src/routes/SAEVRoute.h

diff --git a/src/routes/KeyPoint.cpp b/src/routes/KeyPoint.cpp
new file mode 100644
index 0000000..b3fcc19
--- /dev/null
+++ b/src/routes/KeyPoint.cpp
@@ -0,0 +1,43 @@
+//
+// Created by romain on 22/03/24.
+//
+
+#include "KeyPoint.h"
+
+KeyPoint::KeyPoint() = default;
+KeyPoint::KeyPoint(int nodeIndex, int arrivalInstant, int departureInstant) : _nodeIndex(nodeIndex),
+                                                                              _arrivalInstant(arrivalInstant),
+                                                                              _departureInstant(departureInstant) {}
+
+int KeyPoint::getNodeIndex() const {
+    return _nodeIndex;
+}
+
+void KeyPoint::setNodeIndex(int nodeIndex) {
+    KeyPoint::_nodeIndex = nodeIndex;
+}
+
+int KeyPoint::getArrivalInstant() const {
+    return _arrivalInstant;
+}
+
+void KeyPoint::setArrivalInstant(int arrivalInstant) {
+    KeyPoint::_arrivalInstant = arrivalInstant;
+}
+
+int KeyPoint::getDepartureInstant() const {
+    return _departureInstant;
+}
+
+void KeyPoint::setDepartureInstant(int departureInstant) {
+    KeyPoint::_departureInstant = departureInstant;
+}
+
+bool KeyPoint::isBeforeKeyPoint(const KeyPoint &kp) const {
+    return _departureInstant <= kp.getArrivalInstant();
+}
+
+bool KeyPoint::isAfterKeyPoint(const KeyPoint &kp) const {
+    return _arrivalInstant >= kp.getDepartureInstant();
+}
+
diff --git a/src/routes/KeyPoint.h b/src/routes/KeyPoint.h
new file mode 100644
index 0000000..a595fb5
--- /dev/null
+++ b/src/routes/KeyPoint.h
@@ -0,0 +1,42 @@
+//
+// Created by romain on 22/03/24.
+//
+
+#ifndef GREEDYALGORITHM_KEYPOINT_H
+#define GREEDYALGORITHM_KEYPOINT_H
+
+
+class KeyPoint {
+private:
+    int _nodeIndex{};
+    int _arrivalInstant{};
+    int _departureInstant{};
+
+public:
+    KeyPoint(int nodeIndex, int arrivalInstant, int departureInstant);
+
+    KeyPoint();
+
+    [[nodiscard]] int getNodeIndex() const;
+    void setNodeIndex(int nodeIndex);
+
+    [[nodiscard]] int getArrivalInstant() const;
+    void setArrivalInstant(int arrivalInstant);
+
+    [[nodiscard]] int getDepartureInstant() const;
+    void setDepartureInstant(int departureInstant);
+
+    /**
+     * Returns true if this is temporally before (or at the same time) as the given key point
+     * @return true if we arrive on the given key point after (or at the same time as) when we depart from this key point
+     */
+    [[nodiscard]] bool isBeforeKeyPoint(const KeyPoint& kp) const;
+    /**
+     * Returns true if this is temporally after (or at the same time) as the given key point
+     * @return true if we arrive on the given key point after (or at the same time as) when we depart from this key point
+     */
+     [[nodiscard]] bool isAfterKeyPoint(const KeyPoint& kp) const;
+};
+
+
+#endif //GREEDYALGORITHM_KEYPOINT_H
diff --git a/src/routes/RequestKeyPoint.cpp b/src/routes/RequestKeyPoint.cpp
new file mode 100644
index 0000000..7c8b32f
--- /dev/null
+++ b/src/routes/RequestKeyPoint.cpp
@@ -0,0 +1,23 @@
+//
+// Created by romain on 22/03/24.
+//
+
+#include "RequestKeyPoint.h"
+
+SAEVehicle *RequestKeyPoint::getSAEV() const {
+    return _saev;
+}
+
+void RequestKeyPoint::setSAEV(SAEVehicle *saev) {
+    _saev = saev;
+    _lineStop = nullptr;
+}
+
+LineStop *RequestKeyPoint::getLineStop() const {
+    return _lineStop;
+}
+
+void RequestKeyPoint::setLineStop(LineStop *lineStop) {
+    _lineStop = lineStop;
+    _saev = nullptr;
+}
diff --git a/src/routes/RequestKeyPoint.h b/src/routes/RequestKeyPoint.h
new file mode 100644
index 0000000..32358b8
--- /dev/null
+++ b/src/routes/RequestKeyPoint.h
@@ -0,0 +1,30 @@
+//
+// Created by romain on 22/03/24.
+//
+
+#ifndef GREEDYALGORITHM_REQUESTKEYPOINT_H
+#define GREEDYALGORITHM_REQUESTKEYPOINT_H
+
+
+#include "KeyPoint.h"
+#include "../instance/SAEVehicle.h"
+#include "../instance/graph/LineStop.h"
+
+class RequestKeyPoint : KeyPoint {
+private:
+    SAEVehicle* _saev;
+    LineStop* _lineStop;
+
+public:
+    RequestKeyPoint() = default;
+    explicit RequestKeyPoint(SAEVehicle* vehicle) { _saev = vehicle; }
+
+    [[nodiscard]] SAEVehicle *getSAEV() const;
+    void setSAEV(SAEVehicle *saev);
+
+    [[nodiscard]] LineStop *getLineStop() const;
+    void setLineStop(LineStop *lineStop);
+};
+
+
+#endif //GREEDYALGORITHM_REQUESTKEYPOINT_H
diff --git a/src/routes/RequestRoute.cpp b/src/routes/RequestRoute.cpp
new file mode 100644
index 0000000..8aeea6c
--- /dev/null
+++ b/src/routes/RequestRoute.cpp
@@ -0,0 +1,5 @@
+//
+// Created by romain on 22/03/24.
+//
+
+#include "RequestRoute.h"
diff --git a/src/routes/RequestRoute.h b/src/routes/RequestRoute.h
new file mode 100644
index 0000000..a44f962
--- /dev/null
+++ b/src/routes/RequestRoute.h
@@ -0,0 +1,35 @@
+//
+// Created by romain on 22/03/24.
+//
+
+#ifndef GREEDYALGORITHM_REQUESTROUTE_H
+#define GREEDYALGORITHM_REQUESTROUTE_H
+
+
+#include "RequestKeyPoint.h"
+
+class RequestRoute {
+private:
+    RequestKeyPoint route[4];
+public:
+    RequestRoute() = default;
+
+    [[nodiscard]] int getNodeIndex(int routeIndex) const;
+    void setNodeIndex(int routeIndex, int nodeIndex);
+
+    [[nodiscard]] int getArrivalInstant(int routeIndex) const;
+    void setArrivalInstant(int routeIndex, int arrivalInstant);
+
+    [[nodiscard]] int getDepartureInstant(int routeIndex) const;
+    void setDepartureInstant(int routeIndex, int departureInstant);
+
+    [[nodiscard]] SAEVehicle *getSAEV(int routeIndex) const;
+    void setSAEV(int routeIndex, SAEVehicle *saev);
+
+    [[nodiscard]] LineStop *getLineStop(int routeIndex) const;
+    void setLineStop(int routeIndex, LineStop *lineStop);
+
+};
+
+
+#endif //GREEDYALGORITHM_REQUESTROUTE_H
diff --git a/src/routes/SAEVKeyPoint.cpp b/src/routes/SAEVKeyPoint.cpp
new file mode 100644
index 0000000..12454f0
--- /dev/null
+++ b/src/routes/SAEVKeyPoint.cpp
@@ -0,0 +1,21 @@
+//
+// Created by romain on 22/03/24.
+//
+
+#include "SAEVKeyPoint.h"
+
+Request *SAEVKeyPoint::getRequest() const {
+    return _request;
+}
+
+void SAEVKeyPoint::setRequest(Request *request) {
+    SAEVKeyPoint::_request = request;
+}
+
+bool SAEVKeyPoint::isEntry() const {
+    return _isEntry;
+}
+
+void SAEVKeyPoint::setIsEntry(bool isEntry) {
+    SAEVKeyPoint::_isEntry = isEntry;
+}
diff --git a/src/routes/SAEVKeyPoint.h b/src/routes/SAEVKeyPoint.h
new file mode 100644
index 0000000..09f94fe
--- /dev/null
+++ b/src/routes/SAEVKeyPoint.h
@@ -0,0 +1,26 @@
+//
+// Created by romain on 22/03/24.
+//
+
+#ifndef GREEDYALGORITHM_SAEVKEYPOINT_H
+#define GREEDYALGORITHM_SAEVKEYPOINT_H
+
+
+#include "../instance/requests/Request.h"
+#include "KeyPoint.h"
+
+class SAEVKeyPoint : KeyPoint {
+private:
+    Request* _request;
+    bool _isEntry;
+
+public:
+    [[nodiscard]] Request *getRequest() const;
+    void setRequest(Request *request);
+
+    [[nodiscard]] bool isEntry() const;
+    void setIsEntry(bool isEntry);
+};
+
+
+#endif //GREEDYALGORITHM_SAEVKEYPOINT_H
diff --git a/src/routes/SAEVRoute.cpp b/src/routes/SAEVRoute.cpp
new file mode 100644
index 0000000..d467cbb
--- /dev/null
+++ b/src/routes/SAEVRoute.cpp
@@ -0,0 +1,5 @@
+//
+// Created by romain on 22/03/24.
+//
+
+#include "SAEVRoute.h"
diff --git a/src/routes/SAEVRoute.h b/src/routes/SAEVRoute.h
new file mode 100644
index 0000000..9fcac2f
--- /dev/null
+++ b/src/routes/SAEVRoute.h
@@ -0,0 +1,20 @@
+//
+// Created by romain on 22/03/24.
+//
+
+#ifndef GREEDYALGORITHM_SAEVROUTE_H
+#define GREEDYALGORITHM_SAEVROUTE_H
+
+
+#include <vector>
+#include "SAEVKeyPoint.h"
+
+class SAEVRoute {
+private:
+    std::vector<SAEVKeyPoint> route;
+public:
+    void emplaceBack(SAEVKeyPoint keyPoint) { route.emplace_back(keyPoint); }
+};
+
+
+#endif //GREEDYALGORITHM_SAEVROUTE_H
-- 
GitLab


From 10cb1069535e022851420d443bc33d38e6404d9e Mon Sep 17 00:00:00 2001
From: Romain BERNARD <romain.bernard@uca.fr>
Date: Mon, 25 Mar 2024 11:17:07 +0100
Subject: [PATCH 007/327] Add checks and virtual inheritance

---
 src/routes/KeyPoint.cpp        |  4 ++++
 src/routes/KeyPoint.h          |  4 +++-
 src/routes/RequestKeyPoint.cpp |  9 +++++++++
 src/routes/RequestKeyPoint.h   |  5 ++++-
 src/routes/SAEVKeyPoint.cpp    | 10 ++++++++++
 src/routes/SAEVKeyPoint.h      |  6 +++++-
 6 files changed, 35 insertions(+), 3 deletions(-)

diff --git a/src/routes/KeyPoint.cpp b/src/routes/KeyPoint.cpp
index b3fcc19..8c41501 100644
--- a/src/routes/KeyPoint.cpp
+++ b/src/routes/KeyPoint.cpp
@@ -41,3 +41,7 @@ bool KeyPoint::isAfterKeyPoint(const KeyPoint &kp) const {
     return _arrivalInstant >= kp.getDepartureInstant();
 }
 
+bool KeyPoint::check() const {
+    return _arrivalInstant <= _departureInstant;
+}
+
diff --git a/src/routes/KeyPoint.h b/src/routes/KeyPoint.h
index a595fb5..7bef9fd 100644
--- a/src/routes/KeyPoint.h
+++ b/src/routes/KeyPoint.h
@@ -7,7 +7,7 @@
 
 
 class KeyPoint {
-private:
+protected:
     int _nodeIndex{};
     int _arrivalInstant{};
     int _departureInstant{};
@@ -36,6 +36,8 @@ public:
      * @return true if we arrive on the given key point after (or at the same time as) when we depart from this key point
      */
      [[nodiscard]] bool isAfterKeyPoint(const KeyPoint& kp) const;
+
+    virtual [[nodiscard]] bool check() const;
 };
 
 
diff --git a/src/routes/RequestKeyPoint.cpp b/src/routes/RequestKeyPoint.cpp
index 7c8b32f..ce14757 100644
--- a/src/routes/RequestKeyPoint.cpp
+++ b/src/routes/RequestKeyPoint.cpp
@@ -21,3 +21,12 @@ void RequestKeyPoint::setLineStop(LineStop *lineStop) {
     _lineStop = lineStop;
     _saev = nullptr;
 }
+
+/**
+ * Verifies KeyPoint::check() + RequestKeyPoint specific constraints :
+ * @see KeyPoint::check()
+ * @return True if parent class checks are true and if one of _linestop xor _saev is a nullptr
+ */
+bool RequestKeyPoint::check() const {
+    return KeyPoint::check() && ((_saev != nullptr && _lineStop == nullptr) || (_saev == nullptr && _lineStop != nullptr));
+}
diff --git a/src/routes/RequestKeyPoint.h b/src/routes/RequestKeyPoint.h
index 32358b8..bf85c05 100644
--- a/src/routes/RequestKeyPoint.h
+++ b/src/routes/RequestKeyPoint.h
@@ -10,7 +10,7 @@
 #include "../instance/SAEVehicle.h"
 #include "../instance/graph/LineStop.h"
 
-class RequestKeyPoint : KeyPoint {
+class RequestKeyPoint : public virtual KeyPoint {
 private:
     SAEVehicle* _saev;
     LineStop* _lineStop;
@@ -18,12 +18,15 @@ private:
 public:
     RequestKeyPoint() = default;
     explicit RequestKeyPoint(SAEVehicle* vehicle) { _saev = vehicle; }
+    explicit RequestKeyPoint(LineStop* lineStop) { _lineStop = lineStop; }
 
     [[nodiscard]] SAEVehicle *getSAEV() const;
     void setSAEV(SAEVehicle *saev);
 
     [[nodiscard]] LineStop *getLineStop() const;
     void setLineStop(LineStop *lineStop);
+
+    [[nodiscard]] bool check() const override;
 };
 
 
diff --git a/src/routes/SAEVKeyPoint.cpp b/src/routes/SAEVKeyPoint.cpp
index 12454f0..19907b4 100644
--- a/src/routes/SAEVKeyPoint.cpp
+++ b/src/routes/SAEVKeyPoint.cpp
@@ -4,6 +4,12 @@
 
 #include "SAEVKeyPoint.h"
 
+
+SAEVKeyPoint::SAEVKeyPoint(Request *request, bool isEntry) {
+    _request = request;
+    _isEntry = isEntry;
+}
+
 Request *SAEVKeyPoint::getRequest() const {
     return _request;
 }
@@ -19,3 +25,7 @@ bool SAEVKeyPoint::isEntry() const {
 void SAEVKeyPoint::setIsEntry(bool isEntry) {
     SAEVKeyPoint::_isEntry = isEntry;
 }
+
+bool SAEVKeyPoint::check() const {
+    return KeyPoint::check() && _request != nullptr;
+}
diff --git a/src/routes/SAEVKeyPoint.h b/src/routes/SAEVKeyPoint.h
index 09f94fe..10cbc32 100644
--- a/src/routes/SAEVKeyPoint.h
+++ b/src/routes/SAEVKeyPoint.h
@@ -9,17 +9,21 @@
 #include "../instance/requests/Request.h"
 #include "KeyPoint.h"
 
-class SAEVKeyPoint : KeyPoint {
+class SAEVKeyPoint : public virtual KeyPoint {
 private:
     Request* _request;
     bool _isEntry;
 
 public:
+    SAEVKeyPoint(Request* request, bool  isEntry);
+
     [[nodiscard]] Request *getRequest() const;
     void setRequest(Request *request);
 
     [[nodiscard]] bool isEntry() const;
     void setIsEntry(bool isEntry);
+
+    [[nodiscard]] bool check() const override;
 };
 
 
-- 
GitLab


From 07fd36ed3a3a258dc84f73f26cd6d6bbbc59ad87 Mon Sep 17 00:00:00 2001
From: Romain BERNARD <romain.bernard@uca.fr>
Date: Mon, 25 Mar 2024 15:42:01 +0100
Subject: [PATCH 008/327] API to add key points to routes (SAEV)

---
 src/instance/SAEVehicle.cpp | 15 +++++++++++++++
 src/instance/SAEVehicle.h   | 12 +++++++++---
 src/routes/KeyPoint.h       |  4 +++-
 src/routes/SAEVKeyPoint.h   |  4 +++-
 src/routes/SAEVRoute.h      | 14 +++++++++++++-
 5 files changed, 43 insertions(+), 6 deletions(-)

diff --git a/src/instance/SAEVehicle.cpp b/src/instance/SAEVehicle.cpp
index bac525f..6f3ce02 100644
--- a/src/instance/SAEVehicle.cpp
+++ b/src/instance/SAEVehicle.cpp
@@ -3,3 +3,18 @@
 //
 
 #include "SAEVehicle.h"
+
+/**
+ * Moves an existing KeyPoint to the end of the SAEV _route.
+ * Prefer using the two parameter version of this function to create objects in place.
+ * @see emplace_back(Request*, bool)
+ * @param keyPoint An existing Key Point to add to the SAEVKeyPoint vector
+ */
+void SAEVehicle::push_back(const SAEVKeyPoint& keyPoint) { _route.push_back(keyPoint); }
+/**
+ * Creates a new KeyPoint to the SAEV _route
+ * @param request pointer to the request that will enter/leave the vehicle/_route on this key point
+ * @param isEntry bool value  that's true if the request enters the vehicle and false if it's leaving the vehicle
+ * @see SAEVRoute::emplace_back
+ */
+void SAEVehicle::emplace_back(Request* request, bool  isEntry) { _route.emplace_back(request, isEntry); }
diff --git a/src/instance/SAEVehicle.h b/src/instance/SAEVehicle.h
index 02962f7..73a2632 100644
--- a/src/instance/SAEVehicle.h
+++ b/src/instance/SAEVehicle.h
@@ -6,16 +6,22 @@
 #define GREEDYALGORITHM_SAEVEHICLE_H
 
 
+#include "../routes/SAEVRoute.h"
+
 class SAEVehicle {
 private:
-    const int capacity;
+    const int _capacity;
+    SAEVRoute _route;
 
 public:
-    explicit SAEVehicle(const int capacity) : capacity(capacity) {}
+    explicit SAEVehicle(const int capacity) : _capacity(capacity) {}
 
     [[nodiscard]] int getCapacity() const {
-        return capacity;
+        return _capacity;
     }
+
+    void push_back(const SAEVKeyPoint& keyPoint);
+    void emplace_back(Request* request, bool  isEntry);
 };
 
 
diff --git a/src/routes/KeyPoint.h b/src/routes/KeyPoint.h
index 7bef9fd..275f9af 100644
--- a/src/routes/KeyPoint.h
+++ b/src/routes/KeyPoint.h
@@ -37,7 +37,9 @@ public:
      */
      [[nodiscard]] bool isAfterKeyPoint(const KeyPoint& kp) const;
 
-    virtual [[nodiscard]] bool check() const;
+    [[nodiscard]] virtual bool check() const;
+
+    ~KeyPoint() = default;
 };
 
 
diff --git a/src/routes/SAEVKeyPoint.h b/src/routes/SAEVKeyPoint.h
index 10cbc32..84e8226 100644
--- a/src/routes/SAEVKeyPoint.h
+++ b/src/routes/SAEVKeyPoint.h
@@ -24,7 +24,9 @@ public:
     void setIsEntry(bool isEntry);
 
     [[nodiscard]] bool check() const override;
-};
+
+    ~SAEVKeyPoint() = default;
+}
 
 
 #endif //GREEDYALGORITHM_SAEVKEYPOINT_H
diff --git a/src/routes/SAEVRoute.h b/src/routes/SAEVRoute.h
index 9fcac2f..17514fa 100644
--- a/src/routes/SAEVRoute.h
+++ b/src/routes/SAEVRoute.h
@@ -13,7 +13,19 @@ class SAEVRoute {
 private:
     std::vector<SAEVKeyPoint> route;
 public:
-    void emplaceBack(SAEVKeyPoint keyPoint) { route.emplace_back(keyPoint); }
+    /**
+     * Moves an existing KeyPoint to the end of the SAEV _route.
+     * Prefer using the two parameter version of this function to create objects in place.
+     * @see emplace_back(Request*, bool)
+     * @param keyPoint An existing Key Point to add to the SAEVKeyPoint vector
+     */
+    void push_back(const SAEVKeyPoint& keyPoint) { route.push_back(std::move(keyPoint)); }
+    /**
+     * Creates a new KeyPoint to the SAEV _route
+     * @param request pointer to the request that will enter/leave the vehicle/_route on this key point
+     * @param isEntry bool value  that's true if the request enters the vehicle and false if it's leaving the vehicle
+     */
+    void emplace_back(Request* request, bool  isEntry) { route.emplace_back(request, isEntry); }
 };
 
 
-- 
GitLab


From f09f9def4cc40de78f21b1bb28aff62adea07a40 Mon Sep 17 00:00:00 2001
From: Romain BERNARD <romain.bernard@uca.fr>
Date: Mon, 25 Mar 2024 16:13:17 +0100
Subject: [PATCH 009/327] default values in key points to avoid confusion

---
 src/routes/KeyPoint.h | 9 ++++-----
 1 file changed, 4 insertions(+), 5 deletions(-)

diff --git a/src/routes/KeyPoint.h b/src/routes/KeyPoint.h
index 275f9af..a51e083 100644
--- a/src/routes/KeyPoint.h
+++ b/src/routes/KeyPoint.h
@@ -8,14 +8,13 @@
 
 class KeyPoint {
 protected:
-    int _nodeIndex{};
-    int _arrivalInstant{};
-    int _departureInstant{};
+    int _nodeIndex{-1};
+    int _arrivalInstant{-1};
+    int _departureInstant{-1};
 
 public:
-    KeyPoint(int nodeIndex, int arrivalInstant, int departureInstant);
-
     KeyPoint();
+    KeyPoint(int nodeIndex, int arrivalInstant, int departureInstant);
 
     [[nodiscard]] int getNodeIndex() const;
     void setNodeIndex(int nodeIndex);
-- 
GitLab


From 8b7a65ca1772e452963e256659fbe8819f63ddb9 Mon Sep 17 00:00:00 2001
From: Romain BERNARD <romain.bernard@uca.fr>
Date: Mon, 25 Mar 2024 17:13:47 +0100
Subject: [PATCH 010/327] RequestRoute base API

---
 src/routes/RequestRoute.cpp | 69 +++++++++++++++++++++++++++++++++++++
 src/routes/RequestRoute.h   | 10 +++++-
 2 files changed, 78 insertions(+), 1 deletion(-)

diff --git a/src/routes/RequestRoute.cpp b/src/routes/RequestRoute.cpp
index 8aeea6c..8b3257b 100644
--- a/src/routes/RequestRoute.cpp
+++ b/src/routes/RequestRoute.cpp
@@ -3,3 +3,72 @@
 //
 
 #include "RequestRoute.h"
+
+int RequestRoute::getNodeIndex(int routeIndex) const {
+    return _route[routeIndex].getNodeIndex();
+}
+
+void RequestRoute::setNodeIndex(int routeIndex, int nodeIndex) {
+    _route[routeIndex].setNodeIndex(nodeIndex);
+}
+
+int RequestRoute::getArrivalInstant(int routeIndex) const {
+    return _route[routeIndex].getArrivalInstant();
+}
+
+void RequestRoute::setArrivalInstant(int routeIndex, int arrivalInstant) {
+    _route[routeIndex].setArrivalInstant(arrivalInstant);
+}
+
+int RequestRoute::getDepartureInstant(int routeIndex) const {
+    return _route[routeIndex].getDepartureInstant();
+}
+
+void RequestRoute::setDepartureInstant(int routeIndex, int departureInstant) {
+    _route[routeIndex].setDepartureInstant(departureInstant);
+}
+
+SAEVehicle *RequestRoute::getSAEV(int routeIndex) const {
+    return _route[routeIndex].getSAEV();
+}
+
+void RequestRoute::setSAEV(int routeIndex, SAEVehicle *saev) {
+    if(routeIndex == 0 || routeIndex == 3)
+        _route[routeIndex].setSAEV(saev);
+
+}
+
+LineStop *RequestRoute::getLineStop(int routeIndex) const {
+    return _route[routeIndex].getLineStop();
+}
+
+void RequestRoute::setLineStop(int routeIndex, LineStop *lineStop) {
+    if(routeIndex == 1 || routeIndex == 2)
+        _route[routeIndex].setLineStop(lineStop);
+}
+
+void RequestRoute::resetKeyPoint(int routeIndex) {
+    RequestKeyPoint keyPoint = _route[routeIndex];
+    keyPoint.setNodeIndex(-1);
+    if(routeIndex > 1) { //If possible, set the time values to be the same as the preceding node to keep _route continuity
+        keyPoint.setArrivalInstant(_route[routeIndex - 1].getArrivalInstant());
+        keyPoint.setDepartureInstant(keyPoint.getArrivalInstant());
+    } else { //otherwise use default values
+        keyPoint.setArrivalInstant(-1);
+        keyPoint.setDepartureInstant(-1);
+    }
+    keyPoint.setSAEV(nullptr);
+    keyPoint.setLineStop(nullptr);
+}
+
+const RequestKeyPoint *RequestRoute::getRoute() const {
+    return _route;
+}
+
+Request *RequestRoute::getRequestPointer() const {
+    return _requestPointer;
+}
+
+void RequestRoute::setRequestPointer(Request *requestPointer) {
+    _requestPointer = requestPointer;
+}
diff --git a/src/routes/RequestRoute.h b/src/routes/RequestRoute.h
index a44f962..727df3e 100644
--- a/src/routes/RequestRoute.h
+++ b/src/routes/RequestRoute.h
@@ -10,9 +10,11 @@
 
 class RequestRoute {
 private:
-    RequestKeyPoint route[4];
+    RequestKeyPoint _route[4];
+    Request* _requestPointer{};
 public:
     RequestRoute() = default;
+    explicit RequestRoute(Request* request) {_requestPointer = request; };
 
     [[nodiscard]] int getNodeIndex(int routeIndex) const;
     void setNodeIndex(int routeIndex, int nodeIndex);
@@ -29,6 +31,12 @@ public:
     [[nodiscard]] LineStop *getLineStop(int routeIndex) const;
     void setLineStop(int routeIndex, LineStop *lineStop);
 
+    [[nodiscard]] const RequestKeyPoint *getRoute() const;
+
+    [[nodiscard]] Request *getRequestPointer() const;
+    void setRequestPointer(Request *requestPointer);
+
+    void resetKeyPoint(int routeIndex);
 };
 
 
-- 
GitLab


From 099ccd3a08e2e3bf805bdb84ee38ed57582142df Mon Sep 17 00:00:00 2001
From: Romain BERNARD <romain.bernard@uca.fr>
Date: Mon, 25 Mar 2024 17:14:01 +0100
Subject: [PATCH 011/327] Request base API

---
 src/instance/requests/Request.cpp | 112 ++++++++++++++++++++++++++++++
 src/instance/requests/Request.h   |  40 ++++++++++-
 2 files changed, 151 insertions(+), 1 deletion(-)

diff --git a/src/instance/requests/Request.cpp b/src/instance/requests/Request.cpp
index c70e76f..d9b131c 100644
--- a/src/instance/requests/Request.cpp
+++ b/src/instance/requests/Request.cpp
@@ -11,3 +11,115 @@ Request::Request(const int departureNodeIndex, const int arrivalNodeIndex, const
     _currentDeltaTime = deltaTime;
     _departureTW = _arrivalTW - deltaTime;
 }
+
+const int Request::getDepartureNodeIndex() const {
+    return _departureNodeIndex;
+}
+
+const int Request::getArrivalNodeIndex() const {
+    return _arrivalNodeIndex;
+}
+
+const TimeWindow &Request::getArrivalTw() const {
+    return _arrivalTW;
+}
+
+const int Request::getDeltaTime() const {
+    return _deltaTime;
+}
+
+const int Request::getWeight() const {
+    return _weight;
+}
+
+int Request::getCurrentDeltaTime() const {
+    return _currentDeltaTime;
+}
+
+int Request::getRequestServiceStart() const {
+    return _requestServiceStart;
+}
+
+int Request::getRequestServiceEnd() const {
+    return _requestServiceEnd;
+}
+
+const RequestRoute &Request::getCurrentRoute() const {
+    return _currentRoute;
+}
+
+const TimeWindow &Request::getDepartureTw() const {
+    return _departureTW;
+}
+
+//-----------------------------
+//---------- Setters ----------
+//-----------------------------
+
+void Request::setCurrentDeltaTime(int currentDeltaTime) {
+    _currentDeltaTime = currentDeltaTime;
+}
+
+void Request::setRequestServiceStart(int requestServiceStart) {
+    _requestServiceStart = requestServiceStart;
+}
+
+void Request::setRequestServiceEnd(int requestServiceEnd) {
+    _requestServiceEnd = requestServiceEnd;
+}
+
+void Request::setCurrentRoute(const RequestRoute &currentRoute) {
+    _currentRoute = currentRoute;
+}
+
+void Request::setDepartureTw(const TimeWindow &departureTw) {
+    _departureTW = departureTw;
+}
+
+//-----------------------------
+//--------- Route API ---------
+//-----------------------------
+
+int Request::getNodeIndex(int routeIndex) const {
+    return _currentRoute.getNodeIndex(routeIndex);
+}
+
+void Request::setNodeIndex(int routeIndex, int nodeIndex) {
+    _currentRoute.setNodeIndex(routeIndex, nodeIndex);
+}
+
+int Request::getArrivalInstant(int routeIndex) const {
+    return _currentRoute.getArrivalInstant(routeIndex);
+}
+
+void Request::setArrivalInstant(int routeIndex, int arrivalInstant) {
+    _currentRoute.setArrivalInstant(routeIndex, arrivalInstant);
+}
+
+int Request::getDepartureInstant(int routeIndex) const {
+    return _currentRoute.getDepartureInstant(routeIndex);
+}
+
+void Request::setDepartureInstant(int routeIndex, int departureInstant) {
+    _currentRoute.setDepartureInstant(routeIndex, departureInstant);
+}
+
+SAEVehicle *Request::getSAEV(int routeIndex) const {
+    return _currentRoute.getSAEV(routeIndex);
+}
+
+void Request::setSAEV(int routeIndex, SAEVehicle *saev) {
+    _currentRoute.setSAEV(routeIndex, saev);
+}
+
+LineStop *Request::getLineStop(int routeIndex) const {
+    return _currentRoute.getLineStop(routeIndex);
+}
+
+void Request::setLineStop(int routeIndex, LineStop *lineStop) {
+    _currentRoute.setLineStop(routeIndex, lineStop);
+}
+
+void Request::resetKeyPoint(int routeIndex) {
+    _currentRoute.resetKeyPoint(routeIndex);
+}
diff --git a/src/instance/requests/Request.h b/src/instance/requests/Request.h
index 420f8cd..f0af0cc 100644
--- a/src/instance/requests/Request.h
+++ b/src/instance/requests/Request.h
@@ -22,11 +22,49 @@ private:
     int _currentDeltaTime; //deltaTime - currentRouteDuration
     int _requestServiceStart;
     int _requestServiceEnd;
-    RequestRoute _currentRoute;
+    RequestRoute _currentRoute{this};
     TimeWindow _departureTW; //For now, a virtual TW on departures, used for constraint propagation
 public:
     Request(const int departureNodeIndex, const int arrivalNodeIndex,
             const TimeWindow &arrivalTw, const int deltaTime, const int weight);
+
+    //Getters
+    [[nodiscard]] const int getDepartureNodeIndex() const;
+    [[nodiscard]] const int getArrivalNodeIndex() const;
+    [[nodiscard]] const TimeWindow &getArrivalTw() const;
+    [[nodiscard]] const int getDeltaTime() const;
+    [[nodiscard]] const int getWeight() const;
+    [[nodiscard]] int getCurrentDeltaTime() const;
+    [[nodiscard]] int getRequestServiceStart() const;
+    [[nodiscard]] int getRequestServiceEnd() const;
+    [[nodiscard]] const RequestRoute &getCurrentRoute() const;
+    [[nodiscard]] const TimeWindow &getDepartureTw() const;
+
+    //Setters
+    void setCurrentDeltaTime(int currentDeltaTime);
+    void setRequestServiceStart(int requestServiceStart);
+    void setRequestServiceEnd(int requestServiceEnd);
+    void setCurrentRoute(const RequestRoute &currentRoute);
+    void setDepartureTw(const TimeWindow &departureTw);
+
+    //Route API delegation
+    [[nodiscard]] int getNodeIndex(int routeIndex) const;
+    void setNodeIndex(int routeIndex, int nodeIndex);
+
+    [[nodiscard]] int getArrivalInstant(int routeIndex) const;
+    void setArrivalInstant(int routeIndex, int arrivalInstant);
+
+    [[nodiscard]] int getDepartureInstant(int routeIndex) const;
+    void setDepartureInstant(int routeIndex, int departureInstant);
+
+    [[nodiscard]] SAEVehicle *getSAEV(int routeIndex) const;
+    void setSAEV(int routeIndex, SAEVehicle *saev);
+
+    [[nodiscard]] LineStop *getLineStop(int routeIndex) const;
+    void setLineStop(int routeIndex, LineStop *lineStop);
+
+    void resetKeyPoint(int routeIndex);
+
 };
 
 
-- 
GitLab


From 7e6cc16a7c4c1a28fc56fe9fb852b7fd70729700 Mon Sep 17 00:00:00 2001
From: Romain BERNARD <romain.bernard@uca.fr>
Date: Mon, 25 Mar 2024 17:14:24 +0100
Subject: [PATCH 012/327] Add time windows to key points for constraint
 propagation and checks

---
 src/routes/KeyPoint.cpp | 17 +++++++++++++++++
 src/routes/KeyPoint.h   | 15 +++++++++++++++
 2 files changed, 32 insertions(+)

diff --git a/src/routes/KeyPoint.cpp b/src/routes/KeyPoint.cpp
index 8c41501..2752d07 100644
--- a/src/routes/KeyPoint.cpp
+++ b/src/routes/KeyPoint.cpp
@@ -41,6 +41,23 @@ bool KeyPoint::isAfterKeyPoint(const KeyPoint &kp) const {
     return _arrivalInstant >= kp.getDepartureInstant();
 }
 
+const TimeWindow &KeyPoint::getArrivalTimeWindow() const {
+    return _arrivalTimeWindow;
+}
+
+void KeyPoint::setArrivalTimeWindow(const TimeWindow &arrivalTimeWindow) {
+    _arrivalTimeWindow = arrivalTimeWindow;
+}
+
+const TimeWindow &KeyPoint::getDepartureTimeWindow() const {
+    return _departureTimeWindow;
+}
+
+void KeyPoint::setDepartureTimeWindow(const TimeWindow &departureTimeWindow) {
+    _departureTimeWindow = departureTimeWindow;
+}
+
+
 bool KeyPoint::check() const {
     return _arrivalInstant <= _departureInstant;
 }
diff --git a/src/routes/KeyPoint.h b/src/routes/KeyPoint.h
index a51e083..b22d6a9 100644
--- a/src/routes/KeyPoint.h
+++ b/src/routes/KeyPoint.h
@@ -6,12 +6,18 @@
 #define GREEDYALGORITHM_KEYPOINT_H
 
 
+#include "../TimeWindow.h"
+
 class KeyPoint {
 protected:
     int _nodeIndex{-1};
     int _arrivalInstant{-1};
     int _departureInstant{-1};
 
+    //Constraint propagation variables
+    TimeWindow _arrivalTimeWindow{};
+    TimeWindow _departureTimeWindow{};
+
 public:
     KeyPoint();
     KeyPoint(int nodeIndex, int arrivalInstant, int departureInstant);
@@ -25,6 +31,15 @@ public:
     [[nodiscard]] int getDepartureInstant() const;
     void setDepartureInstant(int departureInstant);
 
+    [[nodiscard]] const TimeWindow &getArrivalTimeWindow() const;
+
+    void setArrivalTimeWindow(const TimeWindow &arrivalTimeWindow);
+
+    [[nodiscard]] const TimeWindow &getDepartureTimeWindow() const;
+
+    void setDepartureTimeWindow(const TimeWindow &departureTimeWindow);
+
+
     /**
      * Returns true if this is temporally before (or at the same time) as the given key point
      * @return true if we arrive on the given key point after (or at the same time as) when we depart from this key point
-- 
GitLab


From 76dc3a3d318ef176c11d4f64a12e960326dc6ef0 Mon Sep 17 00:00:00 2001
From: Romain BERNARD <romain.bernard@uca.fr>
Date: Mon, 25 Mar 2024 17:14:38 +0100
Subject: [PATCH 013/327] init values

---
 src/routes/RequestKeyPoint.h | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/src/routes/RequestKeyPoint.h b/src/routes/RequestKeyPoint.h
index bf85c05..aabb656 100644
--- a/src/routes/RequestKeyPoint.h
+++ b/src/routes/RequestKeyPoint.h
@@ -12,8 +12,8 @@
 
 class RequestKeyPoint : public virtual KeyPoint {
 private:
-    SAEVehicle* _saev;
-    LineStop* _lineStop;
+    SAEVehicle* _saev{};
+    LineStop* _lineStop{};
 
 public:
     RequestKeyPoint() = default;
-- 
GitLab


From 535c0aafc37d3789831a0e31b40c59f2f8823ab0 Mon Sep 17 00:00:00 2001
From: Romain BERNARD <romain.bernard@uca.fr>
Date: Mon, 25 Mar 2024 17:15:34 +0100
Subject: [PATCH 014/327] refer to the vehicle in the route and reciprocally
 for easy access to constraints

---
 src/instance/SAEVehicle.cpp |  3 ++-
 src/instance/SAEVehicle.h   |  4 ++--
 src/routes/SAEVKeyPoint.h   |  2 +-
 src/routes/SAEVRoute.h      | 22 +++++++++++++++++++---
 4 files changed, 24 insertions(+), 7 deletions(-)

diff --git a/src/instance/SAEVehicle.cpp b/src/instance/SAEVehicle.cpp
index 6f3ce02..09751b5 100644
--- a/src/instance/SAEVehicle.cpp
+++ b/src/instance/SAEVehicle.cpp
@@ -7,10 +7,11 @@
 /**
  * Moves an existing KeyPoint to the end of the SAEV _route.
  * Prefer using the two parameter version of this function to create objects in place.
+ * WARNING : keyPoint will be moved, preceding references to this object will be invalidated
  * @see emplace_back(Request*, bool)
  * @param keyPoint An existing Key Point to add to the SAEVKeyPoint vector
  */
-void SAEVehicle::push_back(const SAEVKeyPoint& keyPoint) { _route.push_back(keyPoint); }
+void SAEVehicle::push_back(SAEVKeyPoint& keyPoint) { _route.push_back(keyPoint); }
 /**
  * Creates a new KeyPoint to the SAEV _route
  * @param request pointer to the request that will enter/leave the vehicle/_route on this key point
diff --git a/src/instance/SAEVehicle.h b/src/instance/SAEVehicle.h
index 73a2632..2e078ea 100644
--- a/src/instance/SAEVehicle.h
+++ b/src/instance/SAEVehicle.h
@@ -11,7 +11,7 @@
 class SAEVehicle {
 private:
     const int _capacity;
-    SAEVRoute _route;
+    SAEVRoute _route{this}; //Associate the route with the vehicle via pointer
 
 public:
     explicit SAEVehicle(const int capacity) : _capacity(capacity) {}
@@ -20,7 +20,7 @@ public:
         return _capacity;
     }
 
-    void push_back(const SAEVKeyPoint& keyPoint);
+    void push_back(SAEVKeyPoint& keyPoint);
     void emplace_back(Request* request, bool  isEntry);
 };
 
diff --git a/src/routes/SAEVKeyPoint.h b/src/routes/SAEVKeyPoint.h
index 84e8226..652208e 100644
--- a/src/routes/SAEVKeyPoint.h
+++ b/src/routes/SAEVKeyPoint.h
@@ -26,7 +26,7 @@ public:
     [[nodiscard]] bool check() const override;
 
     ~SAEVKeyPoint() = default;
-}
+};
 
 
 #endif //GREEDYALGORITHM_SAEVKEYPOINT_H
diff --git a/src/routes/SAEVRoute.h b/src/routes/SAEVRoute.h
index 17514fa..46eb95c 100644
--- a/src/routes/SAEVRoute.h
+++ b/src/routes/SAEVRoute.h
@@ -11,21 +11,37 @@
 
 class SAEVRoute {
 private:
-    std::vector<SAEVKeyPoint> route;
+    std::vector<SAEVKeyPoint> _route;
+    SAEVehicle* _vehiclePointer{};
 public:
+    SAEVRoute() = default;
+    explicit SAEVRoute(SAEVehicle* pointer) { _vehiclePointer = pointer; }
+
     /**
      * Moves an existing KeyPoint to the end of the SAEV _route.
      * Prefer using the two parameter version of this function to create objects in place.
      * @see emplace_back(Request*, bool)
      * @param keyPoint An existing Key Point to add to the SAEVKeyPoint vector
      */
-    void push_back(const SAEVKeyPoint& keyPoint) { route.push_back(std::move(keyPoint)); }
+    void push_back(SAEVKeyPoint& keyPoint) { _route.push_back(std::move(keyPoint)); }
     /**
      * Creates a new KeyPoint to the SAEV _route
      * @param request pointer to the request that will enter/leave the vehicle/_route on this key point
      * @param isEntry bool value  that's true if the request enters the vehicle and false if it's leaving the vehicle
      */
-    void emplace_back(Request* request, bool  isEntry) { route.emplace_back(request, isEntry); }
+    void emplace_back(Request* request, bool  isEntry) { _route.emplace_back(request, isEntry); }
+
+    [[nodiscard]] const std::vector<SAEVKeyPoint> &getRoute() const {
+        return _route;
+    }
+
+    [[nodiscard]] SAEVehicle *getVehiclePointer() const {
+        return _vehiclePointer;
+    }
+
+    void setVehiclePointer(SAEVehicle *vehiclePointer) {
+        SAEVRoute::_vehiclePointer = vehiclePointer;
+    }
 };
 
 
-- 
GitLab


From 72d3e53ca0cd499475e234e701971a542f99069a Mon Sep 17 00:00:00 2001
From: Romain BERNARD <romain.bernard@uca.fr>
Date: Mon, 25 Mar 2024 17:27:01 +0100
Subject: [PATCH 015/327] make vehicle capacity a static constant field for
 memories' sake (still accessible from a vehicle instance for code
 compatibility if vehicle capacity ever becomes variable in between vehicles)

---
 src/instance/SAEVehicle.h | 9 ++++++---
 1 file changed, 6 insertions(+), 3 deletions(-)

diff --git a/src/instance/SAEVehicle.h b/src/instance/SAEVehicle.h
index 2e078ea..4ff49f0 100644
--- a/src/instance/SAEVehicle.h
+++ b/src/instance/SAEVehicle.h
@@ -5,18 +5,21 @@
 #ifndef GREEDYALGORITHM_SAEVEHICLE_H
 #define GREEDYALGORITHM_SAEVEHICLE_H
 
+#define VEHICLE_CAPACITY 6
+
 
 #include "../routes/SAEVRoute.h"
 
 class SAEVehicle {
 private:
-    const int _capacity;
+    static const int _capacity{VEHICLE_CAPACITY};
     SAEVRoute _route{this}; //Associate the route with the vehicle via pointer
 
 public:
-    explicit SAEVehicle(const int capacity) : _capacity(capacity) {}
+    SAEVehicle() = default;
+//    explicit SAEVehicle(const int capacity) : _capacity(capacity) {}
 
-    [[nodiscard]] int getCapacity() const {
+    [[nodiscard]] static int getCapacity() {
         return _capacity;
     }
 
-- 
GitLab


From bc69cbc2882c2a706507e5993869f0f1bd383b6a Mon Sep 17 00:00:00 2001
From: Romain BERNARD <romain.bernard@uca.fr>
Date: Mon, 25 Mar 2024 17:38:41 +0100
Subject: [PATCH 016/327] declare an enum allowing to refer to request route
 indexes by more comprehensive names

---
 src/routes/RequestRoute.cpp | 4 ++--
 src/routes/RequestRoute.h   | 7 +++++++
 2 files changed, 9 insertions(+), 2 deletions(-)

diff --git a/src/routes/RequestRoute.cpp b/src/routes/RequestRoute.cpp
index 8b3257b..ddf7356 100644
--- a/src/routes/RequestRoute.cpp
+++ b/src/routes/RequestRoute.cpp
@@ -33,7 +33,7 @@ SAEVehicle *RequestRoute::getSAEV(int routeIndex) const {
 }
 
 void RequestRoute::setSAEV(int routeIndex, SAEVehicle *saev) {
-    if(routeIndex == 0 || routeIndex == 3)
+    if(routeIndex == SAEV1 || routeIndex == SAEV2)
         _route[routeIndex].setSAEV(saev);
 
 }
@@ -43,7 +43,7 @@ LineStop *RequestRoute::getLineStop(int routeIndex) const {
 }
 
 void RequestRoute::setLineStop(int routeIndex, LineStop *lineStop) {
-    if(routeIndex == 1 || routeIndex == 2)
+    if(routeIndex == TRANSIT1 || routeIndex == TRANSIT2)
         _route[routeIndex].setLineStop(lineStop);
 }
 
diff --git a/src/routes/RequestRoute.h b/src/routes/RequestRoute.h
index 727df3e..9874b88 100644
--- a/src/routes/RequestRoute.h
+++ b/src/routes/RequestRoute.h
@@ -9,6 +9,13 @@
 #include "RequestKeyPoint.h"
 
 class RequestRoute {
+public:
+    enum RouteStructureEnum {
+        SAEV1 = 0,
+        TRANSIT1 = 1,
+        TRANSIT2 = 2,
+        SAEV2 = 3
+    };
 private:
     RequestKeyPoint _route[4];
     Request* _requestPointer{};
-- 
GitLab


From c13b5723b1053be64fbdc1d4129f0b20678f3624 Mon Sep 17 00:00:00 2001
From: Romain BERNARD <romain.bernard@uca.fr>
Date: Tue, 23 Apr 2024 14:47:36 +0200
Subject: [PATCH 017/327] WIP route refactor in accordance with last meetings

---
 src/routes/KeyPoint.cpp        | 52 ++--------------------------------
 src/routes/KeyPoint.h          | 36 ++---------------------
 src/routes/RequestKeyPoint.cpp | 17 +++++++++++
 src/routes/RequestKeyPoint.h   | 11 +++++++
 src/routes/SAEVKeyPoint.cpp    | 44 ++++++++++++++++++++++++----
 src/routes/SAEVKeyPoint.h      | 28 ++++++++++++++----
 src/routes/SAEVRoute.h         | 25 ++--------------
 7 files changed, 96 insertions(+), 117 deletions(-)

diff --git a/src/routes/KeyPoint.cpp b/src/routes/KeyPoint.cpp
index 2752d07..1239d71 100644
--- a/src/routes/KeyPoint.cpp
+++ b/src/routes/KeyPoint.cpp
@@ -5,9 +5,7 @@
 #include "KeyPoint.h"
 
 KeyPoint::KeyPoint() = default;
-KeyPoint::KeyPoint(int nodeIndex, int arrivalInstant, int departureInstant) : _nodeIndex(nodeIndex),
-                                                                              _arrivalInstant(arrivalInstant),
-                                                                              _departureInstant(departureInstant) {}
+KeyPoint::KeyPoint(int nodeIndex) : _nodeIndex(nodeIndex) {}
 
 int KeyPoint::getNodeIndex() const {
     return _nodeIndex;
@@ -15,50 +13,4 @@ int KeyPoint::getNodeIndex() const {
 
 void KeyPoint::setNodeIndex(int nodeIndex) {
     KeyPoint::_nodeIndex = nodeIndex;
-}
-
-int KeyPoint::getArrivalInstant() const {
-    return _arrivalInstant;
-}
-
-void KeyPoint::setArrivalInstant(int arrivalInstant) {
-    KeyPoint::_arrivalInstant = arrivalInstant;
-}
-
-int KeyPoint::getDepartureInstant() const {
-    return _departureInstant;
-}
-
-void KeyPoint::setDepartureInstant(int departureInstant) {
-    KeyPoint::_departureInstant = departureInstant;
-}
-
-bool KeyPoint::isBeforeKeyPoint(const KeyPoint &kp) const {
-    return _departureInstant <= kp.getArrivalInstant();
-}
-
-bool KeyPoint::isAfterKeyPoint(const KeyPoint &kp) const {
-    return _arrivalInstant >= kp.getDepartureInstant();
-}
-
-const TimeWindow &KeyPoint::getArrivalTimeWindow() const {
-    return _arrivalTimeWindow;
-}
-
-void KeyPoint::setArrivalTimeWindow(const TimeWindow &arrivalTimeWindow) {
-    _arrivalTimeWindow = arrivalTimeWindow;
-}
-
-const TimeWindow &KeyPoint::getDepartureTimeWindow() const {
-    return _departureTimeWindow;
-}
-
-void KeyPoint::setDepartureTimeWindow(const TimeWindow &departureTimeWindow) {
-    _departureTimeWindow = departureTimeWindow;
-}
-
-
-bool KeyPoint::check() const {
-    return _arrivalInstant <= _departureInstant;
-}
-
+}
\ No newline at end of file
diff --git a/src/routes/KeyPoint.h b/src/routes/KeyPoint.h
index b22d6a9..5d0be47 100644
--- a/src/routes/KeyPoint.h
+++ b/src/routes/KeyPoint.h
@@ -11,47 +11,15 @@
 class KeyPoint {
 protected:
     int _nodeIndex{-1};
-    int _arrivalInstant{-1};
-    int _departureInstant{-1};
-
-    //Constraint propagation variables
-    TimeWindow _arrivalTimeWindow{};
-    TimeWindow _departureTimeWindow{};
 
 public:
     KeyPoint();
-    KeyPoint(int nodeIndex, int arrivalInstant, int departureInstant);
+    explicit KeyPoint(int nodeIndex);
 
     [[nodiscard]] int getNodeIndex() const;
     void setNodeIndex(int nodeIndex);
 
-    [[nodiscard]] int getArrivalInstant() const;
-    void setArrivalInstant(int arrivalInstant);
-
-    [[nodiscard]] int getDepartureInstant() const;
-    void setDepartureInstant(int departureInstant);
-
-    [[nodiscard]] const TimeWindow &getArrivalTimeWindow() const;
-
-    void setArrivalTimeWindow(const TimeWindow &arrivalTimeWindow);
-
-    [[nodiscard]] const TimeWindow &getDepartureTimeWindow() const;
-
-    void setDepartureTimeWindow(const TimeWindow &departureTimeWindow);
-
-
-    /**
-     * Returns true if this is temporally before (or at the same time) as the given key point
-     * @return true if we arrive on the given key point after (or at the same time as) when we depart from this key point
-     */
-    [[nodiscard]] bool isBeforeKeyPoint(const KeyPoint& kp) const;
-    /**
-     * Returns true if this is temporally after (or at the same time) as the given key point
-     * @return true if we arrive on the given key point after (or at the same time as) when we depart from this key point
-     */
-     [[nodiscard]] bool isAfterKeyPoint(const KeyPoint& kp) const;
-
-    [[nodiscard]] virtual bool check() const;
+    [[nodiscard]] virtual bool check() const = 0;
 
     ~KeyPoint() = default;
 };
diff --git a/src/routes/RequestKeyPoint.cpp b/src/routes/RequestKeyPoint.cpp
index ce14757..70d7a01 100644
--- a/src/routes/RequestKeyPoint.cpp
+++ b/src/routes/RequestKeyPoint.cpp
@@ -22,6 +22,23 @@ void RequestKeyPoint::setLineStop(LineStop *lineStop) {
     _saev = nullptr;
 }
 
+const TimeWindow &RequestKeyPoint::getArrivalTimeWindow() const {
+    return _arrivalTimeWindow;
+}
+
+void RequestKeyPoint::setArrivalTimeWindow(const TimeWindow &arrivalTimeWindow) {
+    _arrivalTimeWindow = arrivalTimeWindow;
+}
+
+const TimeWindow &RequestKeyPoint::getDepartureTimeWindow() const {
+    return _departureTimeWindow;
+}
+
+void RequestKeyPoint::setDepartureTimeWindow(const TimeWindow &departureTimeWindow) {
+    _departureTimeWindow = departureTimeWindow;
+}
+
+
 /**
  * Verifies KeyPoint::check() + RequestKeyPoint specific constraints :
  * @see KeyPoint::check()
diff --git a/src/routes/RequestKeyPoint.h b/src/routes/RequestKeyPoint.h
index aabb656..ac65c91 100644
--- a/src/routes/RequestKeyPoint.h
+++ b/src/routes/RequestKeyPoint.h
@@ -15,6 +15,10 @@ private:
     SAEVehicle* _saev{};
     LineStop* _lineStop{};
 
+    //Constraint propagation variables
+    TimeWindow _arrivalTimeWindow{};
+    TimeWindow _departureTimeWindow{};
+
 public:
     RequestKeyPoint() = default;
     explicit RequestKeyPoint(SAEVehicle* vehicle) { _saev = vehicle; }
@@ -26,6 +30,13 @@ public:
     [[nodiscard]] LineStop *getLineStop() const;
     void setLineStop(LineStop *lineStop);
 
+    [[nodiscard]] const TimeWindow &getArrivalTimeWindow() const;
+    void setArrivalTimeWindow(const TimeWindow &arrivalTimeWindow);
+
+    [[nodiscard]] const TimeWindow &getDepartureTimeWindow() const;
+    void setDepartureTimeWindow(const TimeWindow &departureTimeWindow);
+
+
     [[nodiscard]] bool check() const override;
 };
 
diff --git a/src/routes/SAEVKeyPoint.cpp b/src/routes/SAEVKeyPoint.cpp
index 19907b4..c29d7fe 100644
--- a/src/routes/SAEVKeyPoint.cpp
+++ b/src/routes/SAEVKeyPoint.cpp
@@ -18,14 +18,46 @@ void SAEVKeyPoint::setRequest(Request *request) {
     SAEVKeyPoint::_request = request;
 }
 
-bool SAEVKeyPoint::isEntry() const {
-    return _isEntry;
+bool SAEVKeyPoint::check() const {
+    return KeyPoint::check() && _request != nullptr;
 }
 
-void SAEVKeyPoint::setIsEntry(bool isEntry) {
-    SAEVKeyPoint::_isEntry = isEntry;
+SAEVKeyPoint *SAEVKeyPoint::getPredecessor() const {
+    return _predecessor;
 }
 
-bool SAEVKeyPoint::check() const {
-    return KeyPoint::check() && _request != nullptr;
+void SAEVKeyPoint::setPredecessor(SAEVKeyPoint *predecessor) {
+    _predecessor = predecessor;
+}
+
+SAEVKeyPoint *SAEVKeyPoint::getSuccessor() const {
+    return _successor;
+}
+
+void SAEVKeyPoint::setSuccessor(SAEVKeyPoint *successor) {
+    _successor = successor;
+}
+
+int SAEVKeyPoint::getCurrentCapacity() const {
+    return _currentCapacity;
+}
+
+void SAEVKeyPoint::setCurrentCapacity(int currentCapacity) {
+    _currentCapacity = currentCapacity;
+}
+
+int SAEVKeyPoint::getMinTw() const {
+    return _minTW;
+}
+
+void SAEVKeyPoint::setMinTw(int minTw) {
+    _minTW = minTw;
+}
+
+int SAEVKeyPoint::getMaxTw() const {
+    return _maxTW;
+}
+
+void SAEVKeyPoint::setMaxTw(int maxTw) {
+    _maxTW = maxTw;
 }
diff --git a/src/routes/SAEVKeyPoint.h b/src/routes/SAEVKeyPoint.h
index 652208e..d669a2e 100644
--- a/src/routes/SAEVKeyPoint.h
+++ b/src/routes/SAEVKeyPoint.h
@@ -11,8 +11,29 @@
 
 class SAEVKeyPoint : public virtual KeyPoint {
 private:
-    Request* _request;
-    bool _isEntry;
+    Request* _request{};
+    SAEVKeyPoint* _predecessor{};
+    SAEVKeyPoint* _successor{};
+    int _currentCapacity{0};
+    int _minTW{0};
+    int _maxTW{0};
+    SAEVehicle* _vehiclePointer{};
+
+public:
+    [[nodiscard]] SAEVKeyPoint *getPredecessor() const;
+    void setPredecessor(SAEVKeyPoint *predecessor);
+
+    [[nodiscard]] SAEVKeyPoint *getSuccessor() const;
+    void setSuccessor(SAEVKeyPoint *successor);
+
+    [[nodiscard]] int getCurrentCapacity() const;
+    void setCurrentCapacity(int currentCapacity);
+
+    [[nodiscard]] int getMinTw() const;
+    void setMinTw(int minTw);
+
+    [[nodiscard]] int getMaxTw() const;
+    void setMaxTw(int maxTw);
 
 public:
     SAEVKeyPoint(Request* request, bool  isEntry);
@@ -20,9 +41,6 @@ public:
     [[nodiscard]] Request *getRequest() const;
     void setRequest(Request *request);
 
-    [[nodiscard]] bool isEntry() const;
-    void setIsEntry(bool isEntry);
-
     [[nodiscard]] bool check() const override;
 
     ~SAEVKeyPoint() = default;
diff --git a/src/routes/SAEVRoute.h b/src/routes/SAEVRoute.h
index 46eb95c..6c63ae6 100644
--- a/src/routes/SAEVRoute.h
+++ b/src/routes/SAEVRoute.h
@@ -12,36 +12,17 @@
 class SAEVRoute {
 private:
     std::vector<SAEVKeyPoint> _route;
-    SAEVehicle* _vehiclePointer{};
+    size_t _nbRequest;
 public:
     SAEVRoute() = default;
-    explicit SAEVRoute(SAEVehicle* pointer) { _vehiclePointer = pointer; }
-
-    /**
-     * Moves an existing KeyPoint to the end of the SAEV _route.
-     * Prefer using the two parameter version of this function to create objects in place.
-     * @see emplace_back(Request*, bool)
-     * @param keyPoint An existing Key Point to add to the SAEVKeyPoint vector
-     */
-    void push_back(SAEVKeyPoint& keyPoint) { _route.push_back(std::move(keyPoint)); }
-    /**
-     * Creates a new KeyPoint to the SAEV _route
-     * @param request pointer to the request that will enter/leave the vehicle/_route on this key point
-     * @param isEntry bool value  that's true if the request enters the vehicle and false if it's leaving the vehicle
-     */
-    void emplace_back(Request* request, bool  isEntry) { _route.emplace_back(request, isEntry); }
+    explicit SAEVRoute(const std::vector<Request>& requestList);
+    void initSAEVRoute(const std::vector<Request>& requestList);
 
     [[nodiscard]] const std::vector<SAEVKeyPoint> &getRoute() const {
         return _route;
     }
 
-    [[nodiscard]] SAEVehicle *getVehiclePointer() const {
-        return _vehiclePointer;
-    }
 
-    void setVehiclePointer(SAEVehicle *vehiclePointer) {
-        SAEVRoute::_vehiclePointer = vehiclePointer;
-    }
 };
 
 
-- 
GitLab


From b5f4c2953def8c3a2e86c6ed2343ecbb355b933c Mon Sep 17 00:00:00 2001
From: Romain BERNARD <romain.bernard@uca.fr>
Date: Tue, 23 Apr 2024 18:42:49 +0200
Subject: [PATCH 018/327] WIP add shortest xy vehicle paths to graph

---
 src/instance/graph/Graph.cpp | 3 +++
 src/instance/graph/Graph.h   | 3 +++
 2 files changed, 6 insertions(+)

diff --git a/src/instance/graph/Graph.cpp b/src/instance/graph/Graph.cpp
index 9556251..6bf5a5d 100644
--- a/src/instance/graph/Graph.cpp
+++ b/src/instance/graph/Graph.cpp
@@ -37,6 +37,9 @@ Graph::Graph(const std::string& nodesFilePath, const std::string& edgesFilePath,
         parseNodeRow(row);
     }
 
+    shortestSAEVPaths.reserve(nodesVector.size());
+    for(std::vector<int> yValues : shortestSAEVPaths) { yValues.reserve(nodesVector.size()); }
+
     //Edges instantiation
     std::ifstream edgesFile(edgesFilePath);
     std::cout << "Edges instantiation" << std::endl;
diff --git a/src/instance/graph/Graph.h b/src/instance/graph/Graph.h
index 9ad45fe..aaf310c 100644
--- a/src/instance/graph/Graph.h
+++ b/src/instance/graph/Graph.h
@@ -20,6 +20,7 @@ private:
     std::vector<Node> nodesVector; //The full list of nodes created in the graph
     std::vector<Edge> edgesVector;
     std::vector<Line> transitLines;
+    std::vector<std::vector<int>> shortestSAEVPaths;
 
     /**
      * For every LineStop on every node of the graph, verify the node returned by looking into LineStop->Line(stopIdx)
@@ -144,6 +145,8 @@ public:
      * @param length The length of this edge (in minutes)
      */
     void createAndAddEdge(int edgeStartNodeIndex, int edgeEndNodeIndex, double length);
+
+    int getShortestSAEVPath(int x, int y) const { return shortestSAEVPaths.at(x).at(y); }
 };
 
 
-- 
GitLab


From e6690e24a03c4a99c4c1a416dba7c3d934e4e2fe Mon Sep 17 00:00:00 2001
From: Romain BERNARD <romain.bernard@uca.fr>
Date: Tue, 23 Apr 2024 18:43:59 +0200
Subject: [PATCH 019/327] remove route mentions from SAEVehicle

---
 src/instance/SAEVehicle.cpp | 16 ----------------
 src/instance/SAEVehicle.h   |  5 -----
 2 files changed, 21 deletions(-)

diff --git a/src/instance/SAEVehicle.cpp b/src/instance/SAEVehicle.cpp
index 09751b5..bac525f 100644
--- a/src/instance/SAEVehicle.cpp
+++ b/src/instance/SAEVehicle.cpp
@@ -3,19 +3,3 @@
 //
 
 #include "SAEVehicle.h"
-
-/**
- * Moves an existing KeyPoint to the end of the SAEV _route.
- * Prefer using the two parameter version of this function to create objects in place.
- * WARNING : keyPoint will be moved, preceding references to this object will be invalidated
- * @see emplace_back(Request*, bool)
- * @param keyPoint An existing Key Point to add to the SAEVKeyPoint vector
- */
-void SAEVehicle::push_back(SAEVKeyPoint& keyPoint) { _route.push_back(keyPoint); }
-/**
- * Creates a new KeyPoint to the SAEV _route
- * @param request pointer to the request that will enter/leave the vehicle/_route on this key point
- * @param isEntry bool value  that's true if the request enters the vehicle and false if it's leaving the vehicle
- * @see SAEVRoute::emplace_back
- */
-void SAEVehicle::emplace_back(Request* request, bool  isEntry) { _route.emplace_back(request, isEntry); }
diff --git a/src/instance/SAEVehicle.h b/src/instance/SAEVehicle.h
index 4ff49f0..2efee9e 100644
--- a/src/instance/SAEVehicle.h
+++ b/src/instance/SAEVehicle.h
@@ -8,12 +8,10 @@
 #define VEHICLE_CAPACITY 6
 
 
-#include "../routes/SAEVRoute.h"
 
 class SAEVehicle {
 private:
     static const int _capacity{VEHICLE_CAPACITY};
-    SAEVRoute _route{this}; //Associate the route with the vehicle via pointer
 
 public:
     SAEVehicle() = default;
@@ -22,9 +20,6 @@ public:
     [[nodiscard]] static int getCapacity() {
         return _capacity;
     }
-
-    void push_back(SAEVKeyPoint& keyPoint);
-    void emplace_back(Request* request, bool  isEntry);
 };
 
 
-- 
GitLab


From 4409005e206657bd142f582fdb58a09ed13bb636 Mon Sep 17 00:00:00 2001
From: Romain BERNARD <romain.bernard@uca.fr>
Date: Tue, 23 Apr 2024 18:58:38 +0200
Subject: [PATCH 020/327] define departure time windows better when possible +
 TW access API

---
 CMakeLists.txt                    | 12 ++++++++----
 src/instance/requests/Request.cpp | 27 +++++++++++++++++++++++++++
 src/instance/requests/Request.h   |  7 +++++++
 test/lib/googletest               |  2 +-
 4 files changed, 43 insertions(+), 5 deletions(-)

diff --git a/CMakeLists.txt b/CMakeLists.txt
index c1ceacf..30775c8 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -43,18 +43,22 @@ add_executable(GreedyAlgorithm
         src/ShortestPath/Transit/TransitShortestPathContainer.h
         src/routes/RequestRoute.cpp
         src/routes/RequestRoute.h
-        src/routes/SAEVRoute.cpp
-        src/routes/SAEVRoute.h
+        src/routes/vehicle/SAEVRoute.cpp
+        src/routes/vehicle/SAEVRoute.h
         src/TimeWindow.cpp
         src/TimeWindow.h
         src/routes/KeyPoint.cpp
         src/routes/KeyPoint.h
         src/routes/RequestKeyPoint.cpp
         src/routes/RequestKeyPoint.h
-        src/routes/SAEVKeyPoint.cpp
-        src/routes/SAEVKeyPoint.h
+        src/routes/vehicle/SAEVKeyPoint.cpp
+        src/routes/vehicle/SAEVKeyPoint.h
         src/instance/SAEVehicle.cpp
         src/instance/SAEVehicle.h
+        src/routes/vehicle/propagation/SAEVRouteChangelist.cpp
+        src/routes/vehicle/propagation/SAEVRouteChangelist.h
+        src/routes/vehicle/propagation/SAEVRouteChange.cpp
+        src/routes/vehicle/propagation/SAEVRouteChange.h
 )
 
 target_include_directories(GreedyAlgorithm PRIVATE ${PYTHON_INCLUDE_DIRS})
diff --git a/src/instance/requests/Request.cpp b/src/instance/requests/Request.cpp
index d9b131c..a30d8d0 100644
--- a/src/instance/requests/Request.cpp
+++ b/src/instance/requests/Request.cpp
@@ -12,6 +12,15 @@ Request::Request(const int departureNodeIndex, const int arrivalNodeIndex, const
     _departureTW = _arrivalTW - deltaTime;
 }
 
+Request::Request(const int departureNodeIndex, const int arrivalNodeIndex, const TimeWindow &arrivalTw,
+                 const int deltaTime, const int weight, const Graph& graph) :
+                 _departureNodeIndex(departureNodeIndex),_arrivalNodeIndex(arrivalNodeIndex),
+                 _arrivalTW(arrivalTw),_deltaTime(deltaTime), _weight(weight) {
+    _currentDeltaTime = deltaTime;
+    _departureTW.min = _arrivalTW.min - deltaTime;
+    _departureTW.max = _arrivalTW.max - graph.getShortestSAEVPath(departureNodeIndex, arrivalNodeIndex);
+}
+
 const int Request::getDepartureNodeIndex() const {
     return _departureNodeIndex;
 }
@@ -52,6 +61,24 @@ const TimeWindow &Request::getDepartureTw() const {
     return _departureTW;
 }
 
+const int &Request::getMinDepartureTw() const {
+    return _departureTW.min;
+}
+
+
+const int &Request::getMaxDepartureTw() const {
+    return _departureTW.max;
+}
+
+const int &Request::getMinArrivalTw() const {
+    return _arrivalTW.min;
+}
+
+
+const int &Request::getMaxArrivalTw() const {
+    return _arrivalTW.max;
+}
+
 //-----------------------------
 //---------- Setters ----------
 //-----------------------------
diff --git a/src/instance/requests/Request.h b/src/instance/requests/Request.h
index f0af0cc..04440a1 100644
--- a/src/instance/requests/Request.h
+++ b/src/instance/requests/Request.h
@@ -8,6 +8,7 @@
 
 #include "../../TimeWindow.h"
 #include "../../routes/RequestRoute.h"
+#include "../graph/Graph.h"
 
 class Request {
 private:
@@ -27,6 +28,8 @@ private:
 public:
     Request(const int departureNodeIndex, const int arrivalNodeIndex,
             const TimeWindow &arrivalTw, const int deltaTime, const int weight);
+    Request(const int departureNodeIndex, const int arrivalNodeIndex, const TimeWindow &arrivalTw,
+            const int deltaTime, const int weight, const Graph& graph);
 
     //Getters
     [[nodiscard]] const int getDepartureNodeIndex() const;
@@ -39,6 +42,10 @@ public:
     [[nodiscard]] int getRequestServiceEnd() const;
     [[nodiscard]] const RequestRoute &getCurrentRoute() const;
     [[nodiscard]] const TimeWindow &getDepartureTw() const;
+    [[nodiscard]] const int &getMinDepartureTw() const;
+    [[nodiscard]] const int &getMaxDepartureTw() const;
+    [[nodiscard]] const int &getMinArrivalTw() const;
+    [[nodiscard]] const int &getMaxArrivalTw() const;
 
     //Setters
     void setCurrentDeltaTime(int currentDeltaTime);
diff --git a/test/lib/googletest b/test/lib/googletest
index eff443c..b1a777f 160000
--- a/test/lib/googletest
+++ b/test/lib/googletest
@@ -1 +1 @@
-Subproject commit eff443c6ef5eb6ab598bfaae27f9427fdb4f6af7
+Subproject commit b1a777f31913f8a047f43b2a5f823e736e7f5082
-- 
GitLab


From 19c5b356a84decb632e3fa5b4417ec60a20e7694 Mon Sep 17 00:00:00 2001
From: Romain BERNARD <romain.bernard@uca.fr>
Date: Tue, 23 Apr 2024 19:04:41 +0200
Subject: [PATCH 021/327] WIP route changes for constraint propagation

---
 src/routes/SAEVKeyPoint.cpp                   | 63 -----------------
 src/routes/SAEVRoute.cpp                      |  5 --
 src/routes/SAEVRoute.h                        | 29 --------
 src/routes/vehicle/SAEVKeyPoint.cpp           | 69 ++++++++++++++++++
 src/routes/{ => vehicle}/SAEVKeyPoint.h       | 31 ++++----
 src/routes/vehicle/SAEVRoute.cpp              | 70 +++++++++++++++++++
 src/routes/vehicle/SAEVRoute.h                | 52 ++++++++++++++
 .../vehicle/propagation/SAEVRouteChange.cpp   | 21 ++++++
 .../vehicle/propagation/SAEVRouteChange.h     | 34 +++++++++
 .../propagation/SAEVRouteChangelist.cpp       | 48 +++++++++++++
 .../vehicle/propagation/SAEVRouteChangelist.h | 36 ++++++++++
 11 files changed, 349 insertions(+), 109 deletions(-)
 delete mode 100644 src/routes/SAEVKeyPoint.cpp
 delete mode 100644 src/routes/SAEVRoute.cpp
 delete mode 100644 src/routes/SAEVRoute.h
 create mode 100644 src/routes/vehicle/SAEVKeyPoint.cpp
 rename src/routes/{ => vehicle}/SAEVKeyPoint.h (62%)
 create mode 100644 src/routes/vehicle/SAEVRoute.cpp
 create mode 100644 src/routes/vehicle/SAEVRoute.h
 create mode 100644 src/routes/vehicle/propagation/SAEVRouteChange.cpp
 create mode 100644 src/routes/vehicle/propagation/SAEVRouteChange.h
 create mode 100644 src/routes/vehicle/propagation/SAEVRouteChangelist.cpp
 create mode 100644 src/routes/vehicle/propagation/SAEVRouteChangelist.h

diff --git a/src/routes/SAEVKeyPoint.cpp b/src/routes/SAEVKeyPoint.cpp
deleted file mode 100644
index c29d7fe..0000000
--- a/src/routes/SAEVKeyPoint.cpp
+++ /dev/null
@@ -1,63 +0,0 @@
-//
-// Created by romain on 22/03/24.
-//
-
-#include "SAEVKeyPoint.h"
-
-
-SAEVKeyPoint::SAEVKeyPoint(Request *request, bool isEntry) {
-    _request = request;
-    _isEntry = isEntry;
-}
-
-Request *SAEVKeyPoint::getRequest() const {
-    return _request;
-}
-
-void SAEVKeyPoint::setRequest(Request *request) {
-    SAEVKeyPoint::_request = request;
-}
-
-bool SAEVKeyPoint::check() const {
-    return KeyPoint::check() && _request != nullptr;
-}
-
-SAEVKeyPoint *SAEVKeyPoint::getPredecessor() const {
-    return _predecessor;
-}
-
-void SAEVKeyPoint::setPredecessor(SAEVKeyPoint *predecessor) {
-    _predecessor = predecessor;
-}
-
-SAEVKeyPoint *SAEVKeyPoint::getSuccessor() const {
-    return _successor;
-}
-
-void SAEVKeyPoint::setSuccessor(SAEVKeyPoint *successor) {
-    _successor = successor;
-}
-
-int SAEVKeyPoint::getCurrentCapacity() const {
-    return _currentCapacity;
-}
-
-void SAEVKeyPoint::setCurrentCapacity(int currentCapacity) {
-    _currentCapacity = currentCapacity;
-}
-
-int SAEVKeyPoint::getMinTw() const {
-    return _minTW;
-}
-
-void SAEVKeyPoint::setMinTw(int minTw) {
-    _minTW = minTw;
-}
-
-int SAEVKeyPoint::getMaxTw() const {
-    return _maxTW;
-}
-
-void SAEVKeyPoint::setMaxTw(int maxTw) {
-    _maxTW = maxTw;
-}
diff --git a/src/routes/SAEVRoute.cpp b/src/routes/SAEVRoute.cpp
deleted file mode 100644
index d467cbb..0000000
--- a/src/routes/SAEVRoute.cpp
+++ /dev/null
@@ -1,5 +0,0 @@
-//
-// Created by romain on 22/03/24.
-//
-
-#include "SAEVRoute.h"
diff --git a/src/routes/SAEVRoute.h b/src/routes/SAEVRoute.h
deleted file mode 100644
index 6c63ae6..0000000
--- a/src/routes/SAEVRoute.h
+++ /dev/null
@@ -1,29 +0,0 @@
-//
-// Created by romain on 22/03/24.
-//
-
-#ifndef GREEDYALGORITHM_SAEVROUTE_H
-#define GREEDYALGORITHM_SAEVROUTE_H
-
-
-#include <vector>
-#include "SAEVKeyPoint.h"
-
-class SAEVRoute {
-private:
-    std::vector<SAEVKeyPoint> _route;
-    size_t _nbRequest;
-public:
-    SAEVRoute() = default;
-    explicit SAEVRoute(const std::vector<Request>& requestList);
-    void initSAEVRoute(const std::vector<Request>& requestList);
-
-    [[nodiscard]] const std::vector<SAEVKeyPoint> &getRoute() const {
-        return _route;
-    }
-
-
-};
-
-
-#endif //GREEDYALGORITHM_SAEVROUTE_H
diff --git a/src/routes/vehicle/SAEVKeyPoint.cpp b/src/routes/vehicle/SAEVKeyPoint.cpp
new file mode 100644
index 0000000..79d9f36
--- /dev/null
+++ b/src/routes/vehicle/SAEVKeyPoint.cpp
@@ -0,0 +1,69 @@
+//
+// Created by romain on 22/03/24.
+//
+
+#include "SAEVKeyPoint.h"
+
+bool SAEVKeyPoint::check() const {
+    return KeyPoint::check();
+}
+
+SAEVKeyPoint *SAEVKeyPoint::getPredecessor() const {
+    return _predecessor;
+}
+
+void SAEVKeyPoint::setPredecessor(SAEVKeyPoint *predecessor) {
+    _predecessor = predecessor;
+}
+
+SAEVKeyPoint *SAEVKeyPoint::getSuccessor() const {
+    return _successor;
+}
+
+void SAEVKeyPoint::setSuccessor(SAEVKeyPoint *successor) {
+    _successor = successor;
+}
+
+int SAEVKeyPoint::getCurrentCapacity() const {
+    return _currentOccupation;
+}
+
+void SAEVKeyPoint::setCurrentCapacity(int currentCapacity) {
+    _currentOccupation = currentCapacity;
+}
+
+int SAEVKeyPoint::getMinTw() const {
+    return _minTW;
+}
+
+void SAEVKeyPoint::setMinTw(int minTw) {
+    _minTW = minTw;
+}
+
+int SAEVKeyPoint::getMaxTw() const {
+    return _maxTW;
+}
+
+void SAEVKeyPoint::setMaxTw(int maxTw) {
+    _maxTW = maxTw;
+}
+
+SAEVKeyPoint::SAEVKeyPoint(const Graph &graph, const Request &request, bool isEntry) {
+    if(isEntry) {
+        _minTW = request.getArrivalTw().min - request.getDeltaTime();
+        _maxTW = request.getArrivalTw().max - graph.getShortestSAEVPath(request.getDepartureNodeIndex(), request.getArrivalNodeIndex());
+    } else {
+        _minTW = request.getArrivalTw().min;
+        _maxTW = request.getArrivalTw().max;
+    }
+}
+
+SAEVKeyPoint::SAEVKeyPoint(bool isEntry) {
+    if(isEntry) {
+        _minTW =
+        _maxTW = request.getArrivalTw().max - graph.getShortestSAEVPath(request.getDepartureNodeIndex(), request.getArrivalNodeIndex());
+    } else {
+        _minTW = request.getArrivalTw().min;
+        _maxTW = request.getArrivalTw().max;
+    }
+}
diff --git a/src/routes/SAEVKeyPoint.h b/src/routes/vehicle/SAEVKeyPoint.h
similarity index 62%
rename from src/routes/SAEVKeyPoint.h
rename to src/routes/vehicle/SAEVKeyPoint.h
index d669a2e..639467a 100644
--- a/src/routes/SAEVKeyPoint.h
+++ b/src/routes/vehicle/SAEVKeyPoint.h
@@ -6,20 +6,33 @@
 #define GREEDYALGORITHM_SAEVKEYPOINT_H
 
 
-#include "../instance/requests/Request.h"
-#include "KeyPoint.h"
+#include "../../instance/requests/Request.h"
+#include "../KeyPoint.h"
+#include "../../instance/graph/Graph.h"
 
 class SAEVKeyPoint : public virtual KeyPoint {
 private:
-    Request* _request{};
-    SAEVKeyPoint* _predecessor{};
-    SAEVKeyPoint* _successor{};
-    int _currentCapacity{0};
+    SAEVKeyPoint* _predecessor{nullptr};
+    SAEVKeyPoint* _successor{nullptr};
+    int _currentOccupation{0};
     int _minTW{0};
     int _maxTW{0};
     SAEVehicle* _vehiclePointer{};
 
 public:
+    /**
+     * Depot KP initialization
+     * @param isEntry
+     */
+    SAEVKeyPoint(bool isEntry);
+    /**
+     * SAEV KP initialization
+     * @param graph
+     * @param request
+     * @param isEntry
+     */
+    SAEVKeyPoint(const Graph &graph, const Request& request, bool isEntry);
+
     [[nodiscard]] SAEVKeyPoint *getPredecessor() const;
     void setPredecessor(SAEVKeyPoint *predecessor);
 
@@ -35,12 +48,6 @@ public:
     [[nodiscard]] int getMaxTw() const;
     void setMaxTw(int maxTw);
 
-public:
-    SAEVKeyPoint(Request* request, bool  isEntry);
-
-    [[nodiscard]] Request *getRequest() const;
-    void setRequest(Request *request);
-
     [[nodiscard]] bool check() const override;
 
     ~SAEVKeyPoint() = default;
diff --git a/src/routes/vehicle/SAEVRoute.cpp b/src/routes/vehicle/SAEVRoute.cpp
new file mode 100644
index 0000000..7fe64ec
--- /dev/null
+++ b/src/routes/vehicle/SAEVRoute.cpp
@@ -0,0 +1,70 @@
+//
+// Created by romain on 22/03/24.
+//
+
+#include "SAEVRoute.h"
+
+SAEVRoute::SAEVRoute(const Graph& graph, const std::vector<Request>& requestList) : _nbRequest(requestList.size()), _graph(&graph), _requestList(&requestList) {
+    _route.reserve(_nbRequest*4); //nbRequest*2 O/D KeyPoints + nbRequest*2 Start/End depots (upper bound #vehicle = #requests
+
+    //Init Request O/D key points
+    for(size_t i = 0; i < _nbRequest; ++i) {
+        _route.at(i*2) = SAEVKeyPoint(graph, requestList.at(i), true); //origin
+        _route.at(i*2+1) = SAEVKeyPoint(graph, requestList.at(i), false); //destination
+    }
+
+    //Init start/end depot key points
+    for(size_t i = _nbRequest; i < _nbRequest*2; ++i) {
+        _route.at(i*2) = SAEVKeyPoint(true); //start
+        _route.at(i*2+1) = SAEVKeyPoint(false); //end
+    }
+}
+
+void SAEVRoute::insertRequest(int requestIdx, int originRequestPredecessorIdx, int destinationRequestPredecessorIdx) {
+    SAEVKeyPoint& originKp = _route.at(requestIdx);
+    SAEVKeyPoint& destinationKp = _route.at(requestIdx + 1);
+
+    SAEVKeyPoint& originPredKp = _route.at(originRequestPredecessorIdx);
+    SAEVKeyPoint *originSuccKp = originPredKp.getSuccessor();
+    SAEVKeyPoint& destinationPredKp = _route.at(destinationRequestPredecessorIdx);
+    SAEVKeyPoint *destinationSuccKp = destinationPredKp.getSuccessor();
+
+    //Set values for O/D KPs
+    originKp.setPredecessor(&originPredKp);
+    originKp.setSuccessor(originSuccKp);
+    destinationKp.setPredecessor(&destinationPredKp);
+    destinationKp.setSuccessor(destinationSuccKp);
+
+    //Set values for predecessors/successors
+    originPredKp.setSuccessor(&originKp);
+    originSuccKp->setPredecessor(&originKp);
+    destinationPredKp.setSuccessor(&destinationKp);
+    destinationSuccKp->setPredecessor(&destinationKp);
+}
+
+void SAEVRoute::removeRequest(int requestIdx) {
+    SAEVKeyPoint& originKp = _route.at(requestIdx);
+    SAEVKeyPoint& destinationKp = _route.at(requestIdx + 1);
+
+    //get predecessor and successor for request
+    SAEVKeyPoint* originPredecessor = originKp.getPredecessor();
+    SAEVKeyPoint* originSuccessor = destinationKp.getSuccessor();
+    SAEVKeyPoint* destinationPredecessor = originKp.getPredecessor();
+    SAEVKeyPoint* destinationSuccessor = destinationKp.getSuccessor();
+
+    //Link pred and successor from origin and destination
+    originPredecessor->setSuccessor(originSuccessor);
+    destinationPredecessor->setSuccessor(destinationSuccessor);
+
+    //Revert origin/destination key points to their default state
+    originKp.setPredecessor(nullptr);
+    originKp.setSuccessor(nullptr);
+    destinationKp.setPredecessor(nullptr);
+    destinationKp.setSuccessor(nullptr);
+    originKp.setMinTw(_requestList->at(requestIdx).getMinDepartureTw());
+    originKp.setMaxTw(_requestList->at(requestIdx).getMaxDepartureTw());
+    destinationKp.setMinTw(_requestList->at(requestIdx).getMinArrivalTw());
+    destinationKp.setMaxTw(_requestList->at(requestIdx).getMaxArrivalTw());
+}
+
+
diff --git a/src/routes/vehicle/SAEVRoute.h b/src/routes/vehicle/SAEVRoute.h
new file mode 100644
index 0000000..e056e82
--- /dev/null
+++ b/src/routes/vehicle/SAEVRoute.h
@@ -0,0 +1,52 @@
+//
+// Created by romain on 22/03/24.
+//
+
+#ifndef GREEDYALGORITHM_SAEVROUTE_H
+#define GREEDYALGORITHM_SAEVROUTE_H
+
+
+#include <vector>
+#include "SAEVKeyPoint.h"
+
+class SAEVRoute {
+private:
+    std::vector<SAEVKeyPoint> _route;
+    size_t _nbRequest;
+    const Graph* _graph;
+    const std::vector<Request>* _requestList;
+public:
+    SAEVRoute() = default;
+    /**
+     * Initializes a route following a tabular doubly chained approach where 0->nbRequest*2-1 are Request Origin (even)/Destination (odd)
+     * and nbRequest*2 -> nbRequest*4-1 are vehicle start (even)/end (odd) depot. Each KeyPoint has
+     * @param graph the instance's graph, used to get shortest paths values during key point initialization and later in constraint propagation
+     * @param requestList the instance's request list, used to associate KeyPoints that represent requests with the appropriate informations
+     */
+    explicit SAEVRoute(const Graph& graph, const std::vector<Request>& requestList);
+
+    [[nodiscard]] const std::vector<SAEVKeyPoint> &getRoute() const {
+        return _route;
+    }
+
+    /**
+     * Raw request route insertion method. Public for debug purposes, but should effectively never be called by an outside member FIXME:make private
+     * @param requestIdx index of the request we want to insert in the route
+     * @param originRequestPredecessorIdx Index of the request that will precede the origin of the request we want to insert
+     * @param destinationRequestPredecessorIdx Index of the request that will precede the destination of the request we want to insert
+     */
+    void insertRequest(int requestIdx, int originRequestPredecessorIdx, int destinationRequestPredecessorIdx);
+
+    void insertRequestWithPropagation(int requestIdx, int originRequestPredecessorIdx, int destinationRequestPredecessorIdx);
+
+    /**
+     * Raw request removal method. Public for debug purposes, but should effectively never be called by an outside member FIXME:make private
+     * @param requestIdx index of the request we want to remove from the route
+     */
+    void removeRequest(int requestIdx);
+
+    void removeRequestWithPropagation(int requestIdx);
+};
+
+
+#endif //GREEDYALGORITHM_SAEVROUTE_H
diff --git a/src/routes/vehicle/propagation/SAEVRouteChange.cpp b/src/routes/vehicle/propagation/SAEVRouteChange.cpp
new file mode 100644
index 0000000..d7fabb3
--- /dev/null
+++ b/src/routes/vehicle/propagation/SAEVRouteChange.cpp
@@ -0,0 +1,21 @@
+//
+// Created by romain on 23/04/24.
+//
+
+#include "SAEVRouteChange.h"
+
+void SAEVRouteChange::applyChange() {
+    if(_bound == Min) {
+        _kpPointer->getMinTw() + _value;
+    } else {
+        _kpPointer->getMaxTw() - _value;
+    }
+}
+
+void SAEVRouteChange::revertChange() {
+    if(_bound == Min) {
+        _kpPointer->getMinTw() - _value;
+    } else {
+        _kpPointer->getMaxTw() + _value;
+    }
+}
diff --git a/src/routes/vehicle/propagation/SAEVRouteChange.h b/src/routes/vehicle/propagation/SAEVRouteChange.h
new file mode 100644
index 0000000..766c868
--- /dev/null
+++ b/src/routes/vehicle/propagation/SAEVRouteChange.h
@@ -0,0 +1,34 @@
+//
+// Created by romain on 23/04/24.
+//
+
+#ifndef GREEDYALGORITHM_SAEVROUTECHANGE_H
+#define GREEDYALGORITHM_SAEVROUTECHANGE_H
+
+#include "../SAEVKeyPoint.h"
+
+enum Bound {
+    Min, Max
+};
+
+class SAEVRouteChange {
+private:
+    SAEVKeyPoint* const _kpPointer;
+    const Bound _bound;
+    const int _value;
+public:
+    SAEVRouteChange(SAEVKeyPoint& kp, Bound bound, int value) : _kpPointer(&kp), _bound(bound), _value(value) {};
+    /**
+     * Unconditionally applies the bound change on the appropriate key point
+     * (adds value to the min bound or subtracts value to the max bound)
+     */
+    void applyChange();
+    /**
+     * Unconditionally reverts the bound change on the appropriate key point
+     * (subtracts value to the min bound or adds value to the max bound)
+     */
+    void revertChange();
+};
+
+
+#endif //GREEDYALGORITHM_SAEVROUTECHANGE_H
diff --git a/src/routes/vehicle/propagation/SAEVRouteChangelist.cpp b/src/routes/vehicle/propagation/SAEVRouteChangelist.cpp
new file mode 100644
index 0000000..1e2c214
--- /dev/null
+++ b/src/routes/vehicle/propagation/SAEVRouteChangelist.cpp
@@ -0,0 +1,48 @@
+//
+// Created by romain on 23/04/24.
+//
+
+#include "SAEVRouteChangelist.h"
+
+const std::vector<SAEVRouteChange> &SAEVRouteChangelist::getChangelist() const {
+    return _changelist;
+}
+
+void SAEVRouteChangelist::push_back(SAEVRouteChange change) {
+    _changelist.push_back(change);
+}
+
+void SAEVRouteChangelist::emplace_back(SAEVRouteChange change) {
+    _changelist.emplace_back(change);
+}
+
+void SAEVRouteChangelist::emplace_back(SAEVKeyPoint &kp, Bound bound, int value) {
+    _changelist.emplace_back(kp, bound, value);
+}
+
+void SAEVRouteChangelist::applyChanges(SAEVRoute route) const {
+    route.insertRequest(_requestIdx, _originIdx, _destinationIdx);
+    for(SAEVRouteChange change : _changelist) {
+        change.applyChange();
+    }
+}
+
+void SAEVRouteChangelist::revertChanges(SAEVRoute route) const {
+    route.removeRequest(_requestIdx);
+    for(SAEVRouteChange change : _changelist) {
+        change.revertChange();
+    }
+}
+
+int SAEVRouteChangelist::getRequestIdx() const {
+    return _requestIdx;
+}
+
+int SAEVRouteChangelist::getOriginIdx() const {
+    return _originIdx;
+}
+
+int SAEVRouteChangelist::getDestinationIdx() const {
+    return _destinationIdx;
+}
+
diff --git a/src/routes/vehicle/propagation/SAEVRouteChangelist.h b/src/routes/vehicle/propagation/SAEVRouteChangelist.h
new file mode 100644
index 0000000..37b4c15
--- /dev/null
+++ b/src/routes/vehicle/propagation/SAEVRouteChangelist.h
@@ -0,0 +1,36 @@
+//
+// Created by romain on 23/04/24.
+//
+
+#ifndef GREEDYALGORITHM_SAEVROUTECHANGELIST_H
+#define GREEDYALGORITHM_SAEVROUTECHANGELIST_H
+
+
+#include "SAEVRouteChange.h"
+#include "../SAEVRoute.h"
+
+class SAEVRouteChangelist {
+private:
+    const int _requestIdx, _originIdx, _destinationIdx;
+    std::vector<SAEVRouteChange> _changelist{};
+
+public:
+    explicit SAEVRouteChangelist(const int requestIdx, const int originIdx, const int destinationIdx)
+    : _requestIdx(requestIdx), _originIdx(originIdx), _destinationIdx(destinationIdx) {};
+
+    [[nodiscard]] const std::vector<SAEVRouteChange> &getChangelist() const;
+    [[nodiscard]] int getRequestIdx() const;
+    [[nodiscard]] int getOriginIdx() const;
+    [[nodiscard]] int getDestinationIdx() const;
+
+    void push_back(SAEVRouteChange change);
+    void emplace_back(SAEVRouteChange change);
+    void emplace_back(SAEVKeyPoint& kp, Bound bound, int value);
+
+    void applyChanges(SAEVRoute route) const;
+    void revertChanges(SAEVRoute route) const;
+
+};
+
+
+#endif //GREEDYALGORITHM_SAEVROUTECHANGELIST_H
-- 
GitLab


From ff1a28182aedfaef3b419aa67cd76c225f2a04e6 Mon Sep 17 00:00:00 2001
From: Romain BERNARD <romain.bernard@uca.fr>
Date: Wed, 24 Apr 2024 11:07:56 +0200
Subject: [PATCH 022/327] add score value to the change list

---
 src/routes/vehicle/propagation/SAEVRouteChangelist.cpp | 8 ++++++++
 src/routes/vehicle/propagation/SAEVRouteChangelist.h   | 4 ++++
 2 files changed, 12 insertions(+)

diff --git a/src/routes/vehicle/propagation/SAEVRouteChangelist.cpp b/src/routes/vehicle/propagation/SAEVRouteChangelist.cpp
index 1e2c214..467f4b6 100644
--- a/src/routes/vehicle/propagation/SAEVRouteChangelist.cpp
+++ b/src/routes/vehicle/propagation/SAEVRouteChangelist.cpp
@@ -46,3 +46,11 @@ int SAEVRouteChangelist::getDestinationIdx() const {
     return _destinationIdx;
 }
 
+double SAEVRouteChangelist::getScore() const {
+    return _score;
+}
+
+void SAEVRouteChangelist::setScore(double score) {
+    SAEVRouteChangelist::_score = score;
+}
+
diff --git a/src/routes/vehicle/propagation/SAEVRouteChangelist.h b/src/routes/vehicle/propagation/SAEVRouteChangelist.h
index 37b4c15..ca9ae5f 100644
--- a/src/routes/vehicle/propagation/SAEVRouteChangelist.h
+++ b/src/routes/vehicle/propagation/SAEVRouteChangelist.h
@@ -13,6 +13,7 @@ class SAEVRouteChangelist {
 private:
     const int _requestIdx, _originIdx, _destinationIdx;
     std::vector<SAEVRouteChange> _changelist{};
+    double _score{std::numeric_limits<double>::infinity()}; //Init score to infinity
 
 public:
     explicit SAEVRouteChangelist(const int requestIdx, const int originIdx, const int destinationIdx)
@@ -22,6 +23,9 @@ public:
     [[nodiscard]] int getRequestIdx() const;
     [[nodiscard]] int getOriginIdx() const;
     [[nodiscard]] int getDestinationIdx() const;
+    [[nodiscard]] double getScore() const;
+
+    void setScore(double score);
 
     void push_back(SAEVRouteChange change);
     void emplace_back(SAEVRouteChange change);
-- 
GitLab


From c5fbc4b9ce88e6ac9ec63e6e5dfa1c9bfffaf2e0 Mon Sep 17 00:00:00 2001
From: Romain BERNARD <romain.bernard@uca.fr>
Date: Wed, 24 Apr 2024 11:20:46 +0200
Subject: [PATCH 023/327] comparison operators for ordering if needed

---
 src/routes/vehicle/propagation/SAEVRouteChangelist.cpp | 8 ++++++++
 src/routes/vehicle/propagation/SAEVRouteChangelist.h   | 2 ++
 2 files changed, 10 insertions(+)

diff --git a/src/routes/vehicle/propagation/SAEVRouteChangelist.cpp b/src/routes/vehicle/propagation/SAEVRouteChangelist.cpp
index 467f4b6..1b826c0 100644
--- a/src/routes/vehicle/propagation/SAEVRouteChangelist.cpp
+++ b/src/routes/vehicle/propagation/SAEVRouteChangelist.cpp
@@ -54,3 +54,11 @@ void SAEVRouteChangelist::setScore(double score) {
     SAEVRouteChangelist::_score = score;
 }
 
+bool SAEVRouteChangelist::operator>(const SAEVRouteChangelist &rhs) const {
+    return _score > rhs.getScore();
+}
+
+bool SAEVRouteChangelist::operator<(const SAEVRouteChangelist &rhs) const {
+    return _score < rhs.getScore();
+}
+
diff --git a/src/routes/vehicle/propagation/SAEVRouteChangelist.h b/src/routes/vehicle/propagation/SAEVRouteChangelist.h
index ca9ae5f..6f9b9b8 100644
--- a/src/routes/vehicle/propagation/SAEVRouteChangelist.h
+++ b/src/routes/vehicle/propagation/SAEVRouteChangelist.h
@@ -34,6 +34,8 @@ public:
     void applyChanges(SAEVRoute route) const;
     void revertChanges(SAEVRoute route) const;
 
+    bool operator>(const SAEVRouteChangelist& rhs) const;
+    bool operator<(const SAEVRouteChangelist& rhs) const;
 };
 
 
-- 
GitLab


From 43d4f3bf01e965d31e54a063be63ced595a33d5b Mon Sep 17 00:00:00 2001
From: Romain BERNARD <romain.bernard@uca.fr>
Date: Wed, 24 Apr 2024 11:20:55 +0200
Subject: [PATCH 024/327] doc

---
 .../vehicle/propagation/SAEVRouteChangelist.h | 21 +++++++++++++++++++
 1 file changed, 21 insertions(+)

diff --git a/src/routes/vehicle/propagation/SAEVRouteChangelist.h b/src/routes/vehicle/propagation/SAEVRouteChangelist.h
index 6f9b9b8..cc23ed7 100644
--- a/src/routes/vehicle/propagation/SAEVRouteChangelist.h
+++ b/src/routes/vehicle/propagation/SAEVRouteChangelist.h
@@ -9,6 +9,11 @@
 #include "SAEVRouteChange.h"
 #include "../SAEVRoute.h"
 
+/**
+ * This class serves as iterative memory for changes made to key points during constraint propagation
+ * It memorizes the data to undo/redo request insertion and apply/revert changes made without losing time on duplicate feasibility checks
+ * To allow comparison and ordering between multiple insertions if necessary, it also memorizes a score associated with this constraint propagation
+ */
 class SAEVRouteChangelist {
 private:
     const int _requestIdx, _originIdx, _destinationIdx;
@@ -16,6 +21,12 @@ private:
     double _score{std::numeric_limits<double>::infinity()}; //Init score to infinity
 
 public:
+    /**
+     * Initializes a change list to memorize every iterative modification made during constraint propagation
+     * @param requestIdx The index of the request in the global request list
+     * @param originIdx The index of the request our origin will be inserted after
+     * @param destinationIdx The index of the request our destination will be inserted after
+     */
     explicit SAEVRouteChangelist(const int requestIdx, const int originIdx, const int destinationIdx)
     : _requestIdx(requestIdx), _originIdx(originIdx), _destinationIdx(destinationIdx) {};
 
@@ -31,7 +42,17 @@ public:
     void emplace_back(SAEVRouteChange change);
     void emplace_back(SAEVKeyPoint& kp, Bound bound, int value);
 
+    /**
+     * Inserts the request associated to this changelist to the given route and iteratively applies every change memorized in this changelist.
+     * Aside from OOB exceptions, no checks are done in this method
+     * @param route The route in which we wish to insert the request and apply the change list to
+     */
     void applyChanges(SAEVRoute route) const;
+    /**
+     * removes the request associated to this changelist from the given route and iteratively reverts every change memorized in this changelist.
+     * Aside from OOB exceptions, no checks are done in this method
+     * @param route The route in which we wish to remove the request and revert the change list
+     */
     void revertChanges(SAEVRoute route) const;
 
     bool operator>(const SAEVRouteChangelist& rhs) const;
-- 
GitLab


From 5212b8e0bd3f9aecff8fded1152a884274c5c537 Mon Sep 17 00:00:00 2001
From: Romain BERNARD <romain.bernard@uca.fr>
Date: Wed, 24 Apr 2024 11:37:01 +0200
Subject: [PATCH 025/327] include an SAEVRoute pointer to the change list to
 only apply it on the appropriate route

---
 .../vehicle/propagation/SAEVRouteChangelist.cpp   | 15 +++++++++------
 .../vehicle/propagation/SAEVRouteChangelist.h     | 11 +++++++++--
 2 files changed, 18 insertions(+), 8 deletions(-)

diff --git a/src/routes/vehicle/propagation/SAEVRouteChangelist.cpp b/src/routes/vehicle/propagation/SAEVRouteChangelist.cpp
index 1b826c0..e72e77a 100644
--- a/src/routes/vehicle/propagation/SAEVRouteChangelist.cpp
+++ b/src/routes/vehicle/propagation/SAEVRouteChangelist.cpp
@@ -20,15 +20,15 @@ void SAEVRouteChangelist::emplace_back(SAEVKeyPoint &kp, Bound bound, int value)
     _changelist.emplace_back(kp, bound, value);
 }
 
-void SAEVRouteChangelist::applyChanges(SAEVRoute route) const {
-    route.insertRequest(_requestIdx, _originIdx, _destinationIdx);
+void SAEVRouteChangelist::applyChanges() const {
+    _routePtr->insertRequest(_requestIdx, _originIdx, _destinationIdx);
     for(SAEVRouteChange change : _changelist) {
         change.applyChange();
     }
 }
 
-void SAEVRouteChangelist::revertChanges(SAEVRoute route) const {
-    route.removeRequest(_requestIdx);
+void SAEVRouteChangelist::revertChanges() const {
+    _routePtr->removeRequest(_requestIdx);
     for(SAEVRouteChange change : _changelist) {
         change.revertChange();
     }
@@ -55,10 +55,13 @@ void SAEVRouteChangelist::setScore(double score) {
 }
 
 bool SAEVRouteChangelist::operator>(const SAEVRouteChangelist &rhs) const {
-    return _score > rhs.getScore();
+    return _routePtr == rhs.getRoutePtr() && _score > rhs.getScore();
 }
 
 bool SAEVRouteChangelist::operator<(const SAEVRouteChangelist &rhs) const {
-    return _score < rhs.getScore();
+    return _routePtr == rhs.getRoutePtr() && _score < rhs.getScore();
 }
 
+SAEVRoute * SAEVRouteChangelist::getRoutePtr() const {
+    return _routePtr;
+}
diff --git a/src/routes/vehicle/propagation/SAEVRouteChangelist.h b/src/routes/vehicle/propagation/SAEVRouteChangelist.h
index cc23ed7..3dbf2fb 100644
--- a/src/routes/vehicle/propagation/SAEVRouteChangelist.h
+++ b/src/routes/vehicle/propagation/SAEVRouteChangelist.h
@@ -16,6 +16,7 @@
  */
 class SAEVRouteChangelist {
 private:
+    SAEVRoute * const _routePtr;
     const int _requestIdx, _originIdx, _destinationIdx;
     std::vector<SAEVRouteChange> _changelist{};
     double _score{std::numeric_limits<double>::infinity()}; //Init score to infinity
@@ -23,12 +24,18 @@ private:
 public:
     /**
      * Initializes a change list to memorize every iterative modification made during constraint propagation
+     * @param routePtr a pointer to the route the constraint propagation was applied on. revert/apply operations will be done on this route
      * @param requestIdx The index of the request in the global request list
      * @param originIdx The index of the request our origin will be inserted after
      * @param destinationIdx The index of the request our destination will be inserted after
      */
-    explicit SAEVRouteChangelist(const int requestIdx, const int originIdx, const int destinationIdx)
-    : _requestIdx(requestIdx), _originIdx(originIdx), _destinationIdx(destinationIdx) {};
+    explicit SAEVRouteChangelist(SAEVRoute * const routePtr, const int requestIdx, const int originIdx, const int destinationIdx)
+    : _routePtr(routePtr), _requestIdx(requestIdx), _originIdx(originIdx), _destinationIdx(destinationIdx) {};
+
+    /**
+     * @return A pointer to the route this change list applies/reverts changes to
+     */
+    [[nodiscard]] SAEVRoute * getRoutePtr() const;
 
     [[nodiscard]] const std::vector<SAEVRouteChange> &getChangelist() const;
     [[nodiscard]] int getRequestIdx() const;
-- 
GitLab


From 9f43b786bc9115988c78351cbfcc1287cfd5ccca Mon Sep 17 00:00:00 2001
From: Romain BERNARD <romain.bernard@uca.fr>
Date: Wed, 24 Apr 2024 11:37:29 +0200
Subject: [PATCH 026/327] doc

---
 .../vehicle/propagation/SAEVRouteChangelist.h | 36 +++++++++++++++----
 1 file changed, 29 insertions(+), 7 deletions(-)

diff --git a/src/routes/vehicle/propagation/SAEVRouteChangelist.h b/src/routes/vehicle/propagation/SAEVRouteChangelist.h
index 3dbf2fb..a4d0251 100644
--- a/src/routes/vehicle/propagation/SAEVRouteChangelist.h
+++ b/src/routes/vehicle/propagation/SAEVRouteChangelist.h
@@ -10,9 +10,9 @@
 #include "../SAEVRoute.h"
 
 /**
- * This class serves as iterative memory for changes made to key points during constraint propagation
- * It memorizes the data to undo/redo request insertion and apply/revert changes made without losing time on duplicate feasibility checks
- * To allow comparison and ordering between multiple insertions if necessary, it also memorizes a score associated with this constraint propagation
+ * This class serves as iterative memory for changes made to key points during constraint propagation. \n
+ * It memorizes the data to undo/redo request insertion and apply/revert changes made without losing time on duplicate feasibility checks. \n
+ * To allow comparison and ordering between multiple insertions if necessary, it also memorizes a score associated with this constraint propagation (lower is better)
  */
 class SAEVRouteChangelist {
 private:
@@ -38,11 +38,27 @@ public:
     [[nodiscard]] SAEVRoute * getRoutePtr() const;
 
     [[nodiscard]] const std::vector<SAEVRouteChange> &getChangelist() const;
+    /**
+     * @return The index of the request that we want to insert to a route
+     */
     [[nodiscard]] int getRequestIdx() const;
+    /**
+     * @return The index of the request our origin will be inserted after
+     */
     [[nodiscard]] int getOriginIdx() const;
+    /**
+     * @return The index of the request our destination will be inserted after
+     */
     [[nodiscard]] int getDestinationIdx() const;
+    /**
+     * @return A score value associated with this changelist. A lower score is better
+     */
     [[nodiscard]] double getScore() const;
 
+    /**
+     * Updates this change list's score value if needed (namely, after the whole propagation has been done)
+     * @param score A value representing how good the insertion associated with this change list is (lower is better)
+     */
     void setScore(double score);
 
     void push_back(SAEVRouteChange change);
@@ -52,17 +68,23 @@ public:
     /**
      * Inserts the request associated to this changelist to the given route and iteratively applies every change memorized in this changelist.
      * Aside from OOB exceptions, no checks are done in this method
-     * @param route The route in which we wish to insert the request and apply the change list to
      */
-    void applyChanges(SAEVRoute route) const;
+    void applyChanges() const;
     /**
      * removes the request associated to this changelist from the given route and iteratively reverts every change memorized in this changelist.
      * Aside from OOB exceptions, no checks are done in this method
-     * @param route The route in which we wish to remove the request and revert the change list
      */
-    void revertChanges(SAEVRoute route) const;
+    void revertChanges() const;
 
+    /**
+     * @param rhs the value *this* will be compared to
+     * @return True iff this changelist's score is strictly higher than rhs' score
+     */
     bool operator>(const SAEVRouteChangelist& rhs) const;
+    /**
+     * @param rhs the value *this* will be compared to
+     * @return True iff this changelist's score is strictly lower than rhs' score
+     */
     bool operator<(const SAEVRouteChangelist& rhs) const;
 };
 
-- 
GitLab


From 4a9e765dee0f64d47c153a413190511e70c493bc Mon Sep 17 00:00:00 2001
From: Romain BERNARD <romain.bernard@uca.fr>
Date: Wed, 24 Apr 2024 13:25:09 +0200
Subject: [PATCH 027/327] memo for key point weights wrt changelist
 apply/revert

---
 src/routes/vehicle/propagation/SAEVRouteChangelist.cpp | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/src/routes/vehicle/propagation/SAEVRouteChangelist.cpp b/src/routes/vehicle/propagation/SAEVRouteChangelist.cpp
index e72e77a..2269ad7 100644
--- a/src/routes/vehicle/propagation/SAEVRouteChangelist.cpp
+++ b/src/routes/vehicle/propagation/SAEVRouteChangelist.cpp
@@ -25,6 +25,7 @@ void SAEVRouteChangelist::applyChanges() const {
     for(SAEVRouteChange change : _changelist) {
         change.applyChange();
     }
+    //TODO: update key point weights here ? (only if changelist.size > 0 & score < +Inf)
 }
 
 void SAEVRouteChangelist::revertChanges() const {
@@ -32,6 +33,7 @@ void SAEVRouteChangelist::revertChanges() const {
     for(SAEVRouteChange change : _changelist) {
         change.revertChange();
     }
+    //TODO: update key point weights here ? (only if changelist.size > 0 & score < +Inf)
 }
 
 int SAEVRouteChangelist::getRequestIdx() const {
-- 
GitLab


From 1e1b7a9afd7c793e5aa97268d2c7169c2115077e Mon Sep 17 00:00:00 2001
From: Romain BERNARD <romain.bernard@uca.fr>
Date: Wed, 24 Apr 2024 13:37:58 +0200
Subject: [PATCH 028/327] no need for removal with propagation for now (revert
 changes in this case)

---
 src/routes/vehicle/SAEVRoute.h | 2 --
 1 file changed, 2 deletions(-)

diff --git a/src/routes/vehicle/SAEVRoute.h b/src/routes/vehicle/SAEVRoute.h
index e056e82..b67ed0a 100644
--- a/src/routes/vehicle/SAEVRoute.h
+++ b/src/routes/vehicle/SAEVRoute.h
@@ -44,8 +44,6 @@ public:
      * @param requestIdx index of the request we want to remove from the route
      */
     void removeRequest(int requestIdx);
-
-    void removeRequestWithPropagation(int requestIdx);
 };
 
 
-- 
GitLab


From e0cbd72dcc2bfcbdfb6885d5c2fe2c3e37c9ec1a Mon Sep 17 00:00:00 2001
From: Romain BERNARD <romain.bernard@uca.fr>
Date: Wed, 24 Apr 2024 13:38:33 +0200
Subject: [PATCH 029/327] documentation for insertion and propagation (TODO:
 implement it)

---
 src/routes/vehicle/SAEVRoute.h | 25 ++++++++++++++++++++++++-
 1 file changed, 24 insertions(+), 1 deletion(-)

diff --git a/src/routes/vehicle/SAEVRoute.h b/src/routes/vehicle/SAEVRoute.h
index b67ed0a..55a23f4 100644
--- a/src/routes/vehicle/SAEVRoute.h
+++ b/src/routes/vehicle/SAEVRoute.h
@@ -8,6 +8,7 @@
 
 #include <vector>
 #include "SAEVKeyPoint.h"
+#include "propagation/SAEVRouteChangelist.h"
 
 class SAEVRoute {
 private:
@@ -37,7 +38,29 @@ public:
      */
     void insertRequest(int requestIdx, int originRequestPredecessorIdx, int destinationRequestPredecessorIdx);
 
-    void insertRequestWithPropagation(int requestIdx, int originRequestPredecessorIdx, int destinationRequestPredecessorIdx);
+    /**
+     * Tries to insert the request origin and destination next to the given origin/destination predecessors. \n \n
+     * First we verify multiple constraints that don't require actually inserting the request or doing constraint propagation. \n
+     * Then we propagate our min/max bounds, iteratively rippling through every modification induced by min/max neighbour constraints or delta constraints. \n
+     * ⚠️ In case of infeasibility, tryAdd automatically reverts changes and the change list will be effectively empty, but otherwise it's the caller's responsibility to revert changes if necessary
+     * @param requestIdx Identifier/index in the instance's request vector for the request we wish to insert
+     * @param originRequestPredecessorIdx Identifier/index in the instance's request vector for the request that will precede our request's origin in the route
+     * @param destinationRequestPredecessorIdx Identifier/index in the instance's request vector for the request that will precede our request's destination in the route
+     * @return A change list with every min/max bound change made during the tryAdd procedure and a score estimating insertion quality (lower is better)
+     */
+    SAEVRouteChangelist tryAddRequest(int requestIdx, int originRequestPredecessorIdx, int destinationRequestPredecessorIdx);
+
+    /**
+     * Method called after having validated conditions not requiring request insertion. \n
+     * This will effectively insert our procedure and ripple through bound changes. \n
+     * If the bounds become infeasible (min > max), then the propagation stops with a changelist with score= +Infinity and changes will be immediately reverted.
+     * Otherwise, it's the responsibility of this method's callers to revert changes if wanted (or to defer this responsibility to its caller)
+     * @param requestIdx Identifier/index in the instance's request vector for the request we wish to insert
+     * @param originRequestPredecessorIdx Identifier/index in the instance's request vector for the request that will precede our request's origin in the route
+     * @param destinationRequestPredecessorIdx Identifier/index in the instance's request vector for the request that will precede our request's destination in the route
+     * @return A change list with every min/max bound change made during the insert procedure and a score estimating insertion quality (lower is better)
+     */
+    SAEVRouteChangelist insertRequestWithPropagation(int requestIdx, int originRequestPredecessorIdx, int destinationRequestPredecessorIdx);
 
     /**
      * Raw request removal method. Public for debug purposes, but should effectively never be called by an outside member FIXME:make private
-- 
GitLab


From 88490ceb17d5ec857dedeb6f469efa03c0c85fdb Mon Sep 17 00:00:00 2001
From: Romain BERNARD <romain.bernard@uca.fr>
Date: Thu, 25 Apr 2024 18:33:29 +0200
Subject: [PATCH 030/327] remove arrival/departure instants to use time windows
 down the line

---
 src/instance/requests/Request.cpp | 16 ----------------
 src/routes/RequestRoute.cpp       | 23 -----------------------
 src/routes/RequestRoute.h         |  8 +-------
 3 files changed, 1 insertion(+), 46 deletions(-)

diff --git a/src/instance/requests/Request.cpp b/src/instance/requests/Request.cpp
index a30d8d0..5c1d1b0 100644
--- a/src/instance/requests/Request.cpp
+++ b/src/instance/requests/Request.cpp
@@ -115,22 +115,6 @@ void Request::setNodeIndex(int routeIndex, int nodeIndex) {
     _currentRoute.setNodeIndex(routeIndex, nodeIndex);
 }
 
-int Request::getArrivalInstant(int routeIndex) const {
-    return _currentRoute.getArrivalInstant(routeIndex);
-}
-
-void Request::setArrivalInstant(int routeIndex, int arrivalInstant) {
-    _currentRoute.setArrivalInstant(routeIndex, arrivalInstant);
-}
-
-int Request::getDepartureInstant(int routeIndex) const {
-    return _currentRoute.getDepartureInstant(routeIndex);
-}
-
-void Request::setDepartureInstant(int routeIndex, int departureInstant) {
-    _currentRoute.setDepartureInstant(routeIndex, departureInstant);
-}
-
 SAEVehicle *Request::getSAEV(int routeIndex) const {
     return _currentRoute.getSAEV(routeIndex);
 }
diff --git a/src/routes/RequestRoute.cpp b/src/routes/RequestRoute.cpp
index ddf7356..806cc9b 100644
--- a/src/routes/RequestRoute.cpp
+++ b/src/routes/RequestRoute.cpp
@@ -12,22 +12,6 @@ void RequestRoute::setNodeIndex(int routeIndex, int nodeIndex) {
     _route[routeIndex].setNodeIndex(nodeIndex);
 }
 
-int RequestRoute::getArrivalInstant(int routeIndex) const {
-    return _route[routeIndex].getArrivalInstant();
-}
-
-void RequestRoute::setArrivalInstant(int routeIndex, int arrivalInstant) {
-    _route[routeIndex].setArrivalInstant(arrivalInstant);
-}
-
-int RequestRoute::getDepartureInstant(int routeIndex) const {
-    return _route[routeIndex].getDepartureInstant();
-}
-
-void RequestRoute::setDepartureInstant(int routeIndex, int departureInstant) {
-    _route[routeIndex].setDepartureInstant(departureInstant);
-}
-
 SAEVehicle *RequestRoute::getSAEV(int routeIndex) const {
     return _route[routeIndex].getSAEV();
 }
@@ -50,13 +34,6 @@ void RequestRoute::setLineStop(int routeIndex, LineStop *lineStop) {
 void RequestRoute::resetKeyPoint(int routeIndex) {
     RequestKeyPoint keyPoint = _route[routeIndex];
     keyPoint.setNodeIndex(-1);
-    if(routeIndex > 1) { //If possible, set the time values to be the same as the preceding node to keep _route continuity
-        keyPoint.setArrivalInstant(_route[routeIndex - 1].getArrivalInstant());
-        keyPoint.setDepartureInstant(keyPoint.getArrivalInstant());
-    } else { //otherwise use default values
-        keyPoint.setArrivalInstant(-1);
-        keyPoint.setDepartureInstant(-1);
-    }
     keyPoint.setSAEV(nullptr);
     keyPoint.setLineStop(nullptr);
 }
diff --git a/src/routes/RequestRoute.h b/src/routes/RequestRoute.h
index 9874b88..e003dd1 100644
--- a/src/routes/RequestRoute.h
+++ b/src/routes/RequestRoute.h
@@ -18,7 +18,7 @@ public:
     };
 private:
     RequestKeyPoint _route[4];
-    Request* _requestPointer{};
+    Request* _requestPointer{nullptr};
 public:
     RequestRoute() = default;
     explicit RequestRoute(Request* request) {_requestPointer = request; };
@@ -26,12 +26,6 @@ public:
     [[nodiscard]] int getNodeIndex(int routeIndex) const;
     void setNodeIndex(int routeIndex, int nodeIndex);
 
-    [[nodiscard]] int getArrivalInstant(int routeIndex) const;
-    void setArrivalInstant(int routeIndex, int arrivalInstant);
-
-    [[nodiscard]] int getDepartureInstant(int routeIndex) const;
-    void setDepartureInstant(int routeIndex, int departureInstant);
-
     [[nodiscard]] SAEVehicle *getSAEV(int routeIndex) const;
     void setSAEV(int routeIndex, SAEVehicle *saev);
 
-- 
GitLab


From a8051bdaeb714a01a5b9165d1173cd5bfa6f867f Mon Sep 17 00:00:00 2001
From: Romain BERNARD <romain.bernard@uca.fr>
Date: Thu, 25 Apr 2024 18:55:56 +0200
Subject: [PATCH 031/327] default keypoint check definition

---
 src/routes/KeyPoint.h | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/src/routes/KeyPoint.h b/src/routes/KeyPoint.h
index 5d0be47..f808bad 100644
--- a/src/routes/KeyPoint.h
+++ b/src/routes/KeyPoint.h
@@ -19,7 +19,7 @@ public:
     [[nodiscard]] int getNodeIndex() const;
     void setNodeIndex(int nodeIndex);
 
-    [[nodiscard]] virtual bool check() const = 0;
+    [[nodiscard]] virtual bool check() const { return true; };
 
     ~KeyPoint() = default;
 };
-- 
GitLab


From 37ec30224ed93324886835f6282210d38f9cdbaf Mon Sep 17 00:00:00 2001
From: Romain BERNARD <romain.bernard@uca.fr>
Date: Thu, 25 Apr 2024 19:06:00 +0200
Subject: [PATCH 032/327] default depot time window

---
 src/routes/vehicle/SAEVKeyPoint.cpp | 11 +++--------
 src/routes/vehicle/SAEVKeyPoint.h   |  2 +-
 src/routes/vehicle/SAEVRoute.cpp    |  4 ++--
 3 files changed, 6 insertions(+), 11 deletions(-)

diff --git a/src/routes/vehicle/SAEVKeyPoint.cpp b/src/routes/vehicle/SAEVKeyPoint.cpp
index 79d9f36..8832338 100644
--- a/src/routes/vehicle/SAEVKeyPoint.cpp
+++ b/src/routes/vehicle/SAEVKeyPoint.cpp
@@ -58,12 +58,7 @@ SAEVKeyPoint::SAEVKeyPoint(const Graph &graph, const Request &request, bool isEn
     }
 }
 
-SAEVKeyPoint::SAEVKeyPoint(bool isEntry) {
-    if(isEntry) {
-        _minTW =
-        _maxTW = request.getArrivalTw().max - graph.getShortestSAEVPath(request.getDepartureNodeIndex(), request.getArrivalNodeIndex());
-    } else {
-        _minTW = request.getArrivalTw().min;
-        _maxTW = request.getArrivalTw().max;
-    }
+SAEVKeyPoint::SAEVKeyPoint() {
+    _minTW = 0;
+    _maxTW = INT16_MAX;
 }
diff --git a/src/routes/vehicle/SAEVKeyPoint.h b/src/routes/vehicle/SAEVKeyPoint.h
index 639467a..ebcf555 100644
--- a/src/routes/vehicle/SAEVKeyPoint.h
+++ b/src/routes/vehicle/SAEVKeyPoint.h
@@ -24,7 +24,7 @@ public:
      * Depot KP initialization
      * @param isEntry
      */
-    SAEVKeyPoint(bool isEntry);
+    SAEVKeyPoint();
     /**
      * SAEV KP initialization
      * @param graph
diff --git a/src/routes/vehicle/SAEVRoute.cpp b/src/routes/vehicle/SAEVRoute.cpp
index 7fe64ec..0aeb90e 100644
--- a/src/routes/vehicle/SAEVRoute.cpp
+++ b/src/routes/vehicle/SAEVRoute.cpp
@@ -15,8 +15,8 @@ SAEVRoute::SAEVRoute(const Graph& graph, const std::vector<Request>& requestList
 
     //Init start/end depot key points
     for(size_t i = _nbRequest; i < _nbRequest*2; ++i) {
-        _route.at(i*2) = SAEVKeyPoint(true); //start
-        _route.at(i*2+1) = SAEVKeyPoint(false); //end
+        _route.at(i*2) = SAEVKeyPoint(); //start
+        _route.at(i*2+1) = SAEVKeyPoint(); //end
     }
 }
 
-- 
GitLab


From 17db33c00b22e8c4da250eb24e23eef802aa6ca7 Mon Sep 17 00:00:00 2001
From: Romain BERNARD <romain.bernard@uca.fr>
Date: Thu, 25 Apr 2024 19:06:47 +0200
Subject: [PATCH 033/327] doc

---
 src/routes/vehicle/SAEVKeyPoint.h |  9 ++++-----
 src/routes/vehicle/SAEVRoute.h    | 16 ++++++++--------
 2 files changed, 12 insertions(+), 13 deletions(-)

diff --git a/src/routes/vehicle/SAEVKeyPoint.h b/src/routes/vehicle/SAEVKeyPoint.h
index ebcf555..6c8c9f6 100644
--- a/src/routes/vehicle/SAEVKeyPoint.h
+++ b/src/routes/vehicle/SAEVKeyPoint.h
@@ -21,15 +21,14 @@ private:
 
 public:
     /**
-     * Depot KP initialization
-     * @param isEntry
+     * Depot KP initialization with [0;max] time windows
      */
     SAEVKeyPoint();
     /**
      * SAEV KP initialization
-     * @param graph
-     * @param request
-     * @param isEntry
+     * @param graph the instance's graph, used to get shortest path and estimate start time windows relative to distances
+     * @param request the request associated with our key point, required to initialize time windows
+     * @param isEntry true iff the key point represents the request's origin, false otherwise
      */
     SAEVKeyPoint(const Graph &graph, const Request& request, bool isEntry);
 
diff --git a/src/routes/vehicle/SAEVRoute.h b/src/routes/vehicle/SAEVRoute.h
index 55a23f4..752cd5c 100644
--- a/src/routes/vehicle/SAEVRoute.h
+++ b/src/routes/vehicle/SAEVRoute.h
@@ -33,8 +33,8 @@ public:
     /**
      * Raw request route insertion method. Public for debug purposes, but should effectively never be called by an outside member FIXME:make private
      * @param requestIdx index of the request we want to insert in the route
-     * @param originRequestPredecessorIdx Index of the request that will precede the origin of the request we want to insert
-     * @param destinationRequestPredecessorIdx Index of the request that will precede the destination of the request we want to insert
+     * @param originRequestPredecessorIdx Identifier/index in the route key point vector for the request origin or destination that will precede the origin of the request we want to insert
+     * @param destinationRequestPredecessorIdx Identifier/index in the route key point vector for the request origin or destination that will precede the destination of the request we want to insert
      */
     void insertRequest(int requestIdx, int originRequestPredecessorIdx, int destinationRequestPredecessorIdx);
 
@@ -44,11 +44,11 @@ public:
      * Then we propagate our min/max bounds, iteratively rippling through every modification induced by min/max neighbour constraints or delta constraints. \n
      * ⚠️ In case of infeasibility, tryAdd automatically reverts changes and the change list will be effectively empty, but otherwise it's the caller's responsibility to revert changes if necessary
      * @param requestIdx Identifier/index in the instance's request vector for the request we wish to insert
-     * @param originRequestPredecessorIdx Identifier/index in the instance's request vector for the request that will precede our request's origin in the route
-     * @param destinationRequestPredecessorIdx Identifier/index in the instance's request vector for the request that will precede our request's destination in the route
+     * @param originRequestPredecessorIdx Identifier/index in the route key point vector for the request origin or destination that will precede our request's origin in the route
+     * @param destinationRequestPredecessorIdx Identifier/index in the route key point vector for the request origin or destination that will precede our request's destination in the route
      * @return A change list with every min/max bound change made during the tryAdd procedure and a score estimating insertion quality (lower is better)
      */
-    SAEVRouteChangelist tryAddRequest(int requestIdx, int originRequestPredecessorIdx, int destinationRequestPredecessorIdx);
+    SAEVRouteChangelist tryAddRequest(const int requestIdx, const int originRequestPredecessorIdx, const int destinationRequestPredecessorIdx);
 
     /**
      * Method called after having validated conditions not requiring request insertion. \n
@@ -56,11 +56,11 @@ public:
      * If the bounds become infeasible (min > max), then the propagation stops with a changelist with score= +Infinity and changes will be immediately reverted.
      * Otherwise, it's the responsibility of this method's callers to revert changes if wanted (or to defer this responsibility to its caller)
      * @param requestIdx Identifier/index in the instance's request vector for the request we wish to insert
-     * @param originRequestPredecessorIdx Identifier/index in the instance's request vector for the request that will precede our request's origin in the route
-     * @param destinationRequestPredecessorIdx Identifier/index in the instance's request vector for the request that will precede our request's destination in the route
+     * @param originRequestPredecessorIdx Identifier/index in the route key point vector for the request origin or destination that will precede our request's origin in the route
+     * @param destinationRequestPredecessorIdx Identifier/index in the route key point vector for the request origin or destination that will precede our request's destination in the route
      * @return A change list with every min/max bound change made during the insert procedure and a score estimating insertion quality (lower is better)
      */
-    SAEVRouteChangelist insertRequestWithPropagation(int requestIdx, int originRequestPredecessorIdx, int destinationRequestPredecessorIdx);
+    SAEVRouteChangelist insertRequestWithPropagation(const int requestIdx, const int originRequestPredecessorIdx, const int destinationRequestPredecessorIdx);
 
     /**
      * Raw request removal method. Public for debug purposes, but should effectively never be called by an outside member FIXME:make private
-- 
GitLab


From 110211f5ab250ad472ee6ab5910e4448e8e077b8 Mon Sep 17 00:00:00 2001
From: Romain BERNARD <romain.bernard@uca.fr>
Date: Thu, 25 Apr 2024 19:07:01 +0200
Subject: [PATCH 034/327] fix cyclic dep compilation

---
 src/routes/RequestRoute.h      | 2 ++
 src/routes/vehicle/SAEVRoute.h | 3 ++-
 2 files changed, 4 insertions(+), 1 deletion(-)

diff --git a/src/routes/RequestRoute.h b/src/routes/RequestRoute.h
index e003dd1..5c01c47 100644
--- a/src/routes/RequestRoute.h
+++ b/src/routes/RequestRoute.h
@@ -8,6 +8,7 @@
 
 #include "RequestKeyPoint.h"
 
+class Request;
 class RequestRoute {
 public:
     enum RouteStructureEnum {
@@ -40,5 +41,6 @@ public:
     void resetKeyPoint(int routeIndex);
 };
 
+#include "../instance/requests/Request.h"
 
 #endif //GREEDYALGORITHM_REQUESTROUTE_H
diff --git a/src/routes/vehicle/SAEVRoute.h b/src/routes/vehicle/SAEVRoute.h
index 752cd5c..f8228b9 100644
--- a/src/routes/vehicle/SAEVRoute.h
+++ b/src/routes/vehicle/SAEVRoute.h
@@ -8,8 +8,8 @@
 
 #include <vector>
 #include "SAEVKeyPoint.h"
-#include "propagation/SAEVRouteChangelist.h"
 
+class SAEVRouteChangelist;
 class SAEVRoute {
 private:
     std::vector<SAEVKeyPoint> _route;
@@ -69,5 +69,6 @@ public:
     void removeRequest(int requestIdx);
 };
 
+#include "propagation/SAEVRouteChangelist.h"
 
 #endif //GREEDYALGORITHM_SAEVROUTE_H
-- 
GitLab


From 1b48e230a16fd24806061e8760394aade8edcc56 Mon Sep 17 00:00:00 2001
From: Romain BERNARD <romain.bernard@uca.fr>
Date: Thu, 25 Apr 2024 19:07:22 +0200
Subject: [PATCH 035/327] WIP propagation implementation

---
 src/routes/vehicle/SAEVRoute.cpp | 21 +++++++++++++++++++++
 1 file changed, 21 insertions(+)

diff --git a/src/routes/vehicle/SAEVRoute.cpp b/src/routes/vehicle/SAEVRoute.cpp
index 0aeb90e..2ac4e4c 100644
--- a/src/routes/vehicle/SAEVRoute.cpp
+++ b/src/routes/vehicle/SAEVRoute.cpp
@@ -67,4 +67,25 @@ void SAEVRoute::removeRequest(int requestIdx) {
     destinationKp.setMaxTw(_requestList->at(requestIdx).getMaxArrivalTw());
 }
 
+SAEVRouteChangelist
+SAEVRoute::tryAddRequest(const int requestIdx, const int originRequestPredecessorIdx, const int destinationRequestPredecessorIdx) {
+    bool isFeasible = true;
+    SAEVKeyPoint originPredecessor = _route.at(originRequestPredecessorIdx);
+    SAEVKeyPoint destinationPredecessor = _route.at(destinationRequestPredecessorIdx);
+    if(true) {
+
+    }
+
+    if (isFeasible) {
+        return insertRequestWithPropagation(requestIdx, originRequestPredecessorIdx,destinationRequestPredecessorIdx);
+    } else {
+        return SAEVRouteChangelist(this, requestIdx, originRequestPredecessorIdx, destinationRequestPredecessorIdx);
+    }
+}
+
+SAEVRouteChangelist SAEVRoute::insertRequestWithPropagation(const int requestIdx, const int originRequestPredecessorIdx,
+                                                            const int destinationRequestPredecessorIdx) {
+    return SAEVRouteChangelist(nullptr, 0, 0, 0);
+}
+
 
-- 
GitLab


From 4dac9ddd2327cd9a6702cb469599582a79355af2 Mon Sep 17 00:00:00 2001
From: Romain BERNARD <romain.bernard@uca.fr>
Date: Fri, 26 Apr 2024 16:45:07 +0200
Subject: [PATCH 036/327] add node index in instanciation

---
 src/routes/vehicle/SAEVKeyPoint.cpp | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/src/routes/vehicle/SAEVKeyPoint.cpp b/src/routes/vehicle/SAEVKeyPoint.cpp
index 8832338..491b17f 100644
--- a/src/routes/vehicle/SAEVKeyPoint.cpp
+++ b/src/routes/vehicle/SAEVKeyPoint.cpp
@@ -50,9 +50,11 @@ void SAEVKeyPoint::setMaxTw(int maxTw) {
 
 SAEVKeyPoint::SAEVKeyPoint(const Graph &graph, const Request &request, bool isEntry) {
     if(isEntry) {
+        _nodeIndex = request.getDepartureNodeIndex();
         _minTW = request.getArrivalTw().min - request.getDeltaTime();
         _maxTW = request.getArrivalTw().max - graph.getShortestSAEVPath(request.getDepartureNodeIndex(), request.getArrivalNodeIndex());
     } else {
+        _nodeIndex = request.getArrivalNodeIndex();
         _minTW = request.getArrivalTw().min;
         _maxTW = request.getArrivalTw().max;
     }
-- 
GitLab


From d8cf3052bb33dfce2d105edc142bc595664d2d0a Mon Sep 17 00:00:00 2001
From: Romain BERNARD <romain.bernard@uca.fr>
Date: Fri, 26 Apr 2024 16:45:42 +0200
Subject: [PATCH 037/327] sonarlint issues

---
 src/instance/graph/Graph.h          | 6 +++---
 src/routes/KeyPoint.h               | 4 ++--
 src/routes/vehicle/SAEVKeyPoint.cpp | 9 ++-------
 src/routes/vehicle/SAEVKeyPoint.h   | 9 ++++-----
 4 files changed, 11 insertions(+), 17 deletions(-)

diff --git a/src/instance/graph/Graph.h b/src/instance/graph/Graph.h
index aaf310c..634a334 100644
--- a/src/instance/graph/Graph.h
+++ b/src/instance/graph/Graph.h
@@ -87,7 +87,7 @@ public:
      * @param edge The edge to push in the graph's edge vector
      * @return The edge vector after having added the edge
      */
-    std::vector<Edge> addEdge(Edge& edge) {
+    std::vector<Edge> addEdge(Edge const& edge) {
         edgesVector.push_back(edge);
         return edgesVector;
     }
@@ -97,7 +97,7 @@ public:
      * @param node The node to push in the graph's node vector
      * @return The node vector after having added the node
      */
-    std::vector<Node> addNode(Node& node) {
+    std::vector<Node> addNode(Node const& node) {
         nodesVector.push_back(node);
         return nodesVector;
     }
@@ -146,7 +146,7 @@ public:
      */
     void createAndAddEdge(int edgeStartNodeIndex, int edgeEndNodeIndex, double length);
 
-    int getShortestSAEVPath(int x, int y) const { return shortestSAEVPaths.at(x).at(y); }
+    [[nodiscard]] int getShortestSAEVPath(int x, int y) const { return shortestSAEVPaths.at(x).at(y); }
 };
 
 
diff --git a/src/routes/KeyPoint.h b/src/routes/KeyPoint.h
index f808bad..3f4dc7f 100644
--- a/src/routes/KeyPoint.h
+++ b/src/routes/KeyPoint.h
@@ -9,7 +9,7 @@
 #include "../TimeWindow.h"
 
 class KeyPoint {
-protected:
+private:
     int _nodeIndex{-1};
 
 public:
@@ -21,7 +21,7 @@ public:
 
     [[nodiscard]] virtual bool check() const { return true; };
 
-    ~KeyPoint() = default;
+    virtual ~KeyPoint() = default;
 };
 
 
diff --git a/src/routes/vehicle/SAEVKeyPoint.cpp b/src/routes/vehicle/SAEVKeyPoint.cpp
index 491b17f..c8861c7 100644
--- a/src/routes/vehicle/SAEVKeyPoint.cpp
+++ b/src/routes/vehicle/SAEVKeyPoint.cpp
@@ -50,17 +50,12 @@ void SAEVKeyPoint::setMaxTw(int maxTw) {
 
 SAEVKeyPoint::SAEVKeyPoint(const Graph &graph, const Request &request, bool isEntry) {
     if(isEntry) {
-        _nodeIndex = request.getDepartureNodeIndex();
+        setNodeIndex(request.getDepartureNodeIndex());
         _minTW = request.getArrivalTw().min - request.getDeltaTime();
         _maxTW = request.getArrivalTw().max - graph.getShortestSAEVPath(request.getDepartureNodeIndex(), request.getArrivalNodeIndex());
     } else {
-        _nodeIndex = request.getArrivalNodeIndex();
+        setNodeIndex(request.getArrivalNodeIndex());
         _minTW = request.getArrivalTw().min;
         _maxTW = request.getArrivalTw().max;
     }
 }
-
-SAEVKeyPoint::SAEVKeyPoint() {
-    _minTW = 0;
-    _maxTW = INT16_MAX;
-}
diff --git a/src/routes/vehicle/SAEVKeyPoint.h b/src/routes/vehicle/SAEVKeyPoint.h
index 6c8c9f6..30c1ae0 100644
--- a/src/routes/vehicle/SAEVKeyPoint.h
+++ b/src/routes/vehicle/SAEVKeyPoint.h
@@ -10,20 +10,19 @@
 #include "../KeyPoint.h"
 #include "../../instance/graph/Graph.h"
 
-class SAEVKeyPoint : public virtual KeyPoint {
+class SAEVKeyPoint : public KeyPoint {
 private:
     SAEVKeyPoint* _predecessor{nullptr};
     SAEVKeyPoint* _successor{nullptr};
     int _currentOccupation{0};
     int _minTW{0};
-    int _maxTW{0};
+    int _maxTW{INT16_MAX};
     SAEVehicle* _vehiclePointer{};
-
 public:
     /**
      * Depot KP initialization with [0;max] time windows
      */
-    SAEVKeyPoint();
+    SAEVKeyPoint() = default;
     /**
      * SAEV KP initialization
      * @param graph the instance's graph, used to get shortest path and estimate start time windows relative to distances
@@ -49,7 +48,7 @@ public:
 
     [[nodiscard]] bool check() const override;
 
-    ~SAEVKeyPoint() = default;
+    ~SAEVKeyPoint() override = default;
 };
 
 
-- 
GitLab


From 849674cada3413ca68510812cd6d1e7af4bfa946 Mon Sep 17 00:00:00 2001
From: Romain BERNARD <romain.bernard@uca.fr>
Date: Fri, 26 Apr 2024 18:49:12 +0200
Subject: [PATCH 038/327] implement neighbouring time windows checks (TODO :
 constraint propagation)

---
 src/routes/vehicle/SAEVKeyPoint.cpp |  4 +-
 src/routes/vehicle/SAEVKeyPoint.h   |  4 +-
 src/routes/vehicle/SAEVRoute.cpp    | 77 +++++++++++++++++++++++++----
 src/routes/vehicle/SAEVRoute.h      | 17 ++++---
 4 files changed, 81 insertions(+), 21 deletions(-)

diff --git a/src/routes/vehicle/SAEVKeyPoint.cpp b/src/routes/vehicle/SAEVKeyPoint.cpp
index c8861c7..5434f35 100644
--- a/src/routes/vehicle/SAEVKeyPoint.cpp
+++ b/src/routes/vehicle/SAEVKeyPoint.cpp
@@ -24,11 +24,11 @@ void SAEVKeyPoint::setSuccessor(SAEVKeyPoint *successor) {
     _successor = successor;
 }
 
-int SAEVKeyPoint::getCurrentCapacity() const {
+int SAEVKeyPoint::getCurrentOccupation() const {
     return _currentOccupation;
 }
 
-void SAEVKeyPoint::setCurrentCapacity(int currentCapacity) {
+void SAEVKeyPoint::setCurrentOccupation(int currentCapacity) {
     _currentOccupation = currentCapacity;
 }
 
diff --git a/src/routes/vehicle/SAEVKeyPoint.h b/src/routes/vehicle/SAEVKeyPoint.h
index 30c1ae0..7443250 100644
--- a/src/routes/vehicle/SAEVKeyPoint.h
+++ b/src/routes/vehicle/SAEVKeyPoint.h
@@ -37,8 +37,8 @@ public:
     [[nodiscard]] SAEVKeyPoint *getSuccessor() const;
     void setSuccessor(SAEVKeyPoint *successor);
 
-    [[nodiscard]] int getCurrentCapacity() const;
-    void setCurrentCapacity(int currentCapacity);
+    [[nodiscard]] int getCurrentOccupation() const;
+    void setCurrentOccupation(int currentCapacity);
 
     [[nodiscard]] int getMinTw() const;
     void setMinTw(int minTw);
diff --git a/src/routes/vehicle/SAEVRoute.cpp b/src/routes/vehicle/SAEVRoute.cpp
index 2ac4e4c..396d203 100644
--- a/src/routes/vehicle/SAEVRoute.cpp
+++ b/src/routes/vehicle/SAEVRoute.cpp
@@ -69,18 +69,27 @@ void SAEVRoute::removeRequest(int requestIdx) {
 
 SAEVRouteChangelist
 SAEVRoute::tryAddRequest(const int requestIdx, const int originRequestPredecessorIdx, const int destinationRequestPredecessorIdx) {
-    bool isFeasible = true;
-    SAEVKeyPoint originPredecessor = _route.at(originRequestPredecessorIdx);
-    SAEVKeyPoint destinationPredecessor = _route.at(destinationRequestPredecessorIdx);
-    if(true) {
-
-    }
-
-    if (isFeasible) {
+    const Request* request = &_requestList->at(requestIdx);
+    SAEVKeyPoint const* originPredecessor = &_route.at(originRequestPredecessorIdx);
+    SAEVKeyPoint const* destinationPredecessor = &_route.at(destinationRequestPredecessorIdx);
+
+    //Check vehicle capacity
+    SAEVKeyPoint const* currentKP = originPredecessor;
+    do {
+        if(currentKP->getCurrentOccupation() + request->getWeight() > SAEVehicle::getCapacity()) {
+            return SAEVRouteChangelist(this, requestIdx, originRequestPredecessorIdx, destinationRequestPredecessorIdx);
+        }
+        currentKP = currentKP->getSuccessor();
+    } while (currentKP != destinationPredecessor && currentKP != nullptr);
+
+    //Do basic checks on neighbouring nodes from our Origin/Destination insertion points
+    bool isValid = doNeighbouringTWChecks(requestIdx, request, originPredecessor, destinationPredecessor);
+
+    if(isValid)
         return insertRequestWithPropagation(requestIdx, originRequestPredecessorIdx,destinationRequestPredecessorIdx);
-    } else {
+    else
         return SAEVRouteChangelist(this, requestIdx, originRequestPredecessorIdx, destinationRequestPredecessorIdx);
-    }
+
 }
 
 SAEVRouteChangelist SAEVRoute::insertRequestWithPropagation(const int requestIdx, const int originRequestPredecessorIdx,
@@ -88,4 +97,52 @@ SAEVRouteChangelist SAEVRoute::insertRequestWithPropagation(const int requestIdx
     return SAEVRouteChangelist(nullptr, 0, 0, 0);
 }
 
+bool
+SAEVRoute::doNeighbouringTWChecks(const int requestIdx,  const Request* request,
+                                  const SAEVKeyPoint *originPredecessor, const SAEVKeyPoint *destinationPredecessor) {
+
+    SAEVKeyPoint const* originKP = &_route.at(requestIdx);
+    SAEVKeyPoint const* destinationKP = &_route.at(requestIdx + 1);
+    SAEVKeyPoint const* originSuccessor = originPredecessor->getSuccessor();
+
+    if(originPredecessor != destinationPredecessor)
+    {
+
+        SAEVKeyPoint const* destinationSuccessor = destinationPredecessor->getSuccessor();
+
+        //Tests time windows Origin (yes this if-else could be one giant OR, but I'd rather separate every case)
+        int predOriginTimeWindow = originPredecessor->getMinTw() + _graph->getShortestSAEVPath(originPredecessor->getNodeIndex(), request->getDepartureNodeIndex());
+        int predDestinationTimeWindow = destinationPredecessor->getMinTw() + _graph->getShortestSAEVPath(destinationPredecessor->getNodeIndex(), request->getArrivalNodeIndex());
+        if(predOriginTimeWindow > originKP->getMaxTw())
+            return false;
+        else if(originKP->getMinTw() + _graph->getShortestSAEVPath(originKP->getNodeIndex(), originSuccessor->getNodeIndex()) > originSuccessor->getMaxTw()) // Could be removed ?
+            return false;
+        else if(predOriginTimeWindow + _graph->getShortestSAEVPath(originKP->getNodeIndex(), originSuccessor->getNodeIndex()) > originSuccessor->getMaxTw())
+            return false;
+        //Tests time windows Destination
+        else if(predDestinationTimeWindow > destinationKP->getMaxTw())
+            return false;
+        else if(destinationKP->getMinTw() + _graph->getShortestSAEVPath(destinationKP->getNodeIndex(), destinationSuccessor->getNodeIndex()) > destinationSuccessor->getMaxTw()) //could be removed ?
+            return false;
+        else if(predOriginTimeWindow + _graph->getShortestSAEVPath(destinationKP->getNodeIndex(), destinationSuccessor->getNodeIndex()) > destinationSuccessor->getMaxTw())
+            return false;
+    } else {
+        int predMinTWToOrigin = originPredecessor->getMinTw() + _graph->getShortestSAEVPath(originPredecessor->getNodeIndex(), request->getDepartureNodeIndex());
+        int predMinTWToDest = predMinTWToOrigin + _graph->getShortestSAEVPath(request->getDepartureNodeIndex(), request->getArrivalNodeIndex());
+        if(predMinTWToOrigin > originKP->getMaxTw()) //Path from pred to O
+            return false;
+        else if(predMinTWToDest > destinationKP->getMaxTw()) //Path from pred to D
+            return false;
+        else if(predMinTWToDest + _graph->getShortestSAEVPath(request->getArrivalNodeIndex(), originSuccessor->getNodeIndex()) > originSuccessor->getMaxTw()) //Path from pred to successor
+            return false;
+        else if(originSuccessor->getMinTw() + _graph->getShortestSAEVPath(request->getArrivalNodeIndex(), originSuccessor->getNodeIndex()) > originSuccessor->getMaxTw()) //Path from D to successor
+            return false;
+        else if(originKP->getMinTw() + _graph->getShortestSAEVPath(request->getDepartureNodeIndex(), request->getArrivalNodeIndex()) //Path from O to successor
+        + _graph->getShortestSAEVPath(request->getArrivalNodeIndex(), originSuccessor->getNodeIndex()) > originSuccessor->getMaxTw())
+            return false;
+    }
+
+    return true;
+}
+
 
diff --git a/src/routes/vehicle/SAEVRoute.h b/src/routes/vehicle/SAEVRoute.h
index f8228b9..d98c54a 100644
--- a/src/routes/vehicle/SAEVRoute.h
+++ b/src/routes/vehicle/SAEVRoute.h
@@ -31,13 +31,22 @@ public:
     }
 
     /**
-     * Raw request route insertion method. Public for debug purposes, but should effectively never be called by an outside member FIXME:make private
+     * Raw request route insertion method. Public for debug purposes, but should effectively never be called by an outside member
      * @param requestIdx index of the request we want to insert in the route
      * @param originRequestPredecessorIdx Identifier/index in the route key point vector for the request origin or destination that will precede the origin of the request we want to insert
      * @param destinationRequestPredecessorIdx Identifier/index in the route key point vector for the request origin or destination that will precede the destination of the request we want to insert
      */
     void insertRequest(int requestIdx, int originRequestPredecessorIdx, int destinationRequestPredecessorIdx);
 
+    /**
+     * Raw request removal method. Public for debug purposes, but should effectively never be called by an outside member
+     * @param requestIdx index of the request we want to remove from the route
+     */
+    void removeRequest(int requestIdx);
+
+    bool doNeighbouringTWChecks(const int requestIdx, const Request* request, const SAEVKeyPoint *originPredecessor,
+                                const SAEVKeyPoint *destinationPredecessor);
+
     /**
      * Tries to insert the request origin and destination next to the given origin/destination predecessors. \n \n
      * First we verify multiple constraints that don't require actually inserting the request or doing constraint propagation. \n
@@ -61,12 +70,6 @@ public:
      * @return A change list with every min/max bound change made during the insert procedure and a score estimating insertion quality (lower is better)
      */
     SAEVRouteChangelist insertRequestWithPropagation(const int requestIdx, const int originRequestPredecessorIdx, const int destinationRequestPredecessorIdx);
-
-    /**
-     * Raw request removal method. Public for debug purposes, but should effectively never be called by an outside member FIXME:make private
-     * @param requestIdx index of the request we want to remove from the route
-     */
-    void removeRequest(int requestIdx);
 };
 
 #include "propagation/SAEVRouteChangelist.h"
-- 
GitLab


From 4f23986b83e82358a9b435a00adb20fa1efbdb51 Mon Sep 17 00:00:00 2001
From: Romain BERNARD <romain.bernard@uca.fr>
Date: Mon, 29 Apr 2024 10:41:18 +0200
Subject: [PATCH 039/327] refactor departure->origin and arrival->destination

---
 src/instance/requests/Request.cpp   | 16 ++++++++--------
 src/instance/requests/Request.h     |  8 ++++----
 src/routes/vehicle/SAEVKeyPoint.cpp |  7 ++++---
 3 files changed, 16 insertions(+), 15 deletions(-)

diff --git a/src/instance/requests/Request.cpp b/src/instance/requests/Request.cpp
index 5c1d1b0..6f6b60a 100644
--- a/src/instance/requests/Request.cpp
+++ b/src/instance/requests/Request.cpp
@@ -5,8 +5,8 @@
 #include "Request.h"
 
 Request::Request(const int departureNodeIndex, const int arrivalNodeIndex, const TimeWindow &arrivalTw,
-                 const int deltaTime, const int weight) : _departureNodeIndex(departureNodeIndex),
-                                                          _arrivalNodeIndex(arrivalNodeIndex), _arrivalTW(arrivalTw),
+                 const int deltaTime, const int weight) : _originNodeIndex(departureNodeIndex),
+                                                          _destinationNodeIndex(arrivalNodeIndex), _arrivalTW(arrivalTw),
                                                           _deltaTime(deltaTime), _weight(weight) {
     _currentDeltaTime = deltaTime;
     _departureTW = _arrivalTW - deltaTime;
@@ -14,19 +14,19 @@ Request::Request(const int departureNodeIndex, const int arrivalNodeIndex, const
 
 Request::Request(const int departureNodeIndex, const int arrivalNodeIndex, const TimeWindow &arrivalTw,
                  const int deltaTime, const int weight, const Graph& graph) :
-                 _departureNodeIndex(departureNodeIndex),_arrivalNodeIndex(arrivalNodeIndex),
-                 _arrivalTW(arrivalTw),_deltaTime(deltaTime), _weight(weight) {
+        _originNodeIndex(departureNodeIndex), _destinationNodeIndex(arrivalNodeIndex),
+        _arrivalTW(arrivalTw), _deltaTime(deltaTime), _weight(weight) {
     _currentDeltaTime = deltaTime;
     _departureTW.min = _arrivalTW.min - deltaTime;
     _departureTW.max = _arrivalTW.max - graph.getShortestSAEVPath(departureNodeIndex, arrivalNodeIndex);
 }
 
-const int Request::getDepartureNodeIndex() const {
-    return _departureNodeIndex;
+const int Request::getOriginNodeIndex() const {
+    return _originNodeIndex;
 }
 
-const int Request::getArrivalNodeIndex() const {
-    return _arrivalNodeIndex;
+const int Request::getDestinationNodeIndex() const {
+    return _destinationNodeIndex;
 }
 
 const TimeWindow &Request::getArrivalTw() const {
diff --git a/src/instance/requests/Request.h b/src/instance/requests/Request.h
index 04440a1..b6f1fbe 100644
--- a/src/instance/requests/Request.h
+++ b/src/instance/requests/Request.h
@@ -13,8 +13,8 @@
 class Request {
 private:
     //Request base members (const and initialized on _request creation)
-    const int _departureNodeIndex; //Starting point of the user _request //TODO (?) change this to a Node pointer eventually
-    const int _arrivalNodeIndex; //
+    const int _originNodeIndex; //Starting point of the user _request //TODO (?) change this to a Node pointer eventually
+    const int _destinationNodeIndex; //
     const TimeWindow _arrivalTW; //[min,max] time window for arrival to the destination node
     const int _deltaTime; //Base delta time, aka the maximum total duration of the path to serve this _request
     const int _weight; //How much space the requests takes in the vehicle (defaults to 1)
@@ -32,8 +32,8 @@ public:
             const int deltaTime, const int weight, const Graph& graph);
 
     //Getters
-    [[nodiscard]] const int getDepartureNodeIndex() const;
-    [[nodiscard]] const int getArrivalNodeIndex() const;
+    [[nodiscard]] const int getOriginNodeIndex() const;
+    [[nodiscard]] const int getDestinationNodeIndex() const;
     [[nodiscard]] const TimeWindow &getArrivalTw() const;
     [[nodiscard]] const int getDeltaTime() const;
     [[nodiscard]] const int getWeight() const;
diff --git a/src/routes/vehicle/SAEVKeyPoint.cpp b/src/routes/vehicle/SAEVKeyPoint.cpp
index 5434f35..136e34f 100644
--- a/src/routes/vehicle/SAEVKeyPoint.cpp
+++ b/src/routes/vehicle/SAEVKeyPoint.cpp
@@ -50,11 +50,12 @@ void SAEVKeyPoint::setMaxTw(int maxTw) {
 
 SAEVKeyPoint::SAEVKeyPoint(const Graph &graph, const Request &request, bool isEntry) {
     if(isEntry) {
-        setNodeIndex(request.getDepartureNodeIndex());
+        setNodeIndex(request.getOriginNodeIndex());
         _minTW = request.getArrivalTw().min - request.getDeltaTime();
-        _maxTW = request.getArrivalTw().max - graph.getShortestSAEVPath(request.getDepartureNodeIndex(), request.getArrivalNodeIndex());
+        _maxTW = request.getArrivalTw().max - graph.getShortestSAEVPath(request.getOriginNodeIndex(),
+                                                                        request.getDestinationNodeIndex());
     } else {
-        setNodeIndex(request.getArrivalNodeIndex());
+        setNodeIndex(request.getDestinationNodeIndex());
         _minTW = request.getArrivalTw().min;
         _maxTW = request.getArrivalTw().max;
     }
-- 
GitLab


From 132e9ef4e8906083cd9a32011c4bf1e9cc976175 Mon Sep 17 00:00:00 2001
From: Romain BERNARD <romain.bernard@uca.fr>
Date: Mon, 29 Apr 2024 11:04:15 +0200
Subject: [PATCH 040/327] refactor departure->origin and arrival->destination +
 doc

---
 src/routes/vehicle/SAEVRoute.cpp | 33 +++++++++++++++-----------------
 src/routes/vehicle/SAEVRoute.h   | 18 ++++++++++++++---
 2 files changed, 30 insertions(+), 21 deletions(-)

diff --git a/src/routes/vehicle/SAEVRoute.cpp b/src/routes/vehicle/SAEVRoute.cpp
index 396d203..deac672 100644
--- a/src/routes/vehicle/SAEVRoute.cpp
+++ b/src/routes/vehicle/SAEVRoute.cpp
@@ -83,7 +83,7 @@ SAEVRoute::tryAddRequest(const int requestIdx, const int originRequestPredecesso
     } while (currentKP != destinationPredecessor && currentKP != nullptr);
 
     //Do basic checks on neighbouring nodes from our Origin/Destination insertion points
-    bool isValid = doNeighbouringTWChecks(requestIdx, request, originPredecessor, destinationPredecessor);
+    bool isValid = doNeighbouringTWChecks(requestIdx, request->getOriginNodeIndex(), request->getDestinationNodeIndex(), originPredecessor, destinationPredecessor);
 
     if(isValid)
         return insertRequestWithPropagation(requestIdx, originRequestPredecessorIdx,destinationRequestPredecessorIdx);
@@ -92,13 +92,8 @@ SAEVRoute::tryAddRequest(const int requestIdx, const int originRequestPredecesso
 
 }
 
-SAEVRouteChangelist SAEVRoute::insertRequestWithPropagation(const int requestIdx, const int originRequestPredecessorIdx,
-                                                            const int destinationRequestPredecessorIdx) {
-    return SAEVRouteChangelist(nullptr, 0, 0, 0);
-}
-
 bool
-SAEVRoute::doNeighbouringTWChecks(const int requestIdx,  const Request* request,
+SAEVRoute::doNeighbouringTWChecks(const int requestIdx, const int originNodeIndex, const int destinationNodeIndex,
                                   const SAEVKeyPoint *originPredecessor, const SAEVKeyPoint *destinationPredecessor) {
 
     SAEVKeyPoint const* originKP = &_route.at(requestIdx);
@@ -107,12 +102,11 @@ SAEVRoute::doNeighbouringTWChecks(const int requestIdx,  const Request* request,
 
     if(originPredecessor != destinationPredecessor)
     {
-
         SAEVKeyPoint const* destinationSuccessor = destinationPredecessor->getSuccessor();
 
         //Tests time windows Origin (yes this if-else could be one giant OR, but I'd rather separate every case)
-        int predOriginTimeWindow = originPredecessor->getMinTw() + _graph->getShortestSAEVPath(originPredecessor->getNodeIndex(), request->getDepartureNodeIndex());
-        int predDestinationTimeWindow = destinationPredecessor->getMinTw() + _graph->getShortestSAEVPath(destinationPredecessor->getNodeIndex(), request->getArrivalNodeIndex());
+        int predOriginTimeWindow = originPredecessor->getMinTw() + _graph->getShortestSAEVPath(originPredecessor->getNodeIndex(), originNodeIndex);
+        int predDestinationTimeWindow = destinationPredecessor->getMinTw() + _graph->getShortestSAEVPath(destinationPredecessor->getNodeIndex(), destinationNodeIndex);
         if(predOriginTimeWindow > originKP->getMaxTw())
             return false;
         else if(originKP->getMinTw() + _graph->getShortestSAEVPath(originKP->getNodeIndex(), originSuccessor->getNodeIndex()) > originSuccessor->getMaxTw()) // Could be removed ?
@@ -126,23 +120,26 @@ SAEVRoute::doNeighbouringTWChecks(const int requestIdx,  const Request* request,
             return false;
         else if(predOriginTimeWindow + _graph->getShortestSAEVPath(destinationKP->getNodeIndex(), destinationSuccessor->getNodeIndex()) > destinationSuccessor->getMaxTw())
             return false;
-    } else {
-        int predMinTWToOrigin = originPredecessor->getMinTw() + _graph->getShortestSAEVPath(originPredecessor->getNodeIndex(), request->getDepartureNodeIndex());
-        int predMinTWToDest = predMinTWToOrigin + _graph->getShortestSAEVPath(request->getDepartureNodeIndex(), request->getArrivalNodeIndex());
+    } else { //We need a specific case if origin and destination are inserted after the same node
+        int predMinTWToOrigin = originPredecessor->getMinTw() + _graph->getShortestSAEVPath(originPredecessor->getNodeIndex(), originNodeIndex);
+        int predMinTWToDest = predMinTWToOrigin + _graph->getShortestSAEVPath(originNodeIndex, destinationNodeIndex);
         if(predMinTWToOrigin > originKP->getMaxTw()) //Path from pred to O
             return false;
         else if(predMinTWToDest > destinationKP->getMaxTw()) //Path from pred to D
             return false;
-        else if(predMinTWToDest + _graph->getShortestSAEVPath(request->getArrivalNodeIndex(), originSuccessor->getNodeIndex()) > originSuccessor->getMaxTw()) //Path from pred to successor
+        else if(predMinTWToDest + _graph->getShortestSAEVPath(destinationNodeIndex, originSuccessor->getNodeIndex()) > originSuccessor->getMaxTw()) //Path from pred to successor
             return false;
-        else if(originSuccessor->getMinTw() + _graph->getShortestSAEVPath(request->getArrivalNodeIndex(), originSuccessor->getNodeIndex()) > originSuccessor->getMaxTw()) //Path from D to successor
+        else if(originSuccessor->getMinTw() + _graph->getShortestSAEVPath(destinationNodeIndex, originSuccessor->getNodeIndex()) > originSuccessor->getMaxTw()) //Path from D to successor
             return false;
-        else if(originKP->getMinTw() + _graph->getShortestSAEVPath(request->getDepartureNodeIndex(), request->getArrivalNodeIndex()) //Path from O to successor
-        + _graph->getShortestSAEVPath(request->getArrivalNodeIndex(), originSuccessor->getNodeIndex()) > originSuccessor->getMaxTw())
+        else if(originKP->getMinTw() + _graph->getShortestSAEVPath(originNodeIndex, destinationNodeIndex) //Path from O to successor
+        + _graph->getShortestSAEVPath(destinationNodeIndex, originSuccessor->getNodeIndex()) > originSuccessor->getMaxTw())
             return false;
     }
 
     return true;
 }
 
-
+SAEVRouteChangelist SAEVRoute::insertRequestWithPropagation(const int requestIdx, const int originRequestPredecessorIdx,
+                                                            const int destinationRequestPredecessorIdx) {
+    return SAEVRouteChangelist(nullptr, 0, 0, 0);
+}
diff --git a/src/routes/vehicle/SAEVRoute.h b/src/routes/vehicle/SAEVRoute.h
index d98c54a..38437d6 100644
--- a/src/routes/vehicle/SAEVRoute.h
+++ b/src/routes/vehicle/SAEVRoute.h
@@ -44,9 +44,6 @@ public:
      */
     void removeRequest(int requestIdx);
 
-    bool doNeighbouringTWChecks(const int requestIdx, const Request* request, const SAEVKeyPoint *originPredecessor,
-                                const SAEVKeyPoint *destinationPredecessor);
-
     /**
      * Tries to insert the request origin and destination next to the given origin/destination predecessors. \n \n
      * First we verify multiple constraints that don't require actually inserting the request or doing constraint propagation. \n
@@ -59,6 +56,21 @@ public:
      */
     SAEVRouteChangelist tryAddRequest(const int requestIdx, const int originRequestPredecessorIdx, const int destinationRequestPredecessorIdx);
 
+    /**
+     * Verifies time window constraints on our request's origin/destination's projected neighbour, aka originPredecessor/destinationPredecessor and their successor.
+     * There is a special case taken into account if originPredecessor and destinationPredecessor are the same KeyPoint, since then, Origin's successor would be Destination
+     * ⚠️ Weight constraints are checked separately
+     * ⚠️ Those checks don't modify the route => no rollback is needed at this point
+     * @param requestIdx Index of our request, necessary to retrieve the appropriate key points
+     * @param originNodeIndex The request's origin node index, necessary to compute travel times
+     * @param destinationNodeIndex The request's destination node index, necessary to compute travel times
+     * @param originPredecessor The origin's expected predecessor, aka the point after which we wish to insert our origin
+     * @param destinationPredecessor The destination's expected predecessor, aka the point after which we wish to insert our destination
+     * @return true iff all neighbouring time window conditions are valid at our insertion points, false otherwise
+     */
+    bool doNeighbouringTWChecks(const int requestIdx, const int originNodeIndex, const int destinationNodeIndex,
+                                const SAEVKeyPoint *originPredecessor, const SAEVKeyPoint *destinationPredecessor);
+
     /**
      * Method called after having validated conditions not requiring request insertion. \n
      * This will effectively insert our procedure and ripple through bound changes. \n
-- 
GitLab


From bd8c5b6e60e130088e679a6d638ba2937f7757cb Mon Sep 17 00:00:00 2001
From: Romain BERNARD <romain.bernard@uca.fr>
Date: Mon, 29 Apr 2024 14:26:03 +0200
Subject: [PATCH 041/327] refactor departure->origin and arrival->destination

---
 .../vehicle/propagation/SAEVRouteChangelist.cpp    | 10 +++++-----
 .../vehicle/propagation/SAEVRouteChangelist.h      | 14 +++++++-------
 2 files changed, 12 insertions(+), 12 deletions(-)

diff --git a/src/routes/vehicle/propagation/SAEVRouteChangelist.cpp b/src/routes/vehicle/propagation/SAEVRouteChangelist.cpp
index 2269ad7..6e2b333 100644
--- a/src/routes/vehicle/propagation/SAEVRouteChangelist.cpp
+++ b/src/routes/vehicle/propagation/SAEVRouteChangelist.cpp
@@ -21,7 +21,7 @@ void SAEVRouteChangelist::emplace_back(SAEVKeyPoint &kp, Bound bound, int value)
 }
 
 void SAEVRouteChangelist::applyChanges() const {
-    _routePtr->insertRequest(_requestIdx, _originIdx, _destinationIdx);
+    _routePtr->insertRequest(_requestIdx, _originPredecessorIdx, _destinationPredecessorIdx);
     for(SAEVRouteChange change : _changelist) {
         change.applyChange();
     }
@@ -40,12 +40,12 @@ int SAEVRouteChangelist::getRequestIdx() const {
     return _requestIdx;
 }
 
-int SAEVRouteChangelist::getOriginIdx() const {
-    return _originIdx;
+int SAEVRouteChangelist::getOriginPredecessorIdx() const {
+    return _originPredecessorIdx;
 }
 
-int SAEVRouteChangelist::getDestinationIdx() const {
-    return _destinationIdx;
+int SAEVRouteChangelist::getDestinationPredecessorIdx() const {
+    return _destinationPredecessorIdx;
 }
 
 double SAEVRouteChangelist::getScore() const {
diff --git a/src/routes/vehicle/propagation/SAEVRouteChangelist.h b/src/routes/vehicle/propagation/SAEVRouteChangelist.h
index a4d0251..f0be850 100644
--- a/src/routes/vehicle/propagation/SAEVRouteChangelist.h
+++ b/src/routes/vehicle/propagation/SAEVRouteChangelist.h
@@ -17,7 +17,7 @@
 class SAEVRouteChangelist {
 private:
     SAEVRoute * const _routePtr;
-    const int _requestIdx, _originIdx, _destinationIdx;
+    const int _requestIdx, _originPredecessorIdx, _destinationPredecessorIdx;
     std::vector<SAEVRouteChange> _changelist{};
     double _score{std::numeric_limits<double>::infinity()}; //Init score to infinity
 
@@ -26,11 +26,11 @@ public:
      * Initializes a change list to memorize every iterative modification made during constraint propagation
      * @param routePtr a pointer to the route the constraint propagation was applied on. revert/apply operations will be done on this route
      * @param requestIdx The index of the request in the global request list
-     * @param originIdx The index of the request our origin will be inserted after
-     * @param destinationIdx The index of the request our destination will be inserted after
+     * @param originPredecessorIdx The index of the request our origin will be inserted after
+     * @param destinationPredecessorIdx The index of the request our destination will be inserted after
      */
-    explicit SAEVRouteChangelist(SAEVRoute * const routePtr, const int requestIdx, const int originIdx, const int destinationIdx)
-    : _routePtr(routePtr), _requestIdx(requestIdx), _originIdx(originIdx), _destinationIdx(destinationIdx) {};
+    explicit SAEVRouteChangelist(SAEVRoute * const routePtr, const int requestIdx, const int originPredecessorIdx, const int destinationPredecessorIdx)
+    : _routePtr(routePtr), _requestIdx(requestIdx), _originPredecessorIdx(originPredecessorIdx), _destinationPredecessorIdx(destinationPredecessorIdx) {};
 
     /**
      * @return A pointer to the route this change list applies/reverts changes to
@@ -45,11 +45,11 @@ public:
     /**
      * @return The index of the request our origin will be inserted after
      */
-    [[nodiscard]] int getOriginIdx() const;
+    [[nodiscard]] int getOriginPredecessorIdx() const;
     /**
      * @return The index of the request our destination will be inserted after
      */
-    [[nodiscard]] int getDestinationIdx() const;
+    [[nodiscard]] int getDestinationPredecessorIdx() const;
     /**
      * @return A score value associated with this changelist. A lower score is better
      */
-- 
GitLab


From ffda2920332097e70881a49b3c1a094c909a43f4 Mon Sep 17 00:00:00 2001
From: Romain BERNARD <romain.bernard@uca.fr>
Date: Mon, 29 Apr 2024 19:34:08 +0200
Subject: [PATCH 042/327] refactor use centralised functions to get
 depots/request key points

---
 src/routes/vehicle/SAEVRoute.cpp | 31 ++++++++++++++-----------------
 src/routes/vehicle/SAEVRoute.h   |  6 ++++++
 2 files changed, 20 insertions(+), 17 deletions(-)

diff --git a/src/routes/vehicle/SAEVRoute.cpp b/src/routes/vehicle/SAEVRoute.cpp
index deac672..3be78e4 100644
--- a/src/routes/vehicle/SAEVRoute.cpp
+++ b/src/routes/vehicle/SAEVRoute.cpp
@@ -7,16 +7,13 @@
 SAEVRoute::SAEVRoute(const Graph& graph, const std::vector<Request>& requestList) : _nbRequest(requestList.size()), _graph(&graph), _requestList(&requestList) {
     _route.reserve(_nbRequest*4); //nbRequest*2 O/D KeyPoints + nbRequest*2 Start/End depots (upper bound #vehicle = #requests
 
-    //Init Request O/D key points
+    //Init Request O/D and Depot start/end key points
     for(size_t i = 0; i < _nbRequest; ++i) {
-        _route.at(i*2) = SAEVKeyPoint(graph, requestList.at(i), true); //origin
-        _route.at(i*2+1) = SAEVKeyPoint(graph, requestList.at(i), false); //destination
-    }
+        getOrigin(i) = SAEVKeyPoint(graph, requestList.at(i), true); //origin
+        getDestination(i) = SAEVKeyPoint(graph, requestList.at(i), false); //destination
 
-    //Init start/end depot key points
-    for(size_t i = _nbRequest; i < _nbRequest*2; ++i) {
-        _route.at(i*2) = SAEVKeyPoint(); //start
-        _route.at(i*2+1) = SAEVKeyPoint(); //end
+        getOriginDepot(i) = SAEVKeyPoint(); //start
+        getDestinationDepot(i) = SAEVKeyPoint(); //end
     }
 }
 
@@ -96,9 +93,9 @@ bool
 SAEVRoute::doNeighbouringTWChecks(const int requestIdx, const int originNodeIndex, const int destinationNodeIndex,
                                   const SAEVKeyPoint *originPredecessor, const SAEVKeyPoint *destinationPredecessor) {
 
-    SAEVKeyPoint const* originKP = &_route.at(requestIdx);
-    SAEVKeyPoint const* destinationKP = &_route.at(requestIdx + 1);
-    SAEVKeyPoint const* originSuccessor = originPredecessor->getSuccessor();
+    const SAEVKeyPoint& originKP = getOrigin(requestIdx);
+    const SAEVKeyPoint& destinationKP = getDestination(requestIdx);
+    const SAEVKeyPoint* originSuccessor = originPredecessor->getSuccessor();
 
     if(originPredecessor != destinationPredecessor)
     {
@@ -109,23 +106,23 @@ SAEVRoute::doNeighbouringTWChecks(const int requestIdx, const int originNodeInde
         int predDestinationTimeWindow = destinationPredecessor->getMinTw() + _graph->getShortestSAEVPath(destinationPredecessor->getNodeIndex(), destinationNodeIndex);
         if(predOriginTimeWindow > originKP->getMaxTw())
             return false;
-        else if(originKP->getMinTw() + _graph->getShortestSAEVPath(originKP->getNodeIndex(), originSuccessor->getNodeIndex()) > originSuccessor->getMaxTw()) // Could be removed ?
+        else if(originKP.getMinTw() + _graph->getShortestSAEVPath(originKP.getNodeIndex(), originSuccessor->getNodeIndex()) > originSuccessor->getMaxTw()) // Could be removed ?
             return false;
-        else if(predOriginTimeWindow + _graph->getShortestSAEVPath(originKP->getNodeIndex(), originSuccessor->getNodeIndex()) > originSuccessor->getMaxTw())
+        else if(predOriginTimeWindow + _graph->getShortestSAEVPath(originKP.getNodeIndex(), originSuccessor->getNodeIndex()) > originSuccessor->getMaxTw())
             return false;
         //Tests time windows Destination
-        else if(predDestinationTimeWindow > destinationKP->getMaxTw())
+        else if(predDestinationTimeWindow > destinationKP.getMaxTw())
             return false;
-        else if(destinationKP->getMinTw() + _graph->getShortestSAEVPath(destinationKP->getNodeIndex(), destinationSuccessor->getNodeIndex()) > destinationSuccessor->getMaxTw()) //could be removed ?
+        else if(destinationKP.getMinTw() + _graph->getShortestSAEVPath(destinationKP.getNodeIndex(), destinationSuccessor->getNodeIndex()) > destinationSuccessor->getMaxTw()) //could be removed ?
             return false;
         else if(predOriginTimeWindow + _graph->getShortestSAEVPath(destinationKP->getNodeIndex(), destinationSuccessor->getNodeIndex()) > destinationSuccessor->getMaxTw())
             return false;
     } else { //We need a specific case if origin and destination are inserted after the same node
         int predMinTWToOrigin = originPredecessor->getMinTw() + _graph->getShortestSAEVPath(originPredecessor->getNodeIndex(), originNodeIndex);
         int predMinTWToDest = predMinTWToOrigin + _graph->getShortestSAEVPath(originNodeIndex, destinationNodeIndex);
-        if(predMinTWToOrigin > originKP->getMaxTw()) //Path from pred to O
+        if(predMinTWToOrigin > originKP.getMaxTw()) //Path from pred to O
             return false;
-        else if(predMinTWToDest > destinationKP->getMaxTw()) //Path from pred to D
+        else if(predMinTWToDest > destinationKP.getMaxTw()) //Path from pred to D
             return false;
         else if(predMinTWToDest + _graph->getShortestSAEVPath(destinationNodeIndex, originSuccessor->getNodeIndex()) > originSuccessor->getMaxTw()) //Path from pred to successor
             return false;
diff --git a/src/routes/vehicle/SAEVRoute.h b/src/routes/vehicle/SAEVRoute.h
index 38437d6..b67e627 100644
--- a/src/routes/vehicle/SAEVRoute.h
+++ b/src/routes/vehicle/SAEVRoute.h
@@ -82,6 +82,12 @@ public:
      * @return A change list with every min/max bound change made during the insert procedure and a score estimating insertion quality (lower is better)
      */
     SAEVRouteChangelist insertRequestWithPropagation(const int requestIdx, const int originRequestPredecessorIdx, const int destinationRequestPredecessorIdx);
+
+    SAEVKeyPoint& getOrigin(const size_t requestIdx) { return _route.at(requestIdx*2);}
+    SAEVKeyPoint& getDestination(const size_t requestIdx) { return _route.at(requestIdx*2 + 1);}
+
+    SAEVKeyPoint& getOriginDepot(const size_t vehicleId) { return _route.at(_nbRequest + vehicleId*2);}
+    SAEVKeyPoint& getDestinationDepot(const size_t vehicleId) { return _route.at(_nbRequest + vehicleId*2 + 1);}
 };
 
 #include "propagation/SAEVRouteChangelist.h"
-- 
GitLab


From fe7cdef4affebacbdc76a84c94de5ccba37ea848 Mon Sep 17 00:00:00 2001
From: Romain BERNARD <romain.bernard@uca.fr>
Date: Mon, 29 Apr 2024 19:34:46 +0200
Subject: [PATCH 043/327] add detour score evaluation function

---
 src/routes/vehicle/SAEVRoute.cpp | 33 +++++++++++++++++++++++++++++++-
 src/routes/vehicle/SAEVRoute.h   | 10 ++++++++++
 2 files changed, 42 insertions(+), 1 deletion(-)

diff --git a/src/routes/vehicle/SAEVRoute.cpp b/src/routes/vehicle/SAEVRoute.cpp
index 3be78e4..b986cf5 100644
--- a/src/routes/vehicle/SAEVRoute.cpp
+++ b/src/routes/vehicle/SAEVRoute.cpp
@@ -2,6 +2,7 @@
 // Created by romain on 22/03/24.
 //
 
+#include <queue>
 #include "SAEVRoute.h"
 
 SAEVRoute::SAEVRoute(const Graph& graph, const std::vector<Request>& requestList) : _nbRequest(requestList.size()), _graph(&graph), _requestList(&requestList) {
@@ -104,7 +105,7 @@ SAEVRoute::doNeighbouringTWChecks(const int requestIdx, const int originNodeInde
         //Tests time windows Origin (yes this if-else could be one giant OR, but I'd rather separate every case)
         int predOriginTimeWindow = originPredecessor->getMinTw() + _graph->getShortestSAEVPath(originPredecessor->getNodeIndex(), originNodeIndex);
         int predDestinationTimeWindow = destinationPredecessor->getMinTw() + _graph->getShortestSAEVPath(destinationPredecessor->getNodeIndex(), destinationNodeIndex);
-        if(predOriginTimeWindow > originKP->getMaxTw())
+        if(predOriginTimeWindow > originKP.getMaxTw())
             return false;
         else if(originKP.getMinTw() + _graph->getShortestSAEVPath(originKP.getNodeIndex(), originSuccessor->getNodeIndex()) > originSuccessor->getMaxTw()) // Could be removed ?
             return false;
@@ -140,3 +141,33 @@ SAEVRouteChangelist SAEVRoute::insertRequestWithPropagation(const int requestIdx
                                                             const int destinationRequestPredecessorIdx) {
     return SAEVRouteChangelist(nullptr, 0, 0, 0);
 }
+
+double SAEVRoute::getDetourScore(const int requestIdx, const int originRequestPredecessorIdx,
+                                 const int destinationRequestPredecessorIdx) {
+    double score;
+    const SAEVKeyPoint& originKP = getOrigin(requestIdx);
+    const SAEVKeyPoint& destinationKP = getOrigin(requestIdx);
+    const SAEVKeyPoint& originPredKP = _route.at(originRequestPredecessorIdx);
+    const SAEVKeyPoint* originSuccKP = originPredKP.getSuccessor();
+
+    if(originRequestPredecessorIdx != destinationRequestPredecessorIdx) {
+        const SAEVKeyPoint* destinationPredKP = getDestination(requestIdx).getPredecessor();
+        const SAEVKeyPoint* destinationSuccKP = getDestination(requestIdx).getSuccessor();
+
+        //Origin Detour
+        score = _graph->getShortestSAEVPath(originPredKP.getNodeIndex(), originKP.getNodeIndex()) //T(Pred(O), D)
+                + _graph->getShortestSAEVPath(originKP.getNodeIndex(), originSuccKP->getNodeIndex()) //T(O, Succ(D))
+                - _graph->getShortestSAEVPath(originPredKP.getNodeIndex(), originSuccKP->getNodeIndex()); //T(Pred(O), Succ(O))
+
+        //Destination Detour
+        score += _graph->getShortestSAEVPath(destinationPredKP->getNodeIndex(), destinationKP.getNodeIndex()) //T(Pred(D), D))
+                + _graph->getShortestSAEVPath(destinationKP.getNodeIndex(), destinationSuccKP->getNodeIndex()) //T(D, Succ(D)))
+                - _graph->getShortestSAEVPath(destinationPredKP->getNodeIndex(), destinationSuccKP->getNodeIndex()); //T(Pred(D), Succ(D)))
+    } else {
+        score = _graph->getShortestSAEVPath(originPredKP.getNodeIndex(), originKP.getNodeIndex()) //T(Pred(O), O)
+                + _graph->getShortestSAEVPath(originKP.getNodeIndex(), destinationKP.getNodeIndex()) //T(O, D)
+                + _graph->getShortestSAEVPath(destinationKP.getNodeIndex(), originSuccKP->getNodeIndex()) //T(D, Succ(D))
+                - _graph->getShortestSAEVPath(originPredKP.getNodeIndex(), originSuccKP->getNodeIndex()); //T(Pred(O), Succ(D))
+    }
+    return score;
+}
diff --git a/src/routes/vehicle/SAEVRoute.h b/src/routes/vehicle/SAEVRoute.h
index b67e627..273db54 100644
--- a/src/routes/vehicle/SAEVRoute.h
+++ b/src/routes/vehicle/SAEVRoute.h
@@ -83,6 +83,16 @@ public:
      */
     SAEVRouteChangelist insertRequestWithPropagation(const int requestIdx, const int originRequestPredecessorIdx, const int destinationRequestPredecessorIdx);
 
+    /**
+     * Returns a score value equivalent to the detour implied by insertion of a request after the two given key point indexes.
+     * The specific case of origin/destination being inserted one after another is taken into account
+     * @param requestIdx Identifier/index in the instance's request vector for the request we wish to insert
+     * @param originRequestPredecessorIdx Identifier/index in the route key point vector for the request origin or destination that will precede our request's origin in the route
+     * @param destinationRequestPredecessorIdx Identifier/index in the route key point vector for the request origin or destination that will precede our request's destination in the route
+     * @return
+     */
+    double getDetourScore(const int requestIdx, const int originRequestPredecessorIdx, const int destinationRequestPredecessorIdx);
+
     SAEVKeyPoint& getOrigin(const size_t requestIdx) { return _route.at(requestIdx*2);}
     SAEVKeyPoint& getDestination(const size_t requestIdx) { return _route.at(requestIdx*2 + 1);}
 
-- 
GitLab


From bf2c4efc7a3cf5af5f46807e127051b6b4325cf3 Mon Sep 17 00:00:00 2001
From: Romain BERNARD <romain.bernard@uca.fr>
Date: Mon, 29 Apr 2024 19:35:19 +0200
Subject: [PATCH 044/327] WIP constraint propagation function (TODO: add
 request and counterpart in KP)

---
 src/routes/vehicle/SAEVRoute.cpp | 80 +++++++++++++++++++++++++++++++-
 1 file changed, 79 insertions(+), 1 deletion(-)

diff --git a/src/routes/vehicle/SAEVRoute.cpp b/src/routes/vehicle/SAEVRoute.cpp
index b986cf5..ab797be 100644
--- a/src/routes/vehicle/SAEVRoute.cpp
+++ b/src/routes/vehicle/SAEVRoute.cpp
@@ -139,7 +139,85 @@ SAEVRoute::doNeighbouringTWChecks(const int requestIdx, const int originNodeInde
 
 SAEVRouteChangelist SAEVRoute::insertRequestWithPropagation(const int requestIdx, const int originRequestPredecessorIdx,
                                                             const int destinationRequestPredecessorIdx) {
-    return SAEVRouteChangelist(nullptr, 0, 0, 0);
+    //Init changelist
+    SAEVRouteChangelist changelist{this, requestIdx, originRequestPredecessorIdx, destinationRequestPredecessorIdx};
+    //Properly insert the request to facilitate constraint propagation
+    insertRequest(requestIdx, originRequestPredecessorIdx, destinationRequestPredecessorIdx);
+
+    //Initialize bound propagation signal queue (each item signals a modification done on one of a KeyPoint
+    std::queue<std::pair<Bound, SAEVKeyPoint *>> boundPropagationQueue{};
+    const SAEVKeyPoint& originKP = getOrigin(requestIdx);
+    const SAEVKeyPoint& destinationKP = getDestination(requestIdx);
+    boundPropagationQueue.emplace(Min, originKP);
+    boundPropagationQueue.emplace(Max, originKP);
+    boundPropagationQueue.emplace(Min, destinationKP);
+    boundPropagationQueue.emplace(Max, destinationKP);
+
+    //Pre-init variables used in the loop
+    int oldValue;
+    int newValue;
+    SAEVKeyPoint * predecessorKP;
+    SAEVKeyPoint * successorKP;
+    SAEVKeyPoint * counterpartKP; //An Origin's Destination, or a Destination's Origin
+
+
+    while(!boundPropagationQueue.empty()) {
+        auto const& [bound, keyPoint] = boundPropagationQueue.front();
+        boundPropagationQueue.pop();
+
+        if(bound == Min) {
+            successorKP = keyPoint->getSuccessor();
+            oldValue = successorKP->getMinTw();
+            //Check neighbouring time window
+            newValue = keyPoint->getMinTw() + _graph->getShortestSAEVPath(keyPoint->getNodeIndex(), successorKP->getNodeIndex());
+            if(successorKP != nullptr && oldValue < newValue) {
+                if (newValue > successorKP->getMaxTw()) {
+                    return changelist;
+                }
+                changelist.emplace_back(*successorKP, Min, newValue - oldValue);
+                successorKP->setMinTw(newValue);
+                boundPropagationQueue.emplace(Min, successorKP);
+            }
+            //Check counterpart key point delta time
+            oldValue = counterpartKP->getMinTw();
+            newValue = keyPoint->getMinTw() - keyPoint.getRequest().getDeltaTime();
+            if(!counterpartKP.isOrigin() && oldValue < newValue) {
+                if (newValue > counterpartKP->getMaxTw()) {
+                    return changelist;
+                }
+                changelist.emplace_back(*counterpartKP, Min, newValue - oldValue);
+                counterpartKP->setMinTw(newValue);
+                boundPropagationQueue.emplace(Min, counterpartKP);
+            }
+        } else {
+            predecessorKP = keyPoint->getSuccessor();
+            oldValue = predecessorKP->getMaxTw();
+            //Check neighbouring time window
+            newValue = keyPoint->getMaxTw() - _graph->getShortestSAEVPath(predecessorKP->getNodeIndex(), keyPoint->getNodeIndex());
+            if(predecessorKP != nullptr && oldValue > newValue) {
+                if (predecessorKP->getMinTw() > newValue) {
+                    return changelist;
+                }
+                changelist.emplace_back(*predecessorKP, Max, newValue - oldValue);
+                predecessorKP->setMaxTw(newValue);
+                boundPropagationQueue.emplace(Max, predecessorKP);
+            }
+            //Check counterpart key point delta time
+            oldValue = counterpartKP->getMaxTw();
+            newValue = keyPoint->getMaxTw() + keyPoint.getRequest().getDeltaTime();
+            if(counterpartKP.isOrigin() && oldValue > newValue) {
+                if (counterpartKP->getMinTw() > newValue) {
+                    return changelist;
+                }
+                changelist.emplace_back(*counterpartKP, Max, oldValue - newValue);
+                counterpartKP->setMaxTw(newValue);
+                boundPropagationQueue.emplace(Max, counterpartKP);
+            }
+        }
+    }
+
+    changelist.setScore(getDetourScore(requestIdx, originRequestPredecessorIdx, destinationRequestPredecessorIdx));
+    return changelist;
 }
 
 double SAEVRoute::getDetourScore(const int requestIdx, const int originRequestPredecessorIdx,
-- 
GitLab


From 273290d6adb8a31589f998fb5cf2e3e32e7a4248 Mon Sep 17 00:00:00 2001
From: Romain BERNARD <romain.bernard@uca.fr>
Date: Fri, 17 May 2024 17:45:06 +0200
Subject: [PATCH 045/327] add counterpart and isOrigin to SAEV Keypoints

---
 src/routes/vehicle/SAEVKeyPoint.cpp | 33 +++++++++++++++++++++++++++--
 src/routes/vehicle/SAEVKeyPoint.h   | 26 +++++++++++++++++++++--
 2 files changed, 55 insertions(+), 4 deletions(-)

diff --git a/src/routes/vehicle/SAEVKeyPoint.cpp b/src/routes/vehicle/SAEVKeyPoint.cpp
index 136e34f..6f87535 100644
--- a/src/routes/vehicle/SAEVKeyPoint.cpp
+++ b/src/routes/vehicle/SAEVKeyPoint.cpp
@@ -48,8 +48,9 @@ void SAEVKeyPoint::setMaxTw(int maxTw) {
     _maxTW = maxTw;
 }
 
-SAEVKeyPoint::SAEVKeyPoint(const Graph &graph, const Request &request, bool isEntry) {
-    if(isEntry) {
+SAEVKeyPoint::SAEVKeyPoint(const Graph &graph, const Request &request, bool isOrigin) {
+    _isOrigin = isOrigin;
+    if(isOrigin) {
         setNodeIndex(request.getOriginNodeIndex());
         _minTW = request.getArrivalTw().min - request.getDeltaTime();
         _maxTW = request.getArrivalTw().max - graph.getShortestSAEVPath(request.getOriginNodeIndex(),
@@ -60,3 +61,31 @@ SAEVKeyPoint::SAEVKeyPoint(const Graph &graph, const Request &request, bool isEn
         _maxTW = request.getArrivalTw().max;
     }
 }
+
+bool SAEVKeyPoint::operator==(const SAEVKeyPoint &rhs) const {
+    return this == &rhs;
+}
+
+bool SAEVKeyPoint::isOrigin() const {
+    return _isOrigin;
+}
+
+void SAEVKeyPoint::setIsOrigin(bool isOrigin) {
+    _isOrigin = isOrigin;
+}
+
+Request *SAEVKeyPoint::getRequest() const {
+    return _requestPointer;
+}
+
+void SAEVKeyPoint::setRequest(Request *requestPointer) {
+    _requestPointer = requestPointer;
+}
+
+SAEVKeyPoint *SAEVKeyPoint::getCounterpart() const {
+    return _counterpart;
+}
+
+void SAEVKeyPoint::setCounterpart(SAEVKeyPoint *counterpart) {
+    _counterpart = counterpart;
+}
diff --git a/src/routes/vehicle/SAEVKeyPoint.h b/src/routes/vehicle/SAEVKeyPoint.h
index 7443250..f08bc25 100644
--- a/src/routes/vehicle/SAEVKeyPoint.h
+++ b/src/routes/vehicle/SAEVKeyPoint.h
@@ -9,15 +9,19 @@
 #include "../../instance/requests/Request.h"
 #include "../KeyPoint.h"
 #include "../../instance/graph/Graph.h"
+#include "propagation/SAEVRouteChange.h"
 
 class SAEVKeyPoint : public KeyPoint {
 private:
+    bool _isOrigin;
     SAEVKeyPoint* _predecessor{nullptr};
     SAEVKeyPoint* _successor{nullptr};
+    SAEVKeyPoint* _counterpart{nullptr};
     int _currentOccupation{0};
     int _minTW{0};
     int _maxTW{INT16_MAX};
     SAEVehicle* _vehiclePointer{};
+    Request* _requestPointer;
 public:
     /**
      * Depot KP initialization with [0;max] time windows
@@ -27,9 +31,9 @@ public:
      * SAEV KP initialization
      * @param graph the instance's graph, used to get shortest path and estimate start time windows relative to distances
      * @param request the request associated with our key point, required to initialize time windows
-     * @param isEntry true iff the key point represents the request's origin, false otherwise
+     * @param isOrigin true iff the key point represents the request's origin, false otherwise
      */
-    SAEVKeyPoint(const Graph &graph, const Request& request, bool isEntry);
+    SAEVKeyPoint(const Graph &graph, const Request& request, bool isOrigin);
 
     [[nodiscard]] SAEVKeyPoint *getPredecessor() const;
     void setPredecessor(SAEVKeyPoint *predecessor);
@@ -46,9 +50,27 @@ public:
     [[nodiscard]] int getMaxTw() const;
     void setMaxTw(int maxTw);
 
+    [[nodiscard]] bool isOrigin() const;
+    void setIsOrigin(bool isOrigin);
+
+    [[nodiscard]] Request *getRequest() const;
+    void setRequest(Request *requestPointer);
+
+    SAEVKeyPoint *getCounterpart() const;
+
+    void setCounterpart(SAEVKeyPoint *counterpart);
+
     [[nodiscard]] bool check() const override;
 
     ~SAEVKeyPoint() override = default;
+
+    /**
+     * Two SAEVKeyPoints are equal iff they're the same instance (located at the same adress)
+     * It is done this way because a KP doesn't hold the info of the Request O/D it references. Only the route knows this
+     * @param rhs right hand side of the comparison
+     * @return True iff this and rhs are the same instance at the same adress
+     */
+    bool operator==(const SAEVKeyPoint &rhs) const;
 };
 
 
-- 
GitLab


From f8b93740ac67a39184955f02dcfd7cca2569a7c6 Mon Sep 17 00:00:00 2001
From: Romain BERNARD <romain.bernard@uca.fr>
Date: Fri, 17 May 2024 17:45:56 +0200
Subject: [PATCH 046/327] Link Origins/destinations in route initialization

---
 src/routes/vehicle/SAEVRoute.cpp | 8 ++++++++
 1 file changed, 8 insertions(+)

diff --git a/src/routes/vehicle/SAEVRoute.cpp b/src/routes/vehicle/SAEVRoute.cpp
index ab797be..53ce511 100644
--- a/src/routes/vehicle/SAEVRoute.cpp
+++ b/src/routes/vehicle/SAEVRoute.cpp
@@ -10,11 +10,19 @@ SAEVRoute::SAEVRoute(const Graph& graph, const std::vector<Request>& requestList
 
     //Init Request O/D and Depot start/end key points
     for(size_t i = 0; i < _nbRequest; ++i) {
+        //Create key O/D points
         getOrigin(i) = SAEVKeyPoint(graph, requestList.at(i), true); //origin
         getDestination(i) = SAEVKeyPoint(graph, requestList.at(i), false); //destination
+        //Link Origins and Destinations
+        getOrigin(i).setCounterpart(&getDestination(i));
+        getDestination(i).setCounterpart(&getOrigin(i));
 
+        //Create depot O/D KP (Upper Bound = nb requests)
         getOriginDepot(i) = SAEVKeyPoint(); //start
         getDestinationDepot(i) = SAEVKeyPoint(); //end
+        //Link Origin depots and Destination depots
+        getOriginDepot(i).setCounterpart(&getDestinationDepot(i));
+        getDestinationDepot(i).setCounterpart(&getOriginDepot(i));
     }
 }
 
-- 
GitLab


From 40a0f0973506de0724c9e23a227e4d00c162caf2 Mon Sep 17 00:00:00 2001
From: Romain BERNARD <romain.bernard@uca.fr>
Date: Fri, 17 May 2024 17:47:32 +0200
Subject: [PATCH 047/327] notation fixes

---
 src/routes/vehicle/SAEVRoute.cpp | 13 +++++++------
 test/lib/googletest              |  2 +-
 2 files changed, 8 insertions(+), 7 deletions(-)

diff --git a/src/routes/vehicle/SAEVRoute.cpp b/src/routes/vehicle/SAEVRoute.cpp
index 53ce511..975ce71 100644
--- a/src/routes/vehicle/SAEVRoute.cpp
+++ b/src/routes/vehicle/SAEVRoute.cpp
@@ -124,7 +124,7 @@ SAEVRoute::doNeighbouringTWChecks(const int requestIdx, const int originNodeInde
             return false;
         else if(destinationKP.getMinTw() + _graph->getShortestSAEVPath(destinationKP.getNodeIndex(), destinationSuccessor->getNodeIndex()) > destinationSuccessor->getMaxTw()) //could be removed ?
             return false;
-        else if(predOriginTimeWindow + _graph->getShortestSAEVPath(destinationKP->getNodeIndex(), destinationSuccessor->getNodeIndex()) > destinationSuccessor->getMaxTw())
+        else if(predOriginTimeWindow + _graph->getShortestSAEVPath(destinationKP.getNodeIndex(), destinationSuccessor->getNodeIndex()) > destinationSuccessor->getMaxTw())
             return false;
     } else { //We need a specific case if origin and destination are inserted after the same node
         int predMinTWToOrigin = originPredecessor->getMinTw() + _graph->getShortestSAEVPath(originPredecessor->getNodeIndex(), originNodeIndex);
@@ -137,7 +137,7 @@ SAEVRoute::doNeighbouringTWChecks(const int requestIdx, const int originNodeInde
             return false;
         else if(originSuccessor->getMinTw() + _graph->getShortestSAEVPath(destinationNodeIndex, originSuccessor->getNodeIndex()) > originSuccessor->getMaxTw()) //Path from D to successor
             return false;
-        else if(originKP->getMinTw() + _graph->getShortestSAEVPath(originNodeIndex, destinationNodeIndex) //Path from O to successor
+        else if(originKP.getMinTw() + _graph->getShortestSAEVPath(originNodeIndex, destinationNodeIndex) //Path from O to successor
         + _graph->getShortestSAEVPath(destinationNodeIndex, originSuccessor->getNodeIndex()) > originSuccessor->getMaxTw())
             return false;
     }
@@ -172,6 +172,7 @@ SAEVRouteChangelist SAEVRoute::insertRequestWithPropagation(const int requestIdx
     while(!boundPropagationQueue.empty()) {
         auto const& [bound, keyPoint] = boundPropagationQueue.front();
         boundPropagationQueue.pop();
+        counterpartKP = keyPoint->getCounterpart();
 
         if(bound == Min) {
             successorKP = keyPoint->getSuccessor();
@@ -188,8 +189,8 @@ SAEVRouteChangelist SAEVRoute::insertRequestWithPropagation(const int requestIdx
             }
             //Check counterpart key point delta time
             oldValue = counterpartKP->getMinTw();
-            newValue = keyPoint->getMinTw() - keyPoint.getRequest().getDeltaTime();
-            if(!counterpartKP.isOrigin() && oldValue < newValue) {
+            newValue = keyPoint->getMinTw() - keyPoint->getRequest()->getDeltaTime();
+            if(!counterpartKP->isOrigin() && oldValue < newValue) {
                 if (newValue > counterpartKP->getMaxTw()) {
                     return changelist;
                 }
@@ -212,8 +213,8 @@ SAEVRouteChangelist SAEVRoute::insertRequestWithPropagation(const int requestIdx
             }
             //Check counterpart key point delta time
             oldValue = counterpartKP->getMaxTw();
-            newValue = keyPoint->getMaxTw() + keyPoint.getRequest().getDeltaTime();
-            if(counterpartKP.isOrigin() && oldValue > newValue) {
+            newValue = keyPoint->getMaxTw() + keyPoint->getRequest()->getDeltaTime();
+            if(counterpartKP->isOrigin() && oldValue > newValue) {
                 if (counterpartKP->getMinTw() > newValue) {
                     return changelist;
                 }
diff --git a/test/lib/googletest b/test/lib/googletest
index b1a777f..33af80a 160000
--- a/test/lib/googletest
+++ b/test/lib/googletest
@@ -1 +1 @@
-Subproject commit b1a777f31913f8a047f43b2a5f823e736e7f5082
+Subproject commit 33af80a883ddc33d9c0fac0a5b4578301efb18de
-- 
GitLab


From a78175f419fe0106d0fb1a5b2b61ba064c429d36 Mon Sep 17 00:00:00 2001
From: Romain BERNARD <30secondstodraw@gmail.com>
Date: Fri, 24 May 2024 04:34:30 +0200
Subject: [PATCH 048/327] allow distance matrix format in graph instantiation
 parsing

---
 src/instance/graph/Graph.cpp | 29 ++++++++++++++++++++++++-----
 src/instance/graph/Graph.h   |  2 ++
 2 files changed, 26 insertions(+), 5 deletions(-)

diff --git a/src/instance/graph/Graph.cpp b/src/instance/graph/Graph.cpp
index 6bf5a5d..0a7f9bf 100644
--- a/src/instance/graph/Graph.cpp
+++ b/src/instance/graph/Graph.cpp
@@ -89,12 +89,20 @@ Graph::Graph(const std::string& datFilePath) {
     }
     //-- End of nodes
 
-    //-- Read Edges
-    std::cout << currentRow.toString() << std::endl;
-    while(infile >> currentRow && !currentRow[0].starts_with('#')) {
-        this->parseEdgeRow(currentRow);
+    //Node links (edges or matrix)
+    if(currentRow[0].starts_with("#Edges")) {
+        //-- Read Edges
+        std::cout << currentRow.toString() << std::endl;
+        while (infile >> currentRow && !currentRow[0].starts_with('#')) {
+            this->parseEdgeRow(currentRow);
+        }
+        //-- End of edges
+    } else if (currentRow[0].starts_with("#Matrix")) {
+        //-- Read Distance matrix
+        std::cout << currentRow.toString() << std::endl;
+        this->parseDistanceMatrix(infile, currentRow);
+        //-- End of edges
     }
-    //-- End of edges
 
     //-- Read Public transit line
     std::cout << currentRow.toString() << std::endl;
@@ -286,3 +294,14 @@ void Graph::createAndAddEdge(int edgeStartNodeIndex, int edgeEndNodeIndex, doubl
     Node exitNode = nodesVector.at(edgeEndNodeIndex);
     exitNode.getIncomingEdges().emplace_back(edgesVector.size() - 1);
 }
+
+void Graph::parseDistanceMatrix(std::ifstream &infile, DATRow currentRow) {
+    int intVal;
+    while (infile >> currentRow && !currentRow[0].starts_with('#')) {
+        auto& matrixLine = shortestSAEVPaths.emplace_back();
+        for(int i = 0; i < currentRow.size(); ++i) {
+            std::from_chars(currentRow[i].data(), currentRow[i].data() + currentRow[i].size(), intVal);
+            matrixLine.emplace_back(intVal);
+        }
+    }
+}
diff --git a/src/instance/graph/Graph.h b/src/instance/graph/Graph.h
index 634a334..1027abf 100644
--- a/src/instance/graph/Graph.h
+++ b/src/instance/graph/Graph.h
@@ -147,6 +147,8 @@ public:
     void createAndAddEdge(int edgeStartNodeIndex, int edgeEndNodeIndex, double length);
 
     [[nodiscard]] int getShortestSAEVPath(int x, int y) const { return shortestSAEVPaths.at(x).at(y); }
+
+    void parseDistanceMatrix(std::ifstream &infile, DATRow currentRow);
 };
 
 
-- 
GitLab


From 2a6feb39f2c9dfc9888ac535de33e7d7fbe21e7f Mon Sep 17 00:00:00 2001
From: Romain BERNARD <30secondstodraw@gmail.com>
Date: Fri, 24 May 2024 04:35:21 +0200
Subject: [PATCH 049/327] Request constructor from a DAT file row

---
 src/instance/requests/Request.cpp | 18 ++++++++++++++++++
 src/instance/requests/Request.h   | 11 ++++++-----
 2 files changed, 24 insertions(+), 5 deletions(-)

diff --git a/src/instance/requests/Request.cpp b/src/instance/requests/Request.cpp
index 6f6b60a..c54aee4 100644
--- a/src/instance/requests/Request.cpp
+++ b/src/instance/requests/Request.cpp
@@ -2,7 +2,9 @@
 // Created by rbernard on 22/01/24.
 //
 
+#include <charconv>
 #include "Request.h"
+#include "../../services/DatFile/DATRow.h"
 
 Request::Request(const int departureNodeIndex, const int arrivalNodeIndex, const TimeWindow &arrivalTw,
                  const int deltaTime, const int weight) : _originNodeIndex(departureNodeIndex),
@@ -21,6 +23,22 @@ Request::Request(const int departureNodeIndex, const int arrivalNodeIndex, const
     _departureTW.max = _arrivalTW.max - graph.getShortestSAEVPath(departureNodeIndex, arrivalNodeIndex);
 }
 
+Request::Request(const DATRow& currentRow, const Graph& graph) {
+    std::from_chars(currentRow[0].data(), currentRow[0].data() + currentRow[0].size(), _originNodeIndex);
+    std::from_chars(currentRow[1].data(), currentRow[1].data() + currentRow[1].size(), _destinationNodeIndex);
+
+    int twMin, twMax;
+    std::from_chars(currentRow[2].data(), currentRow[2].data() + currentRow[2].size(), twMin);
+    std::from_chars(currentRow[3].data(), currentRow[3].data() + currentRow[3].size(), twMax);
+    _arrivalTW = TimeWindow(twMin, twMax);
+
+    std::from_chars(currentRow[4].data(), currentRow[4].data() + currentRow[4].size(), _deltaTime);
+    std::from_chars(currentRow[5].data(), currentRow[5].data() + currentRow[5].size(), _weight);
+
+    _departureTW.min = _arrivalTW.min - _currentDeltaTime;
+    _departureTW.max = _arrivalTW.max - graph.getShortestSAEVPath(_originNodeIndex, _destinationNodeIndex);
+}
+
 const int Request::getOriginNodeIndex() const {
     return _originNodeIndex;
 }
diff --git a/src/instance/requests/Request.h b/src/instance/requests/Request.h
index b6f1fbe..08fdfc5 100644
--- a/src/instance/requests/Request.h
+++ b/src/instance/requests/Request.h
@@ -13,11 +13,11 @@
 class Request {
 private:
     //Request base members (const and initialized on _request creation)
-    const int _originNodeIndex; //Starting point of the user _request //TODO (?) change this to a Node pointer eventually
-    const int _destinationNodeIndex; //
-    const TimeWindow _arrivalTW; //[min,max] time window for arrival to the destination node
-    const int _deltaTime; //Base delta time, aka the maximum total duration of the path to serve this _request
-    const int _weight; //How much space the requests takes in the vehicle (defaults to 1)
+    int _originNodeIndex; //Starting point of the user _request //TODO (?) change this to a Node pointer eventually
+    int _destinationNodeIndex; //
+    TimeWindow _arrivalTW; //[min,max] time window for arrival to the destination node
+    int _deltaTime; //Base delta time, aka the maximum total duration of the path to serve this _request
+    int _weight; //How much space the requests takes in the vehicle (defaults to 1)
 
     //Request helpful members (used for constraint propagation and remember the current state of the _request)
     int _currentDeltaTime; //deltaTime - currentRouteDuration
@@ -30,6 +30,7 @@ public:
             const TimeWindow &arrivalTw, const int deltaTime, const int weight);
     Request(const int departureNodeIndex, const int arrivalNodeIndex, const TimeWindow &arrivalTw,
             const int deltaTime, const int weight, const Graph& graph);
+    Request(const DATRow& currentRow, const Graph& graph);
 
     //Getters
     [[nodiscard]] const int getOriginNodeIndex() const;
-- 
GitLab


From de1eb1f337b7ae17eacb66fc555b58c99f626ca3 Mon Sep 17 00:00:00 2001
From: Romain BERNARD <30secondstodraw@gmail.com>
Date: Fri, 24 May 2024 04:35:46 +0200
Subject: [PATCH 050/327] instance constructor create graph and parse requests
 file

---
 src/instance/Instance.cpp | 20 +++++++++++++++++++-
 src/instance/Instance.h   | 20 ++++++++++++--------
 2 files changed, 31 insertions(+), 9 deletions(-)

diff --git a/src/instance/Instance.cpp b/src/instance/Instance.cpp
index f650d9f..498dcf0 100644
--- a/src/instance/Instance.cpp
+++ b/src/instance/Instance.cpp
@@ -2,6 +2,24 @@
 // Created by rbernard on 22/01/24.
 //
 
+#include <iostream>
 #include "Instance.h"
 #include "graph/Graph.h"
-#include "requests/Request.h"
\ No newline at end of file
+#include "requests/Request.h"
+#include "../services/DatFile/DATRow.h"
+
+Instance::Instance(const std::string& graphFilePath,
+                   const std::string& requestsFilePath,
+                   const int vehicleCapacity): _graph(graphFilePath),_vehicleCapacity(vehicleCapacity)
+{
+    parseRequestsFromFile(requestsFilePath);
+}
+
+void Instance::parseRequestsFromFile(const std::string &requestsFilePath) {
+    std::ifstream infile(requestsFilePath);
+    DATRow currentRow = DATRow(',');
+    std::string currentLine;
+    while(infile >> currentRow && !currentRow[0].starts_with('#')) {
+        _requests.emplace_back(currentRow, _graph);
+    }
+}
diff --git a/src/instance/Instance.h b/src/instance/Instance.h
index e99282d..60ea883 100644
--- a/src/instance/Instance.h
+++ b/src/instance/Instance.h
@@ -12,17 +12,21 @@
 
 class Instance {
 private:
-    std::vector<Request> requests;
-    Graph graph;
-    int vehicleCapacity;
+
+    std::vector<Request> _requests;
+    Graph _graph;
+    int _vehicleCapacity;
 
 public:
-    Instance(const std::vector<Request> &requests, Graph graph, const int vehicleCapacity) : requests(
-            requests), graph(std::move(graph)), vehicleCapacity(vehicleCapacity) {}
+    Instance(const std::string &graphFilePath, const std::string &requestsFilePath, const int vehicleCapacity);
+    Instance(const std::vector<Request> &requests, Graph graph, const int vehicleCapacity) : _requests(
+            requests), _graph(std::move(graph)), _vehicleCapacity(vehicleCapacity) {}
+
+    [[nodiscard]] Graph const & getGraph() const { return _graph;}
+    [[nodiscard]] std::vector<Request> const & getRequests() const { return _requests;}
+    [[nodiscard]] int getVehicleCapacity() const { return _vehicleCapacity; }
 
-    [[nodiscard]] Graph const & getGraph() const { return graph;}
-    [[nodiscard]] std::vector<Request> const & getRequests() const { return requests;}
-    [[nodiscard]] int getVehicleCapacity() const { return vehicleCapacity; }
+    void parseRequestsFromFile(const std::string &basicString);
 };
 
 
-- 
GitLab


From 487ab51e2a75ad7ed73aeb3c89747390baaa5fac Mon Sep 17 00:00:00 2001
From: Romain BERNARD <romain.bernard@uca.fr>
Date: Fri, 24 May 2024 18:14:57 +0200
Subject: [PATCH 051/327] const correctness and data init sonarlint

---
 src/instance/requests/Request.cpp   |  4 ++--
 src/instance/requests/Request.h     |  4 ++--
 src/routes/RequestKeyPoint.cpp      |  8 ++++----
 src/routes/RequestKeyPoint.h        | 18 +++++++++---------
 src/routes/RequestRoute.cpp         |  4 ++--
 src/routes/RequestRoute.h           |  6 +++---
 src/routes/vehicle/SAEVKeyPoint.cpp |  7 +++----
 src/routes/vehicle/SAEVKeyPoint.h   | 12 ++++++------
 8 files changed, 31 insertions(+), 32 deletions(-)

diff --git a/src/instance/requests/Request.cpp b/src/instance/requests/Request.cpp
index c54aee4..dca7175 100644
--- a/src/instance/requests/Request.cpp
+++ b/src/instance/requests/Request.cpp
@@ -133,7 +133,7 @@ void Request::setNodeIndex(int routeIndex, int nodeIndex) {
     _currentRoute.setNodeIndex(routeIndex, nodeIndex);
 }
 
-SAEVehicle *Request::getSAEV(int routeIndex) const {
+SAEVehicle const *Request::getSAEV(int routeIndex) const {
     return _currentRoute.getSAEV(routeIndex);
 }
 
@@ -141,7 +141,7 @@ void Request::setSAEV(int routeIndex, SAEVehicle *saev) {
     _currentRoute.setSAEV(routeIndex, saev);
 }
 
-LineStop *Request::getLineStop(int routeIndex) const {
+LineStop const *Request::getLineStop(int routeIndex) const {
     return _currentRoute.getLineStop(routeIndex);
 }
 
diff --git a/src/instance/requests/Request.h b/src/instance/requests/Request.h
index 08fdfc5..6763a59 100644
--- a/src/instance/requests/Request.h
+++ b/src/instance/requests/Request.h
@@ -65,10 +65,10 @@ public:
     [[nodiscard]] int getDepartureInstant(int routeIndex) const;
     void setDepartureInstant(int routeIndex, int departureInstant);
 
-    [[nodiscard]] SAEVehicle *getSAEV(int routeIndex) const;
+    [[nodiscard]] const SAEVehicle *getSAEV(int routeIndex) const;
     void setSAEV(int routeIndex, SAEVehicle *saev);
 
-    [[nodiscard]] LineStop *getLineStop(int routeIndex) const;
+    [[nodiscard]] const LineStop *getLineStop(int routeIndex) const;
     void setLineStop(int routeIndex, LineStop *lineStop);
 
     void resetKeyPoint(int routeIndex);
diff --git a/src/routes/RequestKeyPoint.cpp b/src/routes/RequestKeyPoint.cpp
index 70d7a01..40d52a5 100644
--- a/src/routes/RequestKeyPoint.cpp
+++ b/src/routes/RequestKeyPoint.cpp
@@ -4,20 +4,20 @@
 
 #include "RequestKeyPoint.h"
 
-SAEVehicle *RequestKeyPoint::getSAEV() const {
+SAEVehicle const *RequestKeyPoint::getSAEV() const {
     return _saev;
 }
 
-void RequestKeyPoint::setSAEV(SAEVehicle *saev) {
+void RequestKeyPoint::setSAEV(const SAEVehicle *saev) {
     _saev = saev;
     _lineStop = nullptr;
 }
 
-LineStop *RequestKeyPoint::getLineStop() const {
+LineStop const *RequestKeyPoint::getLineStop() const {
     return _lineStop;
 }
 
-void RequestKeyPoint::setLineStop(LineStop *lineStop) {
+void RequestKeyPoint::setLineStop(const LineStop *lineStop) {
     _lineStop = lineStop;
     _saev = nullptr;
 }
diff --git a/src/routes/RequestKeyPoint.h b/src/routes/RequestKeyPoint.h
index ac65c91..4794e5b 100644
--- a/src/routes/RequestKeyPoint.h
+++ b/src/routes/RequestKeyPoint.h
@@ -10,10 +10,10 @@
 #include "../instance/SAEVehicle.h"
 #include "../instance/graph/LineStop.h"
 
-class RequestKeyPoint : public virtual KeyPoint {
+class RequestKeyPoint : public KeyPoint {
 private:
-    SAEVehicle* _saev{};
-    LineStop* _lineStop{};
+    SAEVehicle const * _saev{};
+    LineStop const * _lineStop{};
 
     //Constraint propagation variables
     TimeWindow _arrivalTimeWindow{};
@@ -21,14 +21,14 @@ private:
 
 public:
     RequestKeyPoint() = default;
-    explicit RequestKeyPoint(SAEVehicle* vehicle) { _saev = vehicle; }
-    explicit RequestKeyPoint(LineStop* lineStop) { _lineStop = lineStop; }
+    explicit RequestKeyPoint(SAEVehicle const* vehicle) : _saev(vehicle) {}
+    explicit RequestKeyPoint(LineStop const* lineStop) : _lineStop(lineStop) {}
 
-    [[nodiscard]] SAEVehicle *getSAEV() const;
-    void setSAEV(SAEVehicle *saev);
+    [[nodiscard]] const SAEVehicle *getSAEV() const;
+    void setSAEV(const SAEVehicle *saev);
 
-    [[nodiscard]] LineStop *getLineStop() const;
-    void setLineStop(LineStop *lineStop);
+    [[nodiscard]] const LineStop *getLineStop() const;
+    void setLineStop(const LineStop *lineStop);
 
     [[nodiscard]] const TimeWindow &getArrivalTimeWindow() const;
     void setArrivalTimeWindow(const TimeWindow &arrivalTimeWindow);
diff --git a/src/routes/RequestRoute.cpp b/src/routes/RequestRoute.cpp
index 806cc9b..f71f0f8 100644
--- a/src/routes/RequestRoute.cpp
+++ b/src/routes/RequestRoute.cpp
@@ -12,7 +12,7 @@ void RequestRoute::setNodeIndex(int routeIndex, int nodeIndex) {
     _route[routeIndex].setNodeIndex(nodeIndex);
 }
 
-SAEVehicle *RequestRoute::getSAEV(int routeIndex) const {
+SAEVehicle const *RequestRoute::getSAEV(int routeIndex) const {
     return _route[routeIndex].getSAEV();
 }
 
@@ -22,7 +22,7 @@ void RequestRoute::setSAEV(int routeIndex, SAEVehicle *saev) {
 
 }
 
-LineStop *RequestRoute::getLineStop(int routeIndex) const {
+LineStop const *RequestRoute::getLineStop(int routeIndex) const {
     return _route[routeIndex].getLineStop();
 }
 
diff --git a/src/routes/RequestRoute.h b/src/routes/RequestRoute.h
index 5c01c47..a32911c 100644
--- a/src/routes/RequestRoute.h
+++ b/src/routes/RequestRoute.h
@@ -22,15 +22,15 @@ private:
     Request* _requestPointer{nullptr};
 public:
     RequestRoute() = default;
-    explicit RequestRoute(Request* request) {_requestPointer = request; };
+    explicit RequestRoute(Request* request) : _requestPointer(request) {};
 
     [[nodiscard]] int getNodeIndex(int routeIndex) const;
     void setNodeIndex(int routeIndex, int nodeIndex);
 
-    [[nodiscard]] SAEVehicle *getSAEV(int routeIndex) const;
+    [[nodiscard]] const SAEVehicle *getSAEV(int routeIndex) const;
     void setSAEV(int routeIndex, SAEVehicle *saev);
 
-    [[nodiscard]] LineStop *getLineStop(int routeIndex) const;
+    [[nodiscard]] const LineStop *getLineStop(int routeIndex) const;
     void setLineStop(int routeIndex, LineStop *lineStop);
 
     [[nodiscard]] const RequestKeyPoint *getRoute() const;
diff --git a/src/routes/vehicle/SAEVKeyPoint.cpp b/src/routes/vehicle/SAEVKeyPoint.cpp
index 6f87535..04d2d23 100644
--- a/src/routes/vehicle/SAEVKeyPoint.cpp
+++ b/src/routes/vehicle/SAEVKeyPoint.cpp
@@ -48,8 +48,7 @@ void SAEVKeyPoint::setMaxTw(int maxTw) {
     _maxTW = maxTw;
 }
 
-SAEVKeyPoint::SAEVKeyPoint(const Graph &graph, const Request &request, bool isOrigin) {
-    _isOrigin = isOrigin;
+SAEVKeyPoint::SAEVKeyPoint(const Graph &graph, const Request &request, bool isOrigin) : _isOrigin(isOrigin), _requestPointer(&request) {
     if(isOrigin) {
         setNodeIndex(request.getOriginNodeIndex());
         _minTW = request.getArrivalTw().min - request.getDeltaTime();
@@ -74,11 +73,11 @@ void SAEVKeyPoint::setIsOrigin(bool isOrigin) {
     _isOrigin = isOrigin;
 }
 
-Request *SAEVKeyPoint::getRequest() const {
+Request const *SAEVKeyPoint::getRequest() const {
     return _requestPointer;
 }
 
-void SAEVKeyPoint::setRequest(Request *requestPointer) {
+void SAEVKeyPoint::setRequest(const Request *requestPointer) {
     _requestPointer = requestPointer;
 }
 
diff --git a/src/routes/vehicle/SAEVKeyPoint.h b/src/routes/vehicle/SAEVKeyPoint.h
index f08bc25..e293670 100644
--- a/src/routes/vehicle/SAEVKeyPoint.h
+++ b/src/routes/vehicle/SAEVKeyPoint.h
@@ -13,15 +13,15 @@
 
 class SAEVKeyPoint : public KeyPoint {
 private:
-    bool _isOrigin;
+    bool _isOrigin{};
     SAEVKeyPoint* _predecessor{nullptr};
     SAEVKeyPoint* _successor{nullptr};
     SAEVKeyPoint* _counterpart{nullptr};
     int _currentOccupation{0};
     int _minTW{0};
     int _maxTW{INT16_MAX};
-    SAEVehicle* _vehiclePointer{};
-    Request* _requestPointer;
+    SAEVehicle const * _vehiclePointer{};
+    Request const * _requestPointer{};
 public:
     /**
      * Depot KP initialization with [0;max] time windows
@@ -53,10 +53,10 @@ public:
     [[nodiscard]] bool isOrigin() const;
     void setIsOrigin(bool isOrigin);
 
-    [[nodiscard]] Request *getRequest() const;
-    void setRequest(Request *requestPointer);
+    [[nodiscard]] const Request *getRequest() const;
+    void setRequest(const Request *requestPointer);
 
-    SAEVKeyPoint *getCounterpart() const;
+    [[nodiscard]] SAEVKeyPoint *getCounterpart() const;
 
     void setCounterpart(SAEVKeyPoint *counterpart);
 
-- 
GitLab


From 2a7634745a536cc73ee80a9cd2742ddad74372e8 Mon Sep 17 00:00:00 2001
From: Romain BERNARD <romain.bernard@uca.fr>
Date: Fri, 24 May 2024 18:15:14 +0200
Subject: [PATCH 052/327] fix dependencies

---
 src/routes/vehicle/SAEVKeyPoint.h                | 3 +--
 src/routes/vehicle/propagation/SAEVRouteChange.h | 4 ++--
 2 files changed, 3 insertions(+), 4 deletions(-)

diff --git a/src/routes/vehicle/SAEVKeyPoint.h b/src/routes/vehicle/SAEVKeyPoint.h
index e293670..9ed9d23 100644
--- a/src/routes/vehicle/SAEVKeyPoint.h
+++ b/src/routes/vehicle/SAEVKeyPoint.h
@@ -6,10 +6,9 @@
 #define GREEDYALGORITHM_SAEVKEYPOINT_H
 
 
-#include "../../instance/requests/Request.h"
 #include "../KeyPoint.h"
 #include "../../instance/graph/Graph.h"
-#include "propagation/SAEVRouteChange.h"
+#include "../../instance/requests/Request.h"
 
 class SAEVKeyPoint : public KeyPoint {
 private:
diff --git a/src/routes/vehicle/propagation/SAEVRouteChange.h b/src/routes/vehicle/propagation/SAEVRouteChange.h
index 766c868..ac932e6 100644
--- a/src/routes/vehicle/propagation/SAEVRouteChange.h
+++ b/src/routes/vehicle/propagation/SAEVRouteChange.h
@@ -5,12 +5,11 @@
 #ifndef GREEDYALGORITHM_SAEVROUTECHANGE_H
 #define GREEDYALGORITHM_SAEVROUTECHANGE_H
 
-#include "../SAEVKeyPoint.h"
-
 enum Bound {
     Min, Max
 };
 
+class SAEVKeyPoint;
 class SAEVRouteChange {
 private:
     SAEVKeyPoint* const _kpPointer;
@@ -30,5 +29,6 @@ public:
     void revertChange();
 };
 
+#include "../SAEVKeyPoint.h"
 
 #endif //GREEDYALGORITHM_SAEVROUTECHANGE_H
-- 
GitLab


From b7a569bb9641f1af8a64ec17cb1787def282c276 Mon Sep 17 00:00:00 2001
From: Romain BERNARD <30secondstodraw@gmail.com>
Date: Mon, 27 May 2024 12:40:12 +0200
Subject: [PATCH 053/327] fix pair initialization in propagation

---
 src/routes/vehicle/SAEVRoute.cpp | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/src/routes/vehicle/SAEVRoute.cpp b/src/routes/vehicle/SAEVRoute.cpp
index 975ce71..6bab44e 100644
--- a/src/routes/vehicle/SAEVRoute.cpp
+++ b/src/routes/vehicle/SAEVRoute.cpp
@@ -154,8 +154,8 @@ SAEVRouteChangelist SAEVRoute::insertRequestWithPropagation(const int requestIdx
 
     //Initialize bound propagation signal queue (each item signals a modification done on one of a KeyPoint
     std::queue<std::pair<Bound, SAEVKeyPoint *>> boundPropagationQueue{};
-    const SAEVKeyPoint& originKP = getOrigin(requestIdx);
-    const SAEVKeyPoint& destinationKP = getDestination(requestIdx);
+    SAEVKeyPoint * originKP = &getOrigin(requestIdx);
+    SAEVKeyPoint * destinationKP = &getDestination(requestIdx);
     boundPropagationQueue.emplace(Min, originKP);
     boundPropagationQueue.emplace(Max, originKP);
     boundPropagationQueue.emplace(Min, destinationKP);
-- 
GitLab


From ae664712a7928f1fad7521d5f41f920f402d0438 Mon Sep 17 00:00:00 2001
From: Romain BERNARD <30secondstodraw@gmail.com>
Date: Sat, 1 Jun 2024 23:16:56 +0200
Subject: [PATCH 054/327] Move PT debug instances to their own folders

---
 .../basic_debug_instance/PT_lines.csv         |  0
 .../basic_debug_instance/edges.csv            |  0
 .../basic_debug_instance/graph.dat            | 21 +++++++++++++++++++
 .../basic_debug_instance/nodes.csv            |  0
 .../basic_debug_instance/params               |  0
 .../contiguous_lines_debug_instance/graph.dat |  0
 .../cycling_line_debug_instance/graph.dat     |  0
 .../graph.dat                                 |  0
 .../graph.dat                                 |  0
 .../graph.dat                                 |  0
 .../two_lines_debug_instance/graph.dat        |  0
 test/debug.cpp                                | 14 ++++++-------
 12 files changed, 28 insertions(+), 7 deletions(-)
 rename resources/test/instances/{ => PT Shortest Path}/basic_debug_instance/PT_lines.csv (100%)
 rename resources/test/instances/{ => PT Shortest Path}/basic_debug_instance/edges.csv (100%)
 create mode 100644 resources/test/instances/PT Shortest Path/basic_debug_instance/graph.dat
 rename resources/test/instances/{ => PT Shortest Path}/basic_debug_instance/nodes.csv (100%)
 rename resources/test/instances/{ => PT Shortest Path}/basic_debug_instance/params (100%)
 rename resources/test/instances/{ => PT Shortest Path}/contiguous_lines_debug_instance/graph.dat (100%)
 rename resources/test/instances/{ => PT Shortest Path}/cycling_line_debug_instance/graph.dat (100%)
 rename resources/test/instances/{ => PT Shortest Path}/multiple_crossing_lines_debug_instance/graph.dat (100%)
 rename resources/test/instances/{ => PT Shortest Path}/multiple_cycling_lines_debug_instance/graph.dat (100%)
 rename resources/test/instances/{ => PT Shortest Path}/single_node_lines_debug_instance/graph.dat (100%)
 rename resources/test/instances/{ => PT Shortest Path}/two_lines_debug_instance/graph.dat (100%)

diff --git a/resources/test/instances/basic_debug_instance/PT_lines.csv b/resources/test/instances/PT Shortest Path/basic_debug_instance/PT_lines.csv
similarity index 100%
rename from resources/test/instances/basic_debug_instance/PT_lines.csv
rename to resources/test/instances/PT Shortest Path/basic_debug_instance/PT_lines.csv
diff --git a/resources/test/instances/basic_debug_instance/edges.csv b/resources/test/instances/PT Shortest Path/basic_debug_instance/edges.csv
similarity index 100%
rename from resources/test/instances/basic_debug_instance/edges.csv
rename to resources/test/instances/PT Shortest Path/basic_debug_instance/edges.csv
diff --git a/resources/test/instances/PT Shortest Path/basic_debug_instance/graph.dat b/resources/test/instances/PT Shortest Path/basic_debug_instance/graph.dat
new file mode 100644
index 0000000..97764d4
--- /dev/null
+++ b/resources/test/instances/PT Shortest Path/basic_debug_instance/graph.dat	
@@ -0,0 +1,21 @@
+#Params (seed)
+123456789
+#Nodes format : status,x,y
+,0,7
+,1,6
+,2,5
+,3,4
+,4,3
+,5,2
+,6,1
+,7,0
+#Edges format : node_in,node_out,length
+0,1,1
+1,2,1
+2,3,2
+2,4,4
+4,5,2
+5,6,3
+6,7,2
+#PT line format : freq (min), start_time, end_time, node_1, ..., node_n
+15,340,560,3,4,5,6
\ No newline at end of file
diff --git a/resources/test/instances/basic_debug_instance/nodes.csv b/resources/test/instances/PT Shortest Path/basic_debug_instance/nodes.csv
similarity index 100%
rename from resources/test/instances/basic_debug_instance/nodes.csv
rename to resources/test/instances/PT Shortest Path/basic_debug_instance/nodes.csv
diff --git a/resources/test/instances/basic_debug_instance/params b/resources/test/instances/PT Shortest Path/basic_debug_instance/params
similarity index 100%
rename from resources/test/instances/basic_debug_instance/params
rename to resources/test/instances/PT Shortest Path/basic_debug_instance/params
diff --git a/resources/test/instances/contiguous_lines_debug_instance/graph.dat b/resources/test/instances/PT Shortest Path/contiguous_lines_debug_instance/graph.dat
similarity index 100%
rename from resources/test/instances/contiguous_lines_debug_instance/graph.dat
rename to resources/test/instances/PT Shortest Path/contiguous_lines_debug_instance/graph.dat
diff --git a/resources/test/instances/cycling_line_debug_instance/graph.dat b/resources/test/instances/PT Shortest Path/cycling_line_debug_instance/graph.dat
similarity index 100%
rename from resources/test/instances/cycling_line_debug_instance/graph.dat
rename to resources/test/instances/PT Shortest Path/cycling_line_debug_instance/graph.dat
diff --git a/resources/test/instances/multiple_crossing_lines_debug_instance/graph.dat b/resources/test/instances/PT Shortest Path/multiple_crossing_lines_debug_instance/graph.dat
similarity index 100%
rename from resources/test/instances/multiple_crossing_lines_debug_instance/graph.dat
rename to resources/test/instances/PT Shortest Path/multiple_crossing_lines_debug_instance/graph.dat
diff --git a/resources/test/instances/multiple_cycling_lines_debug_instance/graph.dat b/resources/test/instances/PT Shortest Path/multiple_cycling_lines_debug_instance/graph.dat
similarity index 100%
rename from resources/test/instances/multiple_cycling_lines_debug_instance/graph.dat
rename to resources/test/instances/PT Shortest Path/multiple_cycling_lines_debug_instance/graph.dat
diff --git a/resources/test/instances/single_node_lines_debug_instance/graph.dat b/resources/test/instances/PT Shortest Path/single_node_lines_debug_instance/graph.dat
similarity index 100%
rename from resources/test/instances/single_node_lines_debug_instance/graph.dat
rename to resources/test/instances/PT Shortest Path/single_node_lines_debug_instance/graph.dat
diff --git a/resources/test/instances/two_lines_debug_instance/graph.dat b/resources/test/instances/PT Shortest Path/two_lines_debug_instance/graph.dat
similarity index 100%
rename from resources/test/instances/two_lines_debug_instance/graph.dat
rename to resources/test/instances/PT Shortest Path/two_lines_debug_instance/graph.dat
diff --git a/test/debug.cpp b/test/debug.cpp
index 2b7f45f..5be6466 100644
--- a/test/debug.cpp
+++ b/test/debug.cpp
@@ -8,15 +8,15 @@
 #include "../src/ShortestPath/Transit/TransitShortestPathContainer.h"
 
 int main() {
-//    Graph give_me_a_name("../resources/test/instances/basic_debug_instance/nodes.csv",
-//          "../resources/test/instances/basic_debug_instance/edges.csv",
-//          "../resources/test/instances/basic_debug_instance/PT_lines.csv");
+//    Graph give_me_a_name("../resources/test/instances/PT Shortest Path/basic_debug_instance/nodes.csv",
+//          "../resources/test/instances/PT Shortest Path/basic_debug_instance/edges.csv",
+//          "../resources/test/instances/PT Shortest Path/basic_debug_instance/PT_lines.csv");
 
 //    std::string instanceFolder = "basic_debug_instance/";
     std::string instanceFolder = "contiguous_lines_debug_instance/";
     std::string datFile = "graph.dat";
 
-    Graph graphFromSingleFile("../resources/test/instances/" + instanceFolder + datFile);
+    Graph graphFromSingleFile("../resources/test/instances/PT Shortest Path/" + instanceFolder + datFile);
     graphFromSingleFile.exportGraphToFiles("../resources/test/outputs/" + instanceFolder);
     TransitShortestPathContainer contiguousContainer(graphFromSingleFile.getNbNodes());
     for(auto& ptLine : graphFromSingleFile.getPTLines()) {
@@ -30,7 +30,7 @@ int main() {
     }
 
     TransitShortestPathContainer crossingContainer(graphFromSingleFile.getNbNodes());
-    Graph crossingLinesGraph("../resources/test/instances/multiple_crossing_lines_debug_instance/" + datFile);
+    Graph crossingLinesGraph("../resources/test/instances/PT Shortest Path/multiple_crossing_lines_debug_instance/" + datFile);
     for(auto& ptLine : crossingLinesGraph.getPTLines()) {
         for(int i = 0; i < ptLine.size(); ++i) {
             for (auto& startingTime: ptLine.getTimetable(i)) {
@@ -42,7 +42,7 @@ int main() {
     }
 
     TransitShortestPathContainer cycleContainer(graphFromSingleFile.getNbNodes());
-    Graph cyclingLineGraph("../resources/test/instances/cycling_line_debug_instance/" + datFile);
+    Graph cyclingLineGraph("../resources/test/instances/PT Shortest Path/cycling_line_debug_instance/" + datFile);
     for(auto& ptLine : cyclingLineGraph.getPTLines()) {
         for(int i = 0; i < ptLine.size(); ++i) {
             for (auto& startingTime: ptLine.getTimetable(i)) {
@@ -55,7 +55,7 @@ int main() {
 
 
     TransitShortestPathContainer multiCycleContainer(graphFromSingleFile.getNbNodes());
-    Graph multipleCyclingLinesGraph("../resources/test/instances/multiple_cycling_lines_debug_instance/" + datFile);
+    Graph multipleCyclingLinesGraph("../resources/test/instances/PT Shortest Path/multiple_cycling_lines_debug_instance/" + datFile);
     for(auto& ptLine : multipleCyclingLinesGraph.getPTLines()) {
         for(int i = 0; i < ptLine.size(); ++i) {
             for (auto& startingTime: ptLine.getTimetable(i)) {
-- 
GitLab


From 40176ad95b7a192c61417863a18dfbf870f3482c Mon Sep 17 00:00:00 2001
From: Romain BERNARD <30secondstodraw@gmail.com>
Date: Sun, 2 Jun 2024 02:02:39 +0200
Subject: [PATCH 055/327] properly retrieve the seed

---
 src/instance/graph/Graph.cpp | 3 +--
 1 file changed, 1 insertion(+), 2 deletions(-)

diff --git a/src/instance/graph/Graph.cpp b/src/instance/graph/Graph.cpp
index 0a7f9bf..1db9c6a 100644
--- a/src/instance/graph/Graph.cpp
+++ b/src/instance/graph/Graph.cpp
@@ -69,7 +69,6 @@ Graph::Graph(const std::string& nodesFilePath, const std::string& edgesFilePath,
 Graph::Graph(const std::string& datFilePath) {
     std::ifstream infile(datFilePath);
     DATRow currentRow = DATRow(',');
-    std::string currentLine;
 
     //-- Read params
     infile >> currentRow;
@@ -77,7 +76,7 @@ Graph::Graph(const std::string& datFilePath) {
     // Seeded random number generator
     infile >> currentRow;
     unsigned long rngSeed;
-    std::from_chars(currentRow[1].data(), currentRow[1].data() + currentRow[1].length(), rngSeed);
+    std::from_chars(currentRow[0].data(), currentRow[0].data() + currentRow[0].length(), rngSeed);
     auto rng = std::mt19937(rngSeed);
     //-- End of params
 
-- 
GitLab


From 2f15321b22a6f2ec9d8f4c0d3a7ed2faf694b43e Mon Sep 17 00:00:00 2001
From: Romain BERNARD <30secondstodraw@gmail.com>
Date: Sun, 2 Jun 2024 02:06:47 +0200
Subject: [PATCH 056/327] move transit preprocess debug to its own file

---
 CMakeLists.txt                                |  1 -
 test/CMakeLists.txt                           | 41 ++++++++++++++++++-
 .../TransitPreprocessDebug.cpp}               | 39 +++++++++---------
 test/src/TransitPreprocessUnitTest.cpp        |  3 --
 4 files changed, 58 insertions(+), 26 deletions(-)
 rename test/{debug.cpp => src/TransitPreprocessDebug.cpp} (53%)
 delete mode 100644 test/src/TransitPreprocessUnitTest.cpp

diff --git a/CMakeLists.txt b/CMakeLists.txt
index 30775c8..a95788a 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -25,7 +25,6 @@ add_executable(GreedyAlgorithm
         src/instance/graph/Line.h
         src/services/CSV/CSVRange.h
         src/services/CSV/CSVIterator.h
-        test/debug.cpp
         src/instance/graph/LineStop.cpp
         src/instance/graph/LineStop.h
         src/services/DatFile/DATRow.h
diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt
index 451d74d..6e1f7bf 100644
--- a/test/CMakeLists.txt
+++ b/test/CMakeLists.txt
@@ -18,6 +18,43 @@ add_executable(Line_UT
         ../src/instance/graph/Line.cpp
         ../src/instance/graph/Line.h
 )
-add_executable(Transit_preprocess_UT src/TransitPreprocessUnitTest.cpp)
+
+add_executable(Transit_preprocess_DEB
+        src/TransitPreprocessDebug.cpp
+        ../src/instance/graph/Node.cpp
+        ../src/instance/graph/Node.h
+        ../src/instance/graph/Edge.cpp
+        ../src/instance/graph/Edge.h
+        ../src/instance/graph/Graph.cpp
+        ../src/instance/graph/Graph.h
+        ../src/instance/graph/Line.cpp
+        ../src/instance/graph/Line.h
+        ../src/routes/KeyPoint.cpp
+        ../src/routes/KeyPoint.h
+        ../src/ShortestPath/Transit/TransitShortestPathContainer.cpp
+        ../src/ShortestPath/Transit/TransitShortestPathContainer.h
+        ../src/ShortestPath/Transit/TransitShortestPathPrecompute.cpp
+        ../src/ShortestPath/Transit/TransitShortestPathPrecompute.h
+)
+
+
+add_executable(Constraint_Propag_DEB
+        src/ConstraintPropagationDebug.cpp
+        ../src/instance/graph/Node.cpp
+        ../src/instance/graph/Node.h
+        ../src/instance/graph/Edge.cpp
+        ../src/instance/graph/Edge.h
+        ../src/instance/graph/Graph.cpp
+        ../src/instance/graph/Graph.h
+        ../src/instance/graph/Line.cpp
+        ../src/instance/graph/Line.h
+        ../src/routes/vehicle/SAEVRoute.cpp
+        ../src/routes/vehicle/SAEVRoute.h
+        src/ConstraintPropagationDebug.cpp
+        src/ConstraintPropagationDebug.cpp
+        src/ConstraintPropagationDebug.cpp
+)
+
 target_link_libraries(Line_UT gtest gtest_main)
-target_link_libraries(Transit_preprocess_UT gtest gtest_main)
\ No newline at end of file
+target_link_libraries(Transit_preprocess_DEB gtest gtest_main)
+target_link_libraries(Constraint_Propag_DEB gtest gtest_main)
\ No newline at end of file
diff --git a/test/debug.cpp b/test/src/TransitPreprocessDebug.cpp
similarity index 53%
rename from test/debug.cpp
rename to test/src/TransitPreprocessDebug.cpp
index 5be6466..66d1bba 100644
--- a/test/debug.cpp
+++ b/test/src/TransitPreprocessDebug.cpp
@@ -1,53 +1,49 @@
 //
-// Created by rbernard on 30/01/2024.
+// Created by romain on 20/03/24.
 //
-#include <iostream>
-#include "../src/instance/graph/Graph.h"
-#include "../src/ShortestPath/Transit/TransitStateContainer.h"
-#include "../src/ShortestPath/Transit/TransitShortestPathPrecompute.h"
-#include "../src/ShortestPath/Transit/TransitShortestPathContainer.h"
 
-int main() {
-//    Graph give_me_a_name("../resources/test/instances/PT Shortest Path/basic_debug_instance/nodes.csv",
-//          "../resources/test/instances/PT Shortest Path/basic_debug_instance/edges.csv",
-//          "../resources/test/instances/PT Shortest Path/basic_debug_instance/PT_lines.csv");
+#include "../lib/googletest/googletest/include/gtest/gtest.h"
+#include "../../src/instance/graph/Graph.h"
+#include "../../src/ShortestPath/Transit/TransitShortestPathContainer.h"
+#include "../../src/ShortestPath/Transit/TransitShortestPathPrecompute.h"
 
-//    std::string instanceFolder = "basic_debug_instance/";
+TEST(TransitPreprocessUnitTest, DebugFunction) {
+    std::string instancesPath = "../../resources/test/instances/PT Shortest Path/";
     std::string instanceFolder = "contiguous_lines_debug_instance/";
     std::string datFile = "graph.dat";
 
-    Graph graphFromSingleFile("../resources/test/instances/PT Shortest Path/" + instanceFolder + datFile);
+    Graph graphFromSingleFile(instancesPath + instanceFolder + datFile);
     graphFromSingleFile.exportGraphToFiles("../resources/test/outputs/" + instanceFolder);
     TransitShortestPathContainer contiguousContainer(graphFromSingleFile.getNbNodes());
     for(auto& ptLine : graphFromSingleFile.getPTLines()) {
         for(int i = 0; i < ptLine.size(); ++i) {
             for (auto& startingTime: ptLine.getTimetable(i)) {
                 contiguousContainer.addShortestPathCollection(i, startingTime, graphFromSingleFile.getNbNodes(),
-                                                              TransitShortestPathPrecompute::executeAlgorithm(graphFromSingleFile, ptLine.getNode(i),startingTime));
+                        TransitShortestPathPrecompute::executeAlgorithm(graphFromSingleFile, ptLine.getNode(i),startingTime));
                 contiguousContainer.getShortestPathsFromTime(i, startingTime - 1);
             }
         }
     }
 
     TransitShortestPathContainer crossingContainer(graphFromSingleFile.getNbNodes());
-    Graph crossingLinesGraph("../resources/test/instances/PT Shortest Path/multiple_crossing_lines_debug_instance/" + datFile);
+    Graph crossingLinesGraph(instancesPath + "multiple_crossing_lines_debug_instance/" + datFile);
     for(auto& ptLine : crossingLinesGraph.getPTLines()) {
         for(int i = 0; i < ptLine.size(); ++i) {
             for (auto& startingTime: ptLine.getTimetable(i)) {
                 crossingContainer.addShortestPathCollection(i, startingTime, crossingLinesGraph.getNbNodes(),
-                                                              TransitShortestPathPrecompute::executeAlgorithm(crossingLinesGraph, ptLine.getNode(i),startingTime));
+                        TransitShortestPathPrecompute::executeAlgorithm(crossingLinesGraph, ptLine.getNode(i),startingTime));
                 crossingContainer.getShortestPathsFromTime(i, startingTime - 1);
             }
         }
     }
 
     TransitShortestPathContainer cycleContainer(graphFromSingleFile.getNbNodes());
-    Graph cyclingLineGraph("../resources/test/instances/PT Shortest Path/cycling_line_debug_instance/" + datFile);
+    Graph cyclingLineGraph(instancesPath + "cycling_line_debug_instance/" + datFile);
     for(auto& ptLine : cyclingLineGraph.getPTLines()) {
         for(int i = 0; i < ptLine.size(); ++i) {
             for (auto& startingTime: ptLine.getTimetable(i)) {
                 cycleContainer.addShortestPathCollection(i, startingTime, cyclingLineGraph.getNbNodes(),
-                                                              TransitShortestPathPrecompute::executeAlgorithm(cyclingLineGraph, ptLine.getNode(i),startingTime));
+                        TransitShortestPathPrecompute::executeAlgorithm(cyclingLineGraph, ptLine.getNode(i),startingTime));
                 cycleContainer.getShortestPathsFromTime(i, startingTime - 1);
             }
         }
@@ -55,16 +51,19 @@ int main() {
 
 
     TransitShortestPathContainer multiCycleContainer(graphFromSingleFile.getNbNodes());
-    Graph multipleCyclingLinesGraph("../resources/test/instances/PT Shortest Path/multiple_cycling_lines_debug_instance/" + datFile);
+    Graph multipleCyclingLinesGraph(instancesPath + "multiple_cycling_lines_debug_instance/" + datFile);
     for(auto& ptLine : multipleCyclingLinesGraph.getPTLines()) {
         for(int i = 0; i < ptLine.size(); ++i) {
             for (auto& startingTime: ptLine.getTimetable(i)) {
                 multiCycleContainer.addShortestPathCollection(i, startingTime, multipleCyclingLinesGraph.getNbNodes(),
-                                                               TransitShortestPathPrecompute::executeAlgorithm(multipleCyclingLinesGraph, ptLine.getNode(i),startingTime));
+                        TransitShortestPathPrecompute::executeAlgorithm(multipleCyclingLinesGraph, ptLine.getNode(i),startingTime));
                 multiCycleContainer.getShortestPathsFromTime(i, startingTime - 1);
             }
         }
     }
+}
 
-    return 0;
+int main(int argc, char* argv[]) {
+    testing::InitGoogleTest(&argc, argv);
+    return RUN_ALL_TESTS();
 }
\ No newline at end of file
diff --git a/test/src/TransitPreprocessUnitTest.cpp b/test/src/TransitPreprocessUnitTest.cpp
deleted file mode 100644
index e211100..0000000
--- a/test/src/TransitPreprocessUnitTest.cpp
+++ /dev/null
@@ -1,3 +0,0 @@
-//
-// Created by romain on 20/03/24.
-//
-- 
GitLab


From 3de9cc4b936d59e5ebd45d12e18e0d647f93bd06 Mon Sep 17 00:00:00 2001
From: Romain BERNARD <30secondstodraw@gmail.com>
Date: Sun, 2 Jun 2024 02:46:50 +0200
Subject: [PATCH 057/327] Add base instance for constraint propagation debug

---
 .../basic_debug_instance/graph.dat            | 16 ++++++++++++++
 .../basic_debug_instance/requests.dat         |  6 ++++++
 .../instances/basic_debug_instance/graph.dat  | 21 -------------------
 test/CMakeLists.txt                           | 19 ++++++++++++++---
 4 files changed, 38 insertions(+), 24 deletions(-)
 create mode 100644 resources/test/instances/Constraint Propagation/basic_debug_instance/graph.dat
 create mode 100644 resources/test/instances/Constraint Propagation/basic_debug_instance/requests.dat
 delete mode 100644 resources/test/instances/basic_debug_instance/graph.dat

diff --git a/resources/test/instances/Constraint Propagation/basic_debug_instance/graph.dat b/resources/test/instances/Constraint Propagation/basic_debug_instance/graph.dat
new file mode 100644
index 0000000..110d845
--- /dev/null
+++ b/resources/test/instances/Constraint Propagation/basic_debug_instance/graph.dat	
@@ -0,0 +1,16 @@
+#Params (seed)
+123456789
+#Nodes format : status (work, leisure, residential),x,y
+residential,0,0
+residential,0,1
+work,1,0
+work,1,1
+#Matrix
+0,10,10,20
+10,0,20,10
+10,20,0,10
+20,10,10,0
+#PT line format : freq (min), start_time, end_time, node_1, ..., node_n
+15,340,560,1,2
+#Depot node index
+0
\ No newline at end of file
diff --git a/resources/test/instances/Constraint Propagation/basic_debug_instance/requests.dat b/resources/test/instances/Constraint Propagation/basic_debug_instance/requests.dat
new file mode 100644
index 0000000..59a584e
--- /dev/null
+++ b/resources/test/instances/Constraint Propagation/basic_debug_instance/requests.dat	
@@ -0,0 +1,6 @@
+#Global Params (delta ratio)
+1
+#Requests (origin_idx,destination_idx,min,max,delta baseline,capacity)
+0,3,510,540,30,1
+1,2,520,545,25,1
+#Expected result for end route D->R1.O->R2.O->R1.D->R2.D->D : [495;515],[505;520],[515;535],[525;545]
\ No newline at end of file
diff --git a/resources/test/instances/basic_debug_instance/graph.dat b/resources/test/instances/basic_debug_instance/graph.dat
deleted file mode 100644
index 97764d4..0000000
--- a/resources/test/instances/basic_debug_instance/graph.dat
+++ /dev/null
@@ -1,21 +0,0 @@
-#Params (seed)
-123456789
-#Nodes format : status,x,y
-,0,7
-,1,6
-,2,5
-,3,4
-,4,3
-,5,2
-,6,1
-,7,0
-#Edges format : node_in,node_out,length
-0,1,1
-1,2,1
-2,3,2
-2,4,4
-4,5,2
-5,6,3
-6,7,2
-#PT line format : freq (min), start_time, end_time, node_1, ..., node_n
-15,340,560,3,4,5,6
\ No newline at end of file
diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt
index 6e1f7bf..eef950b 100644
--- a/test/CMakeLists.txt
+++ b/test/CMakeLists.txt
@@ -40,6 +40,8 @@ add_executable(Transit_preprocess_DEB
 
 add_executable(Constraint_Propag_DEB
         src/ConstraintPropagationDebug.cpp
+        ../src/TimeWindow.cpp
+        ../src/TimeWindow.h
         ../src/instance/graph/Node.cpp
         ../src/instance/graph/Node.h
         ../src/instance/graph/Edge.cpp
@@ -48,11 +50,22 @@ add_executable(Constraint_Propag_DEB
         ../src/instance/graph/Graph.h
         ../src/instance/graph/Line.cpp
         ../src/instance/graph/Line.h
+        ../src/instance/requests/Request.cpp
+        ../src/instance/requests/Request.h
         ../src/routes/vehicle/SAEVRoute.cpp
         ../src/routes/vehicle/SAEVRoute.h
-        src/ConstraintPropagationDebug.cpp
-        src/ConstraintPropagationDebug.cpp
-        src/ConstraintPropagationDebug.cpp
+        ../src/routes/vehicle/propagation/SAEVRouteChange.cpp
+        ../src/routes/vehicle/propagation/SAEVRouteChange.h
+        ../src/routes/vehicle/propagation/SAEVRouteChangelist.cpp
+        ../src/routes/vehicle/propagation/SAEVRouteChangelist.h
+        ../src/routes/vehicle/SAEVKeyPoint.cpp
+        ../src/routes/vehicle/SAEVKeyPoint.h
+        ../src/routes/KeyPoint.cpp
+        ../src/routes/KeyPoint.h
+        ../src/routes/RequestKeyPoint.cpp
+        ../src/routes/RequestKeyPoint.h
+        ../src/routes/RequestRoute.cpp
+        ../src/routes/RequestRoute.h
 )
 
 target_link_libraries(Line_UT gtest gtest_main)
-- 
GitLab


From 366ba8503ab2160571c5cc3a8e34c416ac04419d Mon Sep 17 00:00:00 2001
From: Romain BERNARD <30secondstodraw@gmail.com>
Date: Sun, 2 Jun 2024 02:47:15 +0200
Subject: [PATCH 058/327] Add parse functions for requests in instance file

---
 src/instance/requests/Request.cpp | 44 +++++++++++++++++++++++++++++++
 src/instance/requests/Request.h   |  3 +++
 2 files changed, 47 insertions(+)

diff --git a/src/instance/requests/Request.cpp b/src/instance/requests/Request.cpp
index dca7175..72c822f 100644
--- a/src/instance/requests/Request.cpp
+++ b/src/instance/requests/Request.cpp
@@ -39,6 +39,50 @@ Request::Request(const DATRow& currentRow, const Graph& graph) {
     _departureTW.max = _arrivalTW.max - graph.getShortestSAEVPath(_originNodeIndex, _destinationNodeIndex);
 }
 
+Request::Request(const DATRow& currentRow, double deltaRatio, const Graph& graph) {
+    std::from_chars(currentRow[0].data(), currentRow[0].data() + currentRow[0].size(), _originNodeIndex);
+    std::from_chars(currentRow[1].data(), currentRow[1].data() + currentRow[1].size(), _destinationNodeIndex);
+
+    int twMin, twMax;
+    std::from_chars(currentRow[2].data(), currentRow[2].data() + currentRow[2].size(), twMin);
+    std::from_chars(currentRow[3].data(), currentRow[3].data() + currentRow[3].size(), twMax);
+    _arrivalTW = TimeWindow(twMin, twMax);
+
+    //Assign value (direct time to
+    std::from_chars(currentRow[4].data(), currentRow[4].data() + currentRow[4].size(), _deltaTime);
+    _deltaTime = floor(_deltaTime * deltaRatio);
+
+    std::from_chars(currentRow[5].data(), currentRow[5].data() + currentRow[5].size(), _weight);
+
+    _departureTW.min = _arrivalTW.min - _currentDeltaTime;
+    _departureTW.max = _arrivalTW.max - graph.getShortestSAEVPath(_originNodeIndex, _destinationNodeIndex);
+}
+
+std::vector<Request> Request::getRequestsFromFile(const std::string& datFilePath, const Graph& graph) {
+    std::vector<Request> requests;
+
+    std::ifstream infile(datFilePath);
+    DATRow currentRow = DATRow(',');
+
+    //-- Read params
+    infile >> currentRow;
+    std::cout << currentRow[0] << std::endl;
+    // Delta ratio
+    infile >> currentRow;
+    double deltaRatio;
+    std::from_chars(currentRow[0].data(), currentRow[0].data() + currentRow[0].length(), deltaRatio);
+    //-- End of params
+
+    //-- Read requests
+    infile >> currentRow; // Read and print comment line for format
+    std::cout << currentRow.toString() << std::endl;
+    while(infile >> currentRow && !currentRow[0].starts_with('#')) {
+        requests.emplace_back(currentRow, deltaRatio, graph);
+    }
+
+    return requests;
+}
+
 const int Request::getOriginNodeIndex() const {
     return _originNodeIndex;
 }
diff --git a/src/instance/requests/Request.h b/src/instance/requests/Request.h
index 6763a59..ccedd76 100644
--- a/src/instance/requests/Request.h
+++ b/src/instance/requests/Request.h
@@ -31,6 +31,9 @@ public:
     Request(const int departureNodeIndex, const int arrivalNodeIndex, const TimeWindow &arrivalTw,
             const int deltaTime, const int weight, const Graph& graph);
     Request(const DATRow& currentRow, const Graph& graph);
+    Request(const DATRow& currentRow, double deltaRatio, const Graph& graph);
+
+    static std::vector<Request> getRequestsFromFile(const std::string& datFilePath, const Graph& graph);
 
     //Getters
     [[nodiscard]] const int getOriginNodeIndex() const;
-- 
GitLab


From c33d95d50dfd9504cdb5cd704ed4418725fbc6b3 Mon Sep 17 00:00:00 2001
From: Romain BERNARD <30secondstodraw@gmail.com>
Date: Sun, 2 Jun 2024 02:47:29 +0200
Subject: [PATCH 059/327] Init propag debug file

---
 test/src/ConstraintPropagationDebug.cpp | 28 +++++++++++++++++++++++++
 1 file changed, 28 insertions(+)
 create mode 100644 test/src/ConstraintPropagationDebug.cpp

diff --git a/test/src/ConstraintPropagationDebug.cpp b/test/src/ConstraintPropagationDebug.cpp
new file mode 100644
index 0000000..7ed1f25
--- /dev/null
+++ b/test/src/ConstraintPropagationDebug.cpp
@@ -0,0 +1,28 @@
+//
+// Created by romain on 20/03/24.
+//
+
+#include "../lib/googletest/googletest/include/gtest/gtest.h"
+#include "../../src/instance/graph/Graph.h"
+#include "../../src/ShortestPath/Transit/TransitShortestPathContainer.h"
+#include "../../src/ShortestPath/Transit/TransitShortestPathPrecompute.h"
+#include "../../src/instance/Instance.h"
+
+TEST(TransitPreprocessUnitTest, DebugFunction) {
+    std::string instancesPath = "../../resources/test/instances/Constraint Propagation/";
+    std::string instanceFolder = "basic_debug_instance/";
+    std::string graphDatFile = "graph.dat";
+    std::string requestsDatFile = "requests.dat";
+
+    //Parse graph
+    Graph graphFromSingleFile(instancesPath + instanceFolder + graphDatFile);
+    std::vector<Request> requests = Request::getRequestsFromFile(instancesPath + instanceFolder + requestsDatFile, graphFromSingleFile);
+
+    //Init instance
+    Instance instance(requests,graphFromSingleFile,4);
+}
+
+int main(int argc, char* argv[]) {
+    testing::InitGoogleTest(&argc, argv);
+    return RUN_ALL_TESTS();
+}
\ No newline at end of file
-- 
GitLab


From be2703f9aca03ec96ebae4cf6a7f96c4c8d3d59d Mon Sep 17 00:00:00 2001
From: Romain BERNARD <30secondstodraw@gmail.com>
Date: Sun, 2 Jun 2024 16:49:37 +0200
Subject: [PATCH 060/327] route insertion and initialization fix

---
 src/routes/vehicle/SAEVRoute.cpp | 42 +++++++++++++++++++++-----------
 1 file changed, 28 insertions(+), 14 deletions(-)

diff --git a/src/routes/vehicle/SAEVRoute.cpp b/src/routes/vehicle/SAEVRoute.cpp
index 6bab44e..09cd40c 100644
--- a/src/routes/vehicle/SAEVRoute.cpp
+++ b/src/routes/vehicle/SAEVRoute.cpp
@@ -6,7 +6,7 @@
 #include "SAEVRoute.h"
 
 SAEVRoute::SAEVRoute(const Graph& graph, const std::vector<Request>& requestList) : _nbRequest(requestList.size()), _graph(&graph), _requestList(&requestList) {
-    _route.reserve(_nbRequest*4); //nbRequest*2 O/D KeyPoints + nbRequest*2 Start/End depots (upper bound #vehicle = #requests
+    _route.resize(_nbRequest*4); //nbRequest*2 O/D KeyPoints + nbRequest*2 Start/End depots (upper bound #vehicle = #requests
 
     //Init Request O/D and Depot start/end key points
     for(size_t i = 0; i < _nbRequest; ++i) {
@@ -23,29 +23,43 @@ SAEVRoute::SAEVRoute(const Graph& graph, const std::vector<Request>& requestList
         //Link Origin depots and Destination depots
         getOriginDepot(i).setCounterpart(&getDestinationDepot(i));
         getDestinationDepot(i).setCounterpart(&getOriginDepot(i));
+        getOriginDepot(i).setSuccessor(&getDestinationDepot(i));
+        getDestinationDepot(i).setPredecessor(&getOriginDepot(i));
     }
 }
 
 void SAEVRoute::insertRequest(int requestIdx, int originRequestPredecessorIdx, int destinationRequestPredecessorIdx) {
-    SAEVKeyPoint& originKp = _route.at(requestIdx);
-    SAEVKeyPoint& destinationKp = _route.at(requestIdx + 1);
+    SAEVKeyPoint& originKp = getOrigin(requestIdx);
+    SAEVKeyPoint& destinationKp = getDestination(requestIdx);
 
     SAEVKeyPoint& originPredKp = _route.at(originRequestPredecessorIdx);
     SAEVKeyPoint *originSuccKp = originPredKp.getSuccessor();
     SAEVKeyPoint& destinationPredKp = _route.at(destinationRequestPredecessorIdx);
     SAEVKeyPoint *destinationSuccKp = destinationPredKp.getSuccessor();
 
-    //Set values for O/D KPs
-    originKp.setPredecessor(&originPredKp);
-    originKp.setSuccessor(originSuccKp);
-    destinationKp.setPredecessor(&destinationPredKp);
-    destinationKp.setSuccessor(destinationSuccKp);
-
-    //Set values for predecessors/successors
-    originPredKp.setSuccessor(&originKp);
-    originSuccKp->setPredecessor(&originKp);
-    destinationPredKp.setSuccessor(&destinationKp);
-    destinationSuccKp->setPredecessor(&destinationKp);
+    if(originRequestPredecessorIdx != destinationRequestPredecessorIdx) {
+        //Set values for O/D KPs
+        originKp.setPredecessor(&originPredKp);
+        originKp.setSuccessor(originSuccKp);
+        destinationKp.setPredecessor(&destinationPredKp);
+        destinationKp.setSuccessor(destinationSuccKp);
+
+        //Set values for predecessors/successors
+        originPredKp.setSuccessor(&originKp);
+        originSuccKp->setPredecessor(&originKp);
+        destinationPredKp.setSuccessor(&destinationKp);
+        destinationSuccKp->setPredecessor(&destinationKp);
+    } else {
+        //Set values for O/D KPs
+        originKp.setPredecessor(&originPredKp);
+        originKp.setSuccessor(&destinationKp);
+        destinationKp.setPredecessor(&originKp);
+        destinationKp.setSuccessor(destinationSuccKp);
+
+        //Set values for predecessors/successors
+        originPredKp.setSuccessor(&originKp);
+        originSuccKp->setPredecessor(&destinationKp);
+    }
 }
 
 void SAEVRoute::removeRequest(int requestIdx) {
-- 
GitLab


From fa65fa59e2ac7b2cdb2efd48ebb8f186a8475ff3 Mon Sep 17 00:00:00 2001
From: Romain BERNARD <30secondstodraw@gmail.com>
Date: Sun, 2 Jun 2024 16:50:03 +0200
Subject: [PATCH 061/327] utilitary request/depot index functions

---
 src/routes/vehicle/SAEVRoute.h | 6 ++++++
 1 file changed, 6 insertions(+)

diff --git a/src/routes/vehicle/SAEVRoute.h b/src/routes/vehicle/SAEVRoute.h
index 273db54..9071ae3 100644
--- a/src/routes/vehicle/SAEVRoute.h
+++ b/src/routes/vehicle/SAEVRoute.h
@@ -98,6 +98,12 @@ public:
 
     SAEVKeyPoint& getOriginDepot(const size_t vehicleId) { return _route.at(_nbRequest + vehicleId*2);}
     SAEVKeyPoint& getDestinationDepot(const size_t vehicleId) { return _route.at(_nbRequest + vehicleId*2 + 1);}
+
+    [[nodiscard]] size_t getRequestOriginIdx(const size_t requestIdx) const { return requestIdx * 2;}
+    [[nodiscard]] size_t getRequestDestinationIdx(const size_t requestIdx) const { return requestIdx * 2 + 1;}
+
+    [[nodiscard]] size_t getOriginDepotIdx(const size_t vehicleId) const { return _nbRequest + vehicleId*2;}
+    [[nodiscard]] size_t getDestinationDepotIdx(const size_t vehicleId) const { return _nbRequest + vehicleId*2 + 1;}
 };
 
 #include "propagation/SAEVRouteChangelist.h"
-- 
GitLab


From d8a33399f4e055d3dc05f71bb7f2c90c7bcd82c9 Mon Sep 17 00:00:00 2001
From: Romain BERNARD <30secondstodraw@gmail.com>
Date: Sun, 2 Jun 2024 22:57:02 +0200
Subject: [PATCH 062/327] Add depot node index to depot route nodes

---
 src/instance/graph/Graph.cpp        | 13 +++++++++++++
 src/instance/graph/Graph.h          |  4 ++++
 src/routes/vehicle/SAEVKeyPoint.cpp |  5 +++++
 src/routes/vehicle/SAEVKeyPoint.h   |  7 ++++++-
 src/routes/vehicle/SAEVRoute.cpp    |  4 ++--
 5 files changed, 30 insertions(+), 3 deletions(-)

diff --git a/src/instance/graph/Graph.cpp b/src/instance/graph/Graph.cpp
index 1db9c6a..3eb551a 100644
--- a/src/instance/graph/Graph.cpp
+++ b/src/instance/graph/Graph.cpp
@@ -103,6 +103,11 @@ Graph::Graph(const std::string& datFilePath) {
         //-- End of edges
     }
 
+    if(currentRow[0].starts_with("#Depot")) {
+        infile >> currentRow;
+        std::from_chars(currentRow[0].data(), currentRow[0].data() + currentRow[0].length(), _depotNodeIdx);
+    }
+
     //-- Read Public transit line
     std::cout << currentRow.toString() << std::endl;
     std::uniform_int_distribution<uint32_t> uint_dist10(1,10);
@@ -304,3 +309,11 @@ void Graph::parseDistanceMatrix(std::ifstream &infile, DATRow currentRow) {
         }
     }
 }
+
+int Graph::getDepotNodeIdx() const {
+    return _depotNodeIdx;
+}
+
+void Graph::setDepotNodeIdx(int depotNodeIdx) {
+    _depotNodeIdx = depotNodeIdx;
+}
diff --git a/src/instance/graph/Graph.h b/src/instance/graph/Graph.h
index 1027abf..1e37b62 100644
--- a/src/instance/graph/Graph.h
+++ b/src/instance/graph/Graph.h
@@ -21,6 +21,7 @@ private:
     std::vector<Edge> edgesVector;
     std::vector<Line> transitLines;
     std::vector<std::vector<int>> shortestSAEVPaths;
+    int _depotNodeIdx{0}; //Index of the depot node, defaults to 0, the first node created in the graph
 
     /**
      * For every LineStop on every node of the graph, verify the node returned by looking into LineStop->Line(stopIdx)
@@ -55,6 +56,9 @@ public:
         return nodesVector.at(nodeIndex).getPTLinesSet().size();
     }
 
+    [[nodiscard]] int getDepotNodeIdx() const;
+    void setDepotNodeIdx(int depotNodeIdx);
+
     /**
      * @return The graph's edge vector
      */
diff --git a/src/routes/vehicle/SAEVKeyPoint.cpp b/src/routes/vehicle/SAEVKeyPoint.cpp
index 04d2d23..1a05eb9 100644
--- a/src/routes/vehicle/SAEVKeyPoint.cpp
+++ b/src/routes/vehicle/SAEVKeyPoint.cpp
@@ -88,3 +88,8 @@ SAEVKeyPoint *SAEVKeyPoint::getCounterpart() const {
 void SAEVKeyPoint::setCounterpart(SAEVKeyPoint *counterpart) {
     _counterpart = counterpart;
 }
+
+SAEVKeyPoint::SAEVKeyPoint(int depotNodeIdx) : KeyPoint(depotNodeIdx) {
+    _isDepot = true;
+    setNodeIndex(depotNodeIdx);
+}
diff --git a/src/routes/vehicle/SAEVKeyPoint.h b/src/routes/vehicle/SAEVKeyPoint.h
index 9ed9d23..9682356 100644
--- a/src/routes/vehicle/SAEVKeyPoint.h
+++ b/src/routes/vehicle/SAEVKeyPoint.h
@@ -13,6 +13,7 @@
 class SAEVKeyPoint : public KeyPoint {
 private:
     bool _isOrigin{};
+    bool _isDepot{false};
     SAEVKeyPoint* _predecessor{nullptr};
     SAEVKeyPoint* _successor{nullptr};
     SAEVKeyPoint* _counterpart{nullptr};
@@ -23,9 +24,13 @@ private:
     Request const * _requestPointer{};
 public:
     /**
-     * Depot KP initialization with [0;max] time windows
+     * Default KP constructor to allow pre-allocation of our route vector
      */
     SAEVKeyPoint() = default;
+    /**
+     * Depot KP initialization with [0;max] time windows and a depot node index
+     */
+    explicit SAEVKeyPoint(int depotNodeIdx);
     /**
      * SAEV KP initialization
      * @param graph the instance's graph, used to get shortest path and estimate start time windows relative to distances
diff --git a/src/routes/vehicle/SAEVRoute.cpp b/src/routes/vehicle/SAEVRoute.cpp
index 09cd40c..21e36f9 100644
--- a/src/routes/vehicle/SAEVRoute.cpp
+++ b/src/routes/vehicle/SAEVRoute.cpp
@@ -18,8 +18,8 @@ SAEVRoute::SAEVRoute(const Graph& graph, const std::vector<Request>& requestList
         getDestination(i).setCounterpart(&getOrigin(i));
 
         //Create depot O/D KP (Upper Bound = nb requests)
-        getOriginDepot(i) = SAEVKeyPoint(); //start
-        getDestinationDepot(i) = SAEVKeyPoint(); //end
+        getOriginDepot(i) = SAEVKeyPoint(graph.getDepotNodeIdx()); //start
+        getDestinationDepot(i) = SAEVKeyPoint(graph.getDepotNodeIdx()); //end
         //Link Origin depots and Destination depots
         getOriginDepot(i).setCounterpart(&getDestinationDepot(i));
         getDestinationDepot(i).setCounterpart(&getOriginDepot(i));
-- 
GitLab


From ae2df583ecf117527ae4f5fde047f97159950438 Mon Sep 17 00:00:00 2001
From: Romain BERNARD <30secondstodraw@gmail.com>
Date: Mon, 3 Jun 2024 14:00:48 +0200
Subject: [PATCH 063/327] Add default depot delta time to prevent segfaults

---
 src/routes/vehicle/SAEVKeyPoint.cpp | 12 ++++++++++++
 src/routes/vehicle/SAEVKeyPoint.h   |  6 +++++-
 2 files changed, 17 insertions(+), 1 deletion(-)

diff --git a/src/routes/vehicle/SAEVKeyPoint.cpp b/src/routes/vehicle/SAEVKeyPoint.cpp
index 1a05eb9..ce17621 100644
--- a/src/routes/vehicle/SAEVKeyPoint.cpp
+++ b/src/routes/vehicle/SAEVKeyPoint.cpp
@@ -77,6 +77,10 @@ Request const *SAEVKeyPoint::getRequest() const {
     return _requestPointer;
 }
 
+int SAEVKeyPoint::getDeltaTime() const {
+    return _isDepot ? 0 : _requestPointer->getDeltaTime();
+}
+
 void SAEVKeyPoint::setRequest(const Request *requestPointer) {
     _requestPointer = requestPointer;
 }
@@ -93,3 +97,11 @@ SAEVKeyPoint::SAEVKeyPoint(int depotNodeIdx) : KeyPoint(depotNodeIdx) {
     _isDepot = true;
     setNodeIndex(depotNodeIdx);
 }
+
+bool SAEVKeyPoint::isDepot() const {
+    return _isDepot;
+}
+
+void SAEVKeyPoint::setIsDepot(bool isDepot) {
+    _isDepot = isDepot;
+}
diff --git a/src/routes/vehicle/SAEVKeyPoint.h b/src/routes/vehicle/SAEVKeyPoint.h
index 9682356..b3b565a 100644
--- a/src/routes/vehicle/SAEVKeyPoint.h
+++ b/src/routes/vehicle/SAEVKeyPoint.h
@@ -57,11 +57,13 @@ public:
     [[nodiscard]] bool isOrigin() const;
     void setIsOrigin(bool isOrigin);
 
+    [[nodiscard]] bool isDepot() const;
+    void setIsDepot(bool isDepot);
+
     [[nodiscard]] const Request *getRequest() const;
     void setRequest(const Request *requestPointer);
 
     [[nodiscard]] SAEVKeyPoint *getCounterpart() const;
-
     void setCounterpart(SAEVKeyPoint *counterpart);
 
     [[nodiscard]] bool check() const override;
@@ -75,6 +77,8 @@ public:
      * @return True iff this and rhs are the same instance at the same adress
      */
     bool operator==(const SAEVKeyPoint &rhs) const;
+
+    int getDeltaTime() const;
 };
 
 
-- 
GitLab


From e0f7b4968e8bd9ac4809248d67798b0e10ff6f09 Mon Sep 17 00:00:00 2001
From: Romain BERNARD <30secondstodraw@gmail.com>
Date: Mon, 3 Jun 2024 14:01:21 +0200
Subject: [PATCH 064/327] WIP debug constraint propagation (fix segfaults)

---
 src/routes/vehicle/SAEVRoute.cpp        | 48 +++++++++++++------------
 test/src/ConstraintPropagationDebug.cpp | 11 ++++++
 2 files changed, 37 insertions(+), 22 deletions(-)

diff --git a/src/routes/vehicle/SAEVRoute.cpp b/src/routes/vehicle/SAEVRoute.cpp
index 21e36f9..0c3dc1f 100644
--- a/src/routes/vehicle/SAEVRoute.cpp
+++ b/src/routes/vehicle/SAEVRoute.cpp
@@ -190,21 +190,23 @@ SAEVRouteChangelist SAEVRoute::insertRequestWithPropagation(const int requestIdx
 
         if(bound == Min) {
             successorKP = keyPoint->getSuccessor();
-            oldValue = successorKP->getMinTw();
-            //Check neighbouring time window
-            newValue = keyPoint->getMinTw() + _graph->getShortestSAEVPath(keyPoint->getNodeIndex(), successorKP->getNodeIndex());
             if(successorKP != nullptr && oldValue < newValue) {
-                if (newValue > successorKP->getMaxTw()) {
-                    return changelist;
+                //Check neighbouring time window
+                oldValue = successorKP->getMinTw();
+                newValue = keyPoint->getMinTw() + _graph->getShortestSAEVPath(keyPoint->getNodeIndex(), successorKP->getNodeIndex());
+                if (oldValue < newValue) {
+                    if (newValue > successorKP->getMaxTw()) {
+                        return changelist;
+                    }
+                    changelist.emplace_back(*successorKP, Min, newValue - oldValue);
+                    successorKP->setMinTw(newValue);
+                    boundPropagationQueue.emplace(Min, successorKP);
                 }
-                changelist.emplace_back(*successorKP, Min, newValue - oldValue);
-                successorKP->setMinTw(newValue);
-                boundPropagationQueue.emplace(Min, successorKP);
             }
             //Check counterpart key point delta time
             oldValue = counterpartKP->getMinTw();
-            newValue = keyPoint->getMinTw() - keyPoint->getRequest()->getDeltaTime();
-            if(!counterpartKP->isOrigin() && oldValue < newValue) {
+            newValue = keyPoint->getMinTw() - keyPoint->getDeltaTime();
+            if(!keyPoint->isDepot() && !counterpartKP->isOrigin() && oldValue < newValue) {
                 if (newValue > counterpartKP->getMaxTw()) {
                     return changelist;
                 }
@@ -213,22 +215,24 @@ SAEVRouteChangelist SAEVRoute::insertRequestWithPropagation(const int requestIdx
                 boundPropagationQueue.emplace(Min, counterpartKP);
             }
         } else {
-            predecessorKP = keyPoint->getSuccessor();
-            oldValue = predecessorKP->getMaxTw();
-            //Check neighbouring time window
-            newValue = keyPoint->getMaxTw() - _graph->getShortestSAEVPath(predecessorKP->getNodeIndex(), keyPoint->getNodeIndex());
-            if(predecessorKP != nullptr && oldValue > newValue) {
-                if (predecessorKP->getMinTw() > newValue) {
-                    return changelist;
+            predecessorKP = keyPoint->getPredecessor();
+            if(predecessorKP != nullptr) {
+                //Check neighbouring time window
+                oldValue = predecessorKP->getMaxTw();
+                newValue = keyPoint->getMaxTw() - _graph->getShortestSAEVPath(predecessorKP->getNodeIndex(), keyPoint->getNodeIndex());
+                if(oldValue > newValue) {
+                    if (predecessorKP->getMinTw() > newValue) {
+                        return changelist;
+                    }
+                    changelist.emplace_back(*predecessorKP, Max, newValue - oldValue);
+                    predecessorKP->setMaxTw(newValue);
+                    boundPropagationQueue.emplace(Max, predecessorKP);
                 }
-                changelist.emplace_back(*predecessorKP, Max, newValue - oldValue);
-                predecessorKP->setMaxTw(newValue);
-                boundPropagationQueue.emplace(Max, predecessorKP);
             }
             //Check counterpart key point delta time
             oldValue = counterpartKP->getMaxTw();
-            newValue = keyPoint->getMaxTw() + keyPoint->getRequest()->getDeltaTime();
-            if(counterpartKP->isOrigin() && oldValue > newValue) {
+            newValue = keyPoint->getMaxTw() + keyPoint->getDeltaTime();
+            if(!keyPoint->isDepot() && counterpartKP->isOrigin() && oldValue > newValue) {
                 if (counterpartKP->getMinTw() > newValue) {
                     return changelist;
                 }
diff --git a/test/src/ConstraintPropagationDebug.cpp b/test/src/ConstraintPropagationDebug.cpp
index 7ed1f25..d0217b6 100644
--- a/test/src/ConstraintPropagationDebug.cpp
+++ b/test/src/ConstraintPropagationDebug.cpp
@@ -7,6 +7,7 @@
 #include "../../src/ShortestPath/Transit/TransitShortestPathContainer.h"
 #include "../../src/ShortestPath/Transit/TransitShortestPathPrecompute.h"
 #include "../../src/instance/Instance.h"
+#include "../../src/routes/vehicle/SAEVRoute.h"
 
 TEST(TransitPreprocessUnitTest, DebugFunction) {
     std::string instancesPath = "../../resources/test/instances/Constraint Propagation/";
@@ -20,6 +21,16 @@ TEST(TransitPreprocessUnitTest, DebugFunction) {
 
     //Init instance
     Instance instance(requests,graphFromSingleFile,4);
+    SAEVRoute routesContainer(graphFromSingleFile, requests);
+
+    SAEVRouteChangelist req0Changelist = routesContainer.tryAddRequest(0, routesContainer.getOriginDepotIdx(1), routesContainer.getOriginDepotIdx(1));
+    SAEVRouteChangelist req1Changelist = routesContainer.tryAddRequest(1, routesContainer.getOriginDepotIdx(1), routesContainer.getRequestOriginIdx(0));
+
+    //Test changelist revert/apply
+    req1Changelist.revertChanges();
+    req1Changelist.applyChanges();
+    req1Changelist.revertChanges();
+    req0Changelist.revertChanges();
 }
 
 int main(int argc, char* argv[]) {
-- 
GitLab


From de9cebdec0ffb60f8d9c1632826d1831d09681fe Mon Sep 17 00:00:00 2001
From: Romain BERNARD <romain.bernard@uca.fr>
Date: Fri, 7 Jun 2024 17:10:01 +0200
Subject: [PATCH 065/327] add logs and fix instance

---
 test/src/ConstraintPropagationDebug.cpp | 10 ++++++++--
 1 file changed, 8 insertions(+), 2 deletions(-)

diff --git a/test/src/ConstraintPropagationDebug.cpp b/test/src/ConstraintPropagationDebug.cpp
index d0217b6..90fd60f 100644
--- a/test/src/ConstraintPropagationDebug.cpp
+++ b/test/src/ConstraintPropagationDebug.cpp
@@ -23,8 +23,14 @@ TEST(TransitPreprocessUnitTest, DebugFunction) {
     Instance instance(requests,graphFromSingleFile,4);
     SAEVRoute routesContainer(graphFromSingleFile, requests);
 
-    SAEVRouteChangelist req0Changelist = routesContainer.tryAddRequest(0, routesContainer.getOriginDepotIdx(1), routesContainer.getOriginDepotIdx(1));
-    SAEVRouteChangelist req1Changelist = routesContainer.tryAddRequest(1, routesContainer.getOriginDepotIdx(1), routesContainer.getRequestOriginIdx(0));
+    std::cout << "------------------Fin parsing instance et route-------------------" << std::endl << std::endl;
+    int vehicleId = 1;
+    SAEVRouteChangelist req0Changelist = routesContainer.tryAddRequest(0, routesContainer.getOriginDepotIdx(vehicleId), routesContainer.getOriginDepotIdx(1));
+    std::cout << routesContainer.to_string(vehicleId) << std::endl;
+    std::cout << "------------------------------------------------------------------" << std::endl;
+    SAEVRouteChangelist req1Changelist = routesContainer.tryAddRequest(1, routesContainer.getOriginDepotIdx(vehicleId), routesContainer.getRequestDestinationIdx(0));
+    std::cout << routesContainer.to_string(vehicleId) << std::endl << std::endl;
+    std::cout << "------------------------------------------------------------------" << std::endl;
 
     //Test changelist revert/apply
     req1Changelist.revertChanges();
-- 
GitLab


From 79b7bc7d460fb961dbf0a3ae72527a8775d04d2b Mon Sep 17 00:00:00 2001
From: Romain BERNARD <romain.bernard@uca.fr>
Date: Fri, 7 Jun 2024 17:11:52 +0200
Subject: [PATCH 066/327] add string export functions (file export TODO)

---
 src/routes/KeyPoint.h            |  3 +++
 src/routes/vehicle/SAEVRoute.cpp | 17 +++++++++++++++++
 src/routes/vehicle/SAEVRoute.h   |  3 +++
 3 files changed, 23 insertions(+)

diff --git a/src/routes/KeyPoint.h b/src/routes/KeyPoint.h
index 3f4dc7f..578eb10 100644
--- a/src/routes/KeyPoint.h
+++ b/src/routes/KeyPoint.h
@@ -6,6 +6,7 @@
 #define GREEDYALGORITHM_KEYPOINT_H
 
 
+#include <string>
 #include "../TimeWindow.h"
 
 class KeyPoint {
@@ -22,6 +23,8 @@ public:
     [[nodiscard]] virtual bool check() const { return true; };
 
     virtual ~KeyPoint() = default;
+
+    virtual std::string to_string() const { return std::to_string(_nodeIndex); }
 };
 
 
diff --git a/src/routes/vehicle/SAEVRoute.cpp b/src/routes/vehicle/SAEVRoute.cpp
index 0c3dc1f..87fd9f2 100644
--- a/src/routes/vehicle/SAEVRoute.cpp
+++ b/src/routes/vehicle/SAEVRoute.cpp
@@ -276,3 +276,20 @@ double SAEVRoute::getDetourScore(const int requestIdx, const int originRequestPr
     }
     return score;
 }
+
+std::string SAEVRoute::to_string(size_t vehicleId) {
+    std::string routeString;
+    SAEVKeyPoint* currentKeyPoint = &getOriginDepot(vehicleId);
+    while(currentKeyPoint != nullptr) {
+        routeString += currentKeyPoint->to_string() + " --> ";
+        currentKeyPoint = currentKeyPoint->getSuccessor();
+    }
+    routeString.erase(routeString.length() - 5, routeString.length());
+
+    return routeString;
+}
+
+void SAEVRoute::exportToFile() {
+    //TODO
+}
+
diff --git a/src/routes/vehicle/SAEVRoute.h b/src/routes/vehicle/SAEVRoute.h
index 9071ae3..5ac1bdb 100644
--- a/src/routes/vehicle/SAEVRoute.h
+++ b/src/routes/vehicle/SAEVRoute.h
@@ -104,6 +104,9 @@ public:
 
     [[nodiscard]] size_t getOriginDepotIdx(const size_t vehicleId) const { return _nbRequest + vehicleId*2;}
     [[nodiscard]] size_t getDestinationDepotIdx(const size_t vehicleId) const { return _nbRequest + vehicleId*2 + 1;}
+
+    std::string to_string(size_t vehicleId);
+    void exportToFile();
 };
 
 #include "propagation/SAEVRouteChangelist.h"
-- 
GitLab


From 43510bc84c1c42a497aae7f6393cd46d67d4fd1e Mon Sep 17 00:00:00 2001
From: Romain BERNARD <romain.bernard@uca.fr>
Date: Fri, 7 Jun 2024 17:14:54 +0200
Subject: [PATCH 067/327] refactor requestIdx -> requestId for clarity's sake

---
 src/routes/vehicle/SAEVRoute.cpp              | 58 +++++++++----------
 src/routes/vehicle/SAEVRoute.h                | 32 +++++-----
 .../propagation/SAEVRouteChangelist.cpp       |  8 +--
 .../vehicle/propagation/SAEVRouteChangelist.h | 16 ++---
 4 files changed, 58 insertions(+), 56 deletions(-)

diff --git a/src/routes/vehicle/SAEVRoute.cpp b/src/routes/vehicle/SAEVRoute.cpp
index 87fd9f2..3db5582 100644
--- a/src/routes/vehicle/SAEVRoute.cpp
+++ b/src/routes/vehicle/SAEVRoute.cpp
@@ -28,9 +28,9 @@ SAEVRoute::SAEVRoute(const Graph& graph, const std::vector<Request>& requestList
     }
 }
 
-void SAEVRoute::insertRequest(int requestIdx, int originRequestPredecessorIdx, int destinationRequestPredecessorIdx) {
-    SAEVKeyPoint& originKp = getOrigin(requestIdx);
-    SAEVKeyPoint& destinationKp = getDestination(requestIdx);
+void SAEVRoute::insertRequest(size_t requestId, size_t originRequestPredecessorIdx, size_t destinationRequestPredecessorIdx) {
+    SAEVKeyPoint& originKp = getOrigin(requestId);
+    SAEVKeyPoint& destinationKp = getDestination(requestId);
 
     SAEVKeyPoint& originPredKp = _route.at(originRequestPredecessorIdx);
     SAEVKeyPoint *originSuccKp = originPredKp.getSuccessor();
@@ -62,9 +62,9 @@ void SAEVRoute::insertRequest(int requestIdx, int originRequestPredecessorIdx, i
     }
 }
 
-void SAEVRoute::removeRequest(int requestIdx) {
-    SAEVKeyPoint& originKp = _route.at(requestIdx);
-    SAEVKeyPoint& destinationKp = _route.at(requestIdx + 1);
+void SAEVRoute::removeRequest(int requestId) {
+    SAEVKeyPoint& originKp = _route.at(requestId);
+    SAEVKeyPoint& destinationKp = _route.at(requestId + 1);
 
     //get predecessor and successor for request
     SAEVKeyPoint* originPredecessor = originKp.getPredecessor();
@@ -81,15 +81,15 @@ void SAEVRoute::removeRequest(int requestIdx) {
     originKp.setSuccessor(nullptr);
     destinationKp.setPredecessor(nullptr);
     destinationKp.setSuccessor(nullptr);
-    originKp.setMinTw(_requestList->at(requestIdx).getMinDepartureTw());
-    originKp.setMaxTw(_requestList->at(requestIdx).getMaxDepartureTw());
-    destinationKp.setMinTw(_requestList->at(requestIdx).getMinArrivalTw());
-    destinationKp.setMaxTw(_requestList->at(requestIdx).getMaxArrivalTw());
+    originKp.setMinTw(_requestList->at(requestId).getMinDepartureTw());
+    originKp.setMaxTw(_requestList->at(requestId).getMaxDepartureTw());
+    destinationKp.setMinTw(_requestList->at(requestId).getMinArrivalTw());
+    destinationKp.setMaxTw(_requestList->at(requestId).getMaxArrivalTw());
 }
 
 SAEVRouteChangelist
-SAEVRoute::tryAddRequest(const int requestIdx, const int originRequestPredecessorIdx, const int destinationRequestPredecessorIdx) {
-    const Request* request = &_requestList->at(requestIdx);
+SAEVRoute::tryAddRequest(const size_t requestId, const size_t originRequestPredecessorIdx, const size_t destinationRequestPredecessorIdx) {
+    const Request* request = &_requestList->at(requestId);
     SAEVKeyPoint const* originPredecessor = &_route.at(originRequestPredecessorIdx);
     SAEVKeyPoint const* destinationPredecessor = &_route.at(destinationRequestPredecessorIdx);
 
@@ -97,27 +97,27 @@ SAEVRoute::tryAddRequest(const int requestIdx, const int originRequestPredecesso
     SAEVKeyPoint const* currentKP = originPredecessor;
     do {
         if(currentKP->getCurrentOccupation() + request->getWeight() > SAEVehicle::getCapacity()) {
-            return SAEVRouteChangelist(this, requestIdx, originRequestPredecessorIdx, destinationRequestPredecessorIdx);
+            return SAEVRouteChangelist(this, requestId, originRequestPredecessorIdx, destinationRequestPredecessorIdx);
         }
         currentKP = currentKP->getSuccessor();
     } while (currentKP != destinationPredecessor && currentKP != nullptr);
 
     //Do basic checks on neighbouring nodes from our Origin/Destination insertion points
-    bool isValid = doNeighbouringTWChecks(requestIdx, request->getOriginNodeIndex(), request->getDestinationNodeIndex(), originPredecessor, destinationPredecessor);
+    bool isValid = doNeighbouringTWChecks(requestId, request->getOriginNodeIndex(), request->getDestinationNodeIndex(), originPredecessor, destinationPredecessor);
 
     if(isValid)
-        return insertRequestWithPropagation(requestIdx, originRequestPredecessorIdx,destinationRequestPredecessorIdx);
+        return insertRequestWithPropagation(requestId, originRequestPredecessorIdx, destinationRequestPredecessorIdx);
     else
-        return SAEVRouteChangelist(this, requestIdx, originRequestPredecessorIdx, destinationRequestPredecessorIdx);
+        return SAEVRouteChangelist(this, requestId, originRequestPredecessorIdx, destinationRequestPredecessorIdx);
 
 }
 
 bool
-SAEVRoute::doNeighbouringTWChecks(const int requestIdx, const int originNodeIndex, const int destinationNodeIndex,
+SAEVRoute::doNeighbouringTWChecks(const size_t requestId, const size_t originNodeIndex, const size_t destinationNodeIndex,
                                   const SAEVKeyPoint *originPredecessor, const SAEVKeyPoint *destinationPredecessor) {
 
-    const SAEVKeyPoint& originKP = getOrigin(requestIdx);
-    const SAEVKeyPoint& destinationKP = getDestination(requestIdx);
+    const SAEVKeyPoint& originKP = getOrigin(requestId);
+    const SAEVKeyPoint& destinationKP = getDestination(requestId);
     const SAEVKeyPoint* originSuccessor = originPredecessor->getSuccessor();
 
     if(originPredecessor != destinationPredecessor)
@@ -159,17 +159,17 @@ SAEVRoute::doNeighbouringTWChecks(const int requestIdx, const int originNodeInde
     return true;
 }
 
-SAEVRouteChangelist SAEVRoute::insertRequestWithPropagation(const int requestIdx, const int originRequestPredecessorIdx,
-                                                            const int destinationRequestPredecessorIdx) {
+SAEVRouteChangelist SAEVRoute::insertRequestWithPropagation(const size_t requestId, const size_t originRequestPredecessorIdx,
+                                                            const size_t destinationRequestPredecessorIdx) {
     //Init changelist
-    SAEVRouteChangelist changelist{this, requestIdx, originRequestPredecessorIdx, destinationRequestPredecessorIdx};
+    SAEVRouteChangelist changelist{this, requestId, originRequestPredecessorIdx, destinationRequestPredecessorIdx};
     //Properly insert the request to facilitate constraint propagation
-    insertRequest(requestIdx, originRequestPredecessorIdx, destinationRequestPredecessorIdx);
+    insertRequest(requestId, originRequestPredecessorIdx, destinationRequestPredecessorIdx);
 
     //Initialize bound propagation signal queue (each item signals a modification done on one of a KeyPoint
     std::queue<std::pair<Bound, SAEVKeyPoint *>> boundPropagationQueue{};
-    SAEVKeyPoint * originKP = &getOrigin(requestIdx);
-    SAEVKeyPoint * destinationKP = &getDestination(requestIdx);
+    SAEVKeyPoint * originKP = &getOrigin(requestId);
+    SAEVKeyPoint * destinationKP = &getDestination(requestId);
     boundPropagationQueue.emplace(Min, originKP);
     boundPropagationQueue.emplace(Max, originKP);
     boundPropagationQueue.emplace(Min, destinationKP);
@@ -247,11 +247,11 @@ SAEVRouteChangelist SAEVRoute::insertRequestWithPropagation(const int requestIdx
     return changelist;
 }
 
-double SAEVRoute::getDetourScore(const int requestIdx, const int originRequestPredecessorIdx,
-                                 const int destinationRequestPredecessorIdx) {
+double SAEVRoute::getDetourScore(const size_t requestId, const size_t originRequestPredecessorIdx,
+                                 const size_t destinationRequestPredecessorIdx) {
     double score;
-    const SAEVKeyPoint& originKP = getOrigin(requestIdx);
-    const SAEVKeyPoint& destinationKP = getOrigin(requestIdx);
+    const SAEVKeyPoint& originKP = getOrigin(requestId);
+    const SAEVKeyPoint& destinationKP = getDestination(requestId);
     const SAEVKeyPoint& originPredKP = _route.at(originRequestPredecessorIdx);
     const SAEVKeyPoint* originSuccKP = originPredKP.getSuccessor();
 
diff --git a/src/routes/vehicle/SAEVRoute.h b/src/routes/vehicle/SAEVRoute.h
index 5ac1bdb..d91b566 100644
--- a/src/routes/vehicle/SAEVRoute.h
+++ b/src/routes/vehicle/SAEVRoute.h
@@ -32,43 +32,43 @@ public:
 
     /**
      * Raw request route insertion method. Public for debug purposes, but should effectively never be called by an outside member
-     * @param requestIdx index of the request we want to insert in the route
+     * @param requestId index of the request we want to insert in the route
      * @param originRequestPredecessorIdx Identifier/index in the route key point vector for the request origin or destination that will precede the origin of the request we want to insert
      * @param destinationRequestPredecessorIdx Identifier/index in the route key point vector for the request origin or destination that will precede the destination of the request we want to insert
      */
-    void insertRequest(int requestIdx, int originRequestPredecessorIdx, int destinationRequestPredecessorIdx);
+    void insertRequest(size_t requestId, size_t originRequestPredecessorIdx, size_t destinationRequestPredecessorIdx);
 
     /**
      * Raw request removal method. Public for debug purposes, but should effectively never be called by an outside member
-     * @param requestIdx index of the request we want to remove from the route
+     * @param requestId index of the request we want to remove from the route
      */
-    void removeRequest(int requestIdx);
+    void removeRequest(int requestId);
 
     /**
      * Tries to insert the request origin and destination next to the given origin/destination predecessors. \n \n
      * First we verify multiple constraints that don't require actually inserting the request or doing constraint propagation. \n
      * Then we propagate our min/max bounds, iteratively rippling through every modification induced by min/max neighbour constraints or delta constraints. \n
      * ⚠️ In case of infeasibility, tryAdd automatically reverts changes and the change list will be effectively empty, but otherwise it's the caller's responsibility to revert changes if necessary
-     * @param requestIdx Identifier/index in the instance's request vector for the request we wish to insert
+     * @param requestId Identifier/index in the instance's request vector for the request we wish to insert
      * @param originRequestPredecessorIdx Identifier/index in the route key point vector for the request origin or destination that will precede our request's origin in the route
      * @param destinationRequestPredecessorIdx Identifier/index in the route key point vector for the request origin or destination that will precede our request's destination in the route
      * @return A change list with every min/max bound change made during the tryAdd procedure and a score estimating insertion quality (lower is better)
      */
-    SAEVRouteChangelist tryAddRequest(const int requestIdx, const int originRequestPredecessorIdx, const int destinationRequestPredecessorIdx);
+    SAEVRouteChangelist tryAddRequest(const size_t requestId, const size_t originRequestPredecessorIdx, const size_t destinationRequestPredecessorIdx);
 
     /**
      * Verifies time window constraints on our request's origin/destination's projected neighbour, aka originPredecessor/destinationPredecessor and their successor.
      * There is a special case taken into account if originPredecessor and destinationPredecessor are the same KeyPoint, since then, Origin's successor would be Destination
      * ⚠️ Weight constraints are checked separately
      * ⚠️ Those checks don't modify the route => no rollback is needed at this point
-     * @param requestIdx Index of our request, necessary to retrieve the appropriate key points
+     * @param requestId Index of our request, necessary to retrieve the appropriate key points
      * @param originNodeIndex The request's origin node index, necessary to compute travel times
      * @param destinationNodeIndex The request's destination node index, necessary to compute travel times
      * @param originPredecessor The origin's expected predecessor, aka the point after which we wish to insert our origin
      * @param destinationPredecessor The destination's expected predecessor, aka the point after which we wish to insert our destination
      * @return true iff all neighbouring time window conditions are valid at our insertion points, false otherwise
      */
-    bool doNeighbouringTWChecks(const int requestIdx, const int originNodeIndex, const int destinationNodeIndex,
+    bool doNeighbouringTWChecks(const size_t requestId, const size_t originNodeIndex, const size_t destinationNodeIndex,
                                 const SAEVKeyPoint *originPredecessor, const SAEVKeyPoint *destinationPredecessor);
 
     /**
@@ -76,31 +76,31 @@ public:
      * This will effectively insert our procedure and ripple through bound changes. \n
      * If the bounds become infeasible (min > max), then the propagation stops with a changelist with score= +Infinity and changes will be immediately reverted.
      * Otherwise, it's the responsibility of this method's callers to revert changes if wanted (or to defer this responsibility to its caller)
-     * @param requestIdx Identifier/index in the instance's request vector for the request we wish to insert
+     * @param requestId Identifier/index in the instance's request vector for the request we wish to insert
      * @param originRequestPredecessorIdx Identifier/index in the route key point vector for the request origin or destination that will precede our request's origin in the route
      * @param destinationRequestPredecessorIdx Identifier/index in the route key point vector for the request origin or destination that will precede our request's destination in the route
      * @return A change list with every min/max bound change made during the insert procedure and a score estimating insertion quality (lower is better)
      */
-    SAEVRouteChangelist insertRequestWithPropagation(const int requestIdx, const int originRequestPredecessorIdx, const int destinationRequestPredecessorIdx);
+    SAEVRouteChangelist insertRequestWithPropagation(const size_t requestId, const size_t originRequestPredecessorIdx, const size_t destinationRequestPredecessorIdx);
 
     /**
      * Returns a score value equivalent to the detour implied by insertion of a request after the two given key point indexes.
      * The specific case of origin/destination being inserted one after another is taken into account
-     * @param requestIdx Identifier/index in the instance's request vector for the request we wish to insert
+     * @param requestId Identifier/index in the instance's request vector for the request we wish to insert
      * @param originRequestPredecessorIdx Identifier/index in the route key point vector for the request origin or destination that will precede our request's origin in the route
      * @param destinationRequestPredecessorIdx Identifier/index in the route key point vector for the request origin or destination that will precede our request's destination in the route
      * @return
      */
-    double getDetourScore(const int requestIdx, const int originRequestPredecessorIdx, const int destinationRequestPredecessorIdx);
+    double getDetourScore(const size_t requestId, const size_t originRequestPredecessorIdx, const size_t destinationRequestPredecessorIdx);
 
-    SAEVKeyPoint& getOrigin(const size_t requestIdx) { return _route.at(requestIdx*2);}
-    SAEVKeyPoint& getDestination(const size_t requestIdx) { return _route.at(requestIdx*2 + 1);}
+    SAEVKeyPoint& getOrigin(const size_t requestId) { return _route.at(requestId * 2);}
+    SAEVKeyPoint& getDestination(const size_t requestId) { return _route.at(requestId * 2 + 1);}
 
     SAEVKeyPoint& getOriginDepot(const size_t vehicleId) { return _route.at(_nbRequest + vehicleId*2);}
     SAEVKeyPoint& getDestinationDepot(const size_t vehicleId) { return _route.at(_nbRequest + vehicleId*2 + 1);}
 
-    [[nodiscard]] size_t getRequestOriginIdx(const size_t requestIdx) const { return requestIdx * 2;}
-    [[nodiscard]] size_t getRequestDestinationIdx(const size_t requestIdx) const { return requestIdx * 2 + 1;}
+    [[nodiscard]] size_t getRequestOriginIdx(const size_t requestId) const { return requestId * 2;}
+    [[nodiscard]] size_t getRequestDestinationIdx(const size_t requestId) const { return requestId * 2 + 1;}
 
     [[nodiscard]] size_t getOriginDepotIdx(const size_t vehicleId) const { return _nbRequest + vehicleId*2;}
     [[nodiscard]] size_t getDestinationDepotIdx(const size_t vehicleId) const { return _nbRequest + vehicleId*2 + 1;}
diff --git a/src/routes/vehicle/propagation/SAEVRouteChangelist.cpp b/src/routes/vehicle/propagation/SAEVRouteChangelist.cpp
index 6e2b333..a2535b6 100644
--- a/src/routes/vehicle/propagation/SAEVRouteChangelist.cpp
+++ b/src/routes/vehicle/propagation/SAEVRouteChangelist.cpp
@@ -21,7 +21,7 @@ void SAEVRouteChangelist::emplace_back(SAEVKeyPoint &kp, Bound bound, int value)
 }
 
 void SAEVRouteChangelist::applyChanges() const {
-    _routePtr->insertRequest(_requestIdx, _originPredecessorIdx, _destinationPredecessorIdx);
+    _routePtr->insertRequest(_requestId, _originPredecessorIdx, _destinationPredecessorIdx);
     for(SAEVRouteChange change : _changelist) {
         change.applyChange();
     }
@@ -29,15 +29,15 @@ void SAEVRouteChangelist::applyChanges() const {
 }
 
 void SAEVRouteChangelist::revertChanges() const {
-    _routePtr->removeRequest(_requestIdx);
+    _routePtr->removeRequest(_requestId);
     for(SAEVRouteChange change : _changelist) {
         change.revertChange();
     }
     //TODO: update key point weights here ? (only if changelist.size > 0 & score < +Inf)
 }
 
-int SAEVRouteChangelist::getRequestIdx() const {
-    return _requestIdx;
+size_t SAEVRouteChangelist::getRequestId() const {
+    return _requestId;
 }
 
 int SAEVRouteChangelist::getOriginPredecessorIdx() const {
diff --git a/src/routes/vehicle/propagation/SAEVRouteChangelist.h b/src/routes/vehicle/propagation/SAEVRouteChangelist.h
index f0be850..790c534 100644
--- a/src/routes/vehicle/propagation/SAEVRouteChangelist.h
+++ b/src/routes/vehicle/propagation/SAEVRouteChangelist.h
@@ -17,7 +17,9 @@
 class SAEVRouteChangelist {
 private:
     SAEVRoute * const _routePtr;
-    const int _requestIdx, _originPredecessorIdx, _destinationPredecessorIdx;
+    const size_t _requestId;
+    const size_t _originPredecessorIdx;
+    const size_t _destinationPredecessorIdx;
     std::vector<SAEVRouteChange> _changelist{};
     double _score{std::numeric_limits<double>::infinity()}; //Init score to infinity
 
@@ -25,12 +27,12 @@ public:
     /**
      * Initializes a change list to memorize every iterative modification made during constraint propagation
      * @param routePtr a pointer to the route the constraint propagation was applied on. revert/apply operations will be done on this route
-     * @param requestIdx The index of the request in the global request list
+     * @param requestId The index of the request in the global request list
      * @param originPredecessorIdx The index of the request our origin will be inserted after
      * @param destinationPredecessorIdx The index of the request our destination will be inserted after
      */
-    explicit SAEVRouteChangelist(SAEVRoute * const routePtr, const int requestIdx, const int originPredecessorIdx, const int destinationPredecessorIdx)
-    : _routePtr(routePtr), _requestIdx(requestIdx), _originPredecessorIdx(originPredecessorIdx), _destinationPredecessorIdx(destinationPredecessorIdx) {};
+    explicit SAEVRouteChangelist(SAEVRoute * const routePtr, const size_t requestId, const size_t originPredecessorIdx, const size_t destinationPredecessorIdx)
+    : _routePtr(routePtr), _requestId(requestId), _originPredecessorIdx(originPredecessorIdx), _destinationPredecessorIdx(destinationPredecessorIdx) {};
 
     /**
      * @return A pointer to the route this change list applies/reverts changes to
@@ -41,15 +43,15 @@ public:
     /**
      * @return The index of the request that we want to insert to a route
      */
-    [[nodiscard]] int getRequestIdx() const;
+    [[nodiscard]] size_t getRequestId() const;
     /**
      * @return The index of the request our origin will be inserted after
      */
-    [[nodiscard]] int getOriginPredecessorIdx() const;
+    [[nodiscard]] size_t getOriginPredecessorIdx() const;
     /**
      * @return The index of the request our destination will be inserted after
      */
-    [[nodiscard]] int getDestinationPredecessorIdx() const;
+    [[nodiscard]] size_t getDestinationPredecessorIdx() const;
     /**
      * @return A score value associated with this changelist. A lower score is better
      */
-- 
GitLab


From 076ed8b77e82dde896fe12960713e05056edb400 Mon Sep 17 00:00:00 2001
From: Romain BERNARD <romain.bernard@uca.fr>
Date: Fri, 7 Jun 2024 17:15:24 +0200
Subject: [PATCH 068/327] add utilitary methods

---
 src/routes/vehicle/SAEVKeyPoint.cpp | 13 +++++++++++++
 src/routes/vehicle/SAEVKeyPoint.h   |  5 ++++-
 2 files changed, 17 insertions(+), 1 deletion(-)

diff --git a/src/routes/vehicle/SAEVKeyPoint.cpp b/src/routes/vehicle/SAEVKeyPoint.cpp
index ce17621..aea9863 100644
--- a/src/routes/vehicle/SAEVKeyPoint.cpp
+++ b/src/routes/vehicle/SAEVKeyPoint.cpp
@@ -69,6 +69,10 @@ bool SAEVKeyPoint::isOrigin() const {
     return _isOrigin;
 }
 
+bool SAEVKeyPoint::isDestination() const {
+    return !_isOrigin;
+}
+
 void SAEVKeyPoint::setIsOrigin(bool isOrigin) {
     _isOrigin = isOrigin;
 }
@@ -105,3 +109,12 @@ bool SAEVKeyPoint::isDepot() const {
 void SAEVKeyPoint::setIsDepot(bool isDepot) {
     _isDepot = isDepot;
 }
+
+std::string SAEVKeyPoint::to_string() const {
+    std::string nodeType = "Depot, ";
+    if(!isDepot() && isOrigin()) { nodeType = "Origin, ";}
+    else if(!isDepot()) { nodeType = "Destination,"; }
+
+    return "(nodeIdx=" + std::to_string(getNodeIndex()) + ", Type=" + nodeType +
+    + "TW=[" + std::to_string(getMinTw()) + ";" + std::to_string(getMaxTw()) + "])";
+}
diff --git a/src/routes/vehicle/SAEVKeyPoint.h b/src/routes/vehicle/SAEVKeyPoint.h
index b3b565a..bacdbaa 100644
--- a/src/routes/vehicle/SAEVKeyPoint.h
+++ b/src/routes/vehicle/SAEVKeyPoint.h
@@ -55,6 +55,7 @@ public:
     void setMaxTw(int maxTw);
 
     [[nodiscard]] bool isOrigin() const;
+    [[nodiscard]] bool isDestination() const;
     void setIsOrigin(bool isOrigin);
 
     [[nodiscard]] bool isDepot() const;
@@ -78,7 +79,9 @@ public:
      */
     bool operator==(const SAEVKeyPoint &rhs) const;
 
-    int getDeltaTime() const;
+    [[nodiscard]] int getDeltaTime() const;
+
+    [[nodiscard]] std::string to_string() const override;
 };
 
 
-- 
GitLab


From e8e394eb41ba51f72ceb53763e29097f32393e67 Mon Sep 17 00:00:00 2001
From: Romain BERNARD <romain.bernard@uca.fr>
Date: Fri, 7 Jun 2024 17:19:52 +0200
Subject: [PATCH 069/327] add debug messages

---
 src/routes/vehicle/SAEVRoute.cpp | 28 +++++++++++++++++++++++++---
 1 file changed, 25 insertions(+), 3 deletions(-)

diff --git a/src/routes/vehicle/SAEVRoute.cpp b/src/routes/vehicle/SAEVRoute.cpp
index 3db5582..7c37aa1 100644
--- a/src/routes/vehicle/SAEVRoute.cpp
+++ b/src/routes/vehicle/SAEVRoute.cpp
@@ -3,8 +3,16 @@
 //
 
 #include <queue>
+#include <iostream>
 #include "SAEVRoute.h"
 
+#ifdef DEBUG_TRANSIT_PRECOMPUTE
+#include <iostream>
+#define DEBUG_MSG(str) do { std::cout << str << std::endl; } while( false )
+#else
+#define DEBUG_MSG(str) do { } while ( false )
+#endif
+
 SAEVRoute::SAEVRoute(const Graph& graph, const std::vector<Request>& requestList) : _nbRequest(requestList.size()), _graph(&graph), _requestList(&requestList) {
     _route.resize(_nbRequest*4); //nbRequest*2 O/D KeyPoints + nbRequest*2 Start/End depots (upper bound #vehicle = #requests
 
@@ -187,7 +195,7 @@ SAEVRouteChangelist SAEVRoute::insertRequestWithPropagation(const size_t request
         auto const& [bound, keyPoint] = boundPropagationQueue.front();
         boundPropagationQueue.pop();
         counterpartKP = keyPoint->getCounterpart();
-
+        DEBUG_MSG("KP=" + keyPoint->to_string() + "\n");
         if(bound == Min) {
             successorKP = keyPoint->getSuccessor();
             if(successorKP != nullptr && oldValue < newValue) {
@@ -198,9 +206,12 @@ SAEVRouteChangelist SAEVRoute::insertRequestWithPropagation(const size_t request
                     if (newValue > successorKP->getMaxTw()) {
                         return changelist;
                     }
+                    DEBUG_MSG("\tMIN Successeur KP=" + successorKP->to_string() + "\n\tModif Min=" + std::to_string(oldValue) + "->" + std::to_string(newValue));
                     changelist.emplace_back(*successorKP, Min, newValue - oldValue);
                     successorKP->setMinTw(newValue);
                     boundPropagationQueue.emplace(Min, successorKP);
+                } else {
+//                    DEBUG_MSG("Pas de changement pour Min du noeud " + successorKP->to_string() + " successeur de " + keyPoint->to_string());
                 }
             }
             //Check counterpart key point delta time
@@ -208,13 +219,17 @@ SAEVRouteChangelist SAEVRoute::insertRequestWithPropagation(const size_t request
             newValue = keyPoint->getMinTw() - keyPoint->getDeltaTime();
             if(!keyPoint->isDepot() && !counterpartKP->isOrigin() && oldValue < newValue) {
                 if (newValue > counterpartKP->getMaxTw()) {
+                    DEBUG_MSG("Infaisabilité MIN DELTA Destination->Origine");
                     return changelist;
                 }
+                DEBUG_MSG("\tMIN Counterpart KP=" + counterpartKP->to_string() + "\n\tModif Min=" + std::to_string(oldValue) + "->" + std::to_string(newValue));
                 changelist.emplace_back(*counterpartKP, Min, newValue - oldValue);
                 counterpartKP->setMinTw(newValue);
                 boundPropagationQueue.emplace(Min, counterpartKP);
+            } else if(!keyPoint->isDepot() && keyPoint->isDestination()) {
+//                DEBUG_MSG("Pas de changement pour Min du noeud " + counterpartKP->to_string() + " via  sa destination " + keyPoint->to_string());
             }
-        } else {
+        } else { //MAX
             predecessorKP = keyPoint->getPredecessor();
             if(predecessorKP != nullptr) {
                 //Check neighbouring time window
@@ -224,9 +239,12 @@ SAEVRouteChangelist SAEVRoute::insertRequestWithPropagation(const size_t request
                     if (predecessorKP->getMinTw() > newValue) {
                         return changelist;
                     }
+                    DEBUG_MSG("\tMAX Predecessor KP=" + predecessorKP->to_string() + "\n\tModif Max=" + std::to_string(oldValue) + "->" + std::to_string(newValue));
                     changelist.emplace_back(*predecessorKP, Max, newValue - oldValue);
                     predecessorKP->setMaxTw(newValue);
                     boundPropagationQueue.emplace(Max, predecessorKP);
+                } else {
+//                    DEBUG_MSG("Pas de changement pour Max pour noeud " + predecessorKP->to_string() + " prédécesseur de " + predecessorKP->to_string());
                 }
             }
             //Check counterpart key point delta time
@@ -234,16 +252,20 @@ SAEVRouteChangelist SAEVRoute::insertRequestWithPropagation(const size_t request
             newValue = keyPoint->getMaxTw() + keyPoint->getDeltaTime();
             if(!keyPoint->isDepot() && counterpartKP->isOrigin() && oldValue > newValue) {
                 if (counterpartKP->getMinTw() > newValue) {
+                    DEBUG_MSG("Infaisabilité MAX DELTA Origine->Destination");
                     return changelist;
                 }
                 changelist.emplace_back(*counterpartKP, Max, oldValue - newValue);
                 counterpartKP->setMaxTw(newValue);
                 boundPropagationQueue.emplace(Max, counterpartKP);
+                DEBUG_MSG("\tMAX Destination KP=" + counterpartKP->to_string() + "\n\tModif Max=" + std::to_string(oldValue) + "->" + std::to_string(newValue));
+            } else if(!keyPoint->isDepot() && keyPoint->isOrigin()) {
+//                DEBUG_MSG("Pas de changement pour Max du noeud " + counterpartKP->to_string() + " via son origine " + keyPoint->to_string());
             }
         }
     }
 
-    changelist.setScore(getDetourScore(requestIdx, originRequestPredecessorIdx, destinationRequestPredecessorIdx));
+    changelist.setScore(getDetourScore(requestId, originRequestPredecessorIdx, destinationRequestPredecessorIdx));
     return changelist;
 }
 
-- 
GitLab


From b911edcde01111c5103cc279f5c24b4b8a87017b Mon Sep 17 00:00:00 2001
From: Romain BERNARD <romain.bernard@uca.fr>
Date: Fri, 7 Jun 2024 17:20:38 +0200
Subject: [PATCH 070/327] fix wrong value comparison

---
 src/routes/vehicle/SAEVRoute.cpp | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/src/routes/vehicle/SAEVRoute.cpp b/src/routes/vehicle/SAEVRoute.cpp
index 7c37aa1..d2e48e9 100644
--- a/src/routes/vehicle/SAEVRoute.cpp
+++ b/src/routes/vehicle/SAEVRoute.cpp
@@ -198,7 +198,7 @@ SAEVRouteChangelist SAEVRoute::insertRequestWithPropagation(const size_t request
         DEBUG_MSG("KP=" + keyPoint->to_string() + "\n");
         if(bound == Min) {
             successorKP = keyPoint->getSuccessor();
-            if(successorKP != nullptr && oldValue < newValue) {
+            if(successorKP != nullptr) {
                 //Check neighbouring time window
                 oldValue = successorKP->getMinTw();
                 newValue = keyPoint->getMinTw() + _graph->getShortestSAEVPath(keyPoint->getNodeIndex(), successorKP->getNodeIndex());
-- 
GitLab


From ad2429092621d814d04140eb88f97f95476d1b91 Mon Sep 17 00:00:00 2001
From: Romain BERNARD <romain.bernard@uca.fr>
Date: Fri, 7 Jun 2024 17:21:50 +0200
Subject: [PATCH 071/327] Fix DELTA steps in propagation

---
 src/routes/vehicle/SAEVRoute.cpp | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/src/routes/vehicle/SAEVRoute.cpp b/src/routes/vehicle/SAEVRoute.cpp
index d2e48e9..34de2cc 100644
--- a/src/routes/vehicle/SAEVRoute.cpp
+++ b/src/routes/vehicle/SAEVRoute.cpp
@@ -217,7 +217,7 @@ SAEVRouteChangelist SAEVRoute::insertRequestWithPropagation(const size_t request
             //Check counterpart key point delta time
             oldValue = counterpartKP->getMinTw();
             newValue = keyPoint->getMinTw() - keyPoint->getDeltaTime();
-            if(!keyPoint->isDepot() && !counterpartKP->isOrigin() && oldValue < newValue) {
+            if(!keyPoint->isDepot() && keyPoint->isDestination() && oldValue < newValue) {
                 if (newValue > counterpartKP->getMaxTw()) {
                     DEBUG_MSG("Infaisabilité MIN DELTA Destination->Origine");
                     return changelist;
@@ -250,7 +250,7 @@ SAEVRouteChangelist SAEVRoute::insertRequestWithPropagation(const size_t request
             //Check counterpart key point delta time
             oldValue = counterpartKP->getMaxTw();
             newValue = keyPoint->getMaxTw() + keyPoint->getDeltaTime();
-            if(!keyPoint->isDepot() && counterpartKP->isOrigin() && oldValue > newValue) {
+            if(!keyPoint->isDepot() && keyPoint->isOrigin() && oldValue > newValue) {
                 if (counterpartKP->getMinTw() > newValue) {
                     DEBUG_MSG("Infaisabilité MAX DELTA Origine->Destination");
                     return changelist;
-- 
GitLab


From 2b3b595125a4bb7214c49a2cc7e02c0af4b7ff20 Mon Sep 17 00:00:00 2001
From: Romain BERNARD <romain.bernard@uca.fr>
Date: Fri, 7 Jun 2024 17:22:07 +0200
Subject: [PATCH 072/327] fix score calculation

---
 src/routes/vehicle/SAEVRoute.cpp | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/src/routes/vehicle/SAEVRoute.cpp b/src/routes/vehicle/SAEVRoute.cpp
index 34de2cc..c83c053 100644
--- a/src/routes/vehicle/SAEVRoute.cpp
+++ b/src/routes/vehicle/SAEVRoute.cpp
@@ -278,8 +278,8 @@ double SAEVRoute::getDetourScore(const size_t requestId, const size_t originRequ
     const SAEVKeyPoint* originSuccKP = originPredKP.getSuccessor();
 
     if(originRequestPredecessorIdx != destinationRequestPredecessorIdx) {
-        const SAEVKeyPoint* destinationPredKP = getDestination(requestIdx).getPredecessor();
-        const SAEVKeyPoint* destinationSuccKP = getDestination(requestIdx).getSuccessor();
+        const SAEVKeyPoint* destinationPredKP = destinationKP.getPredecessor();
+        const SAEVKeyPoint* destinationSuccKP = destinationKP.getSuccessor();
 
         //Origin Detour
         score = _graph->getShortestSAEVPath(originPredKP.getNodeIndex(), originKP.getNodeIndex()) //T(Pred(O), D)
-- 
GitLab


From 3676bce900f7b79bbf978fe585f8391b69732dd0 Mon Sep 17 00:00:00 2001
From: Romain BERNARD <romain.bernard@uca.fr>
Date: Fri, 7 Jun 2024 17:32:43 +0200
Subject: [PATCH 073/327] pointer to const sonar feedback

---
 src/routes/vehicle/SAEVRoute.cpp | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/src/routes/vehicle/SAEVRoute.cpp b/src/routes/vehicle/SAEVRoute.cpp
index c83c053..06d627d 100644
--- a/src/routes/vehicle/SAEVRoute.cpp
+++ b/src/routes/vehicle/SAEVRoute.cpp
@@ -301,7 +301,7 @@ double SAEVRoute::getDetourScore(const size_t requestId, const size_t originRequ
 
 std::string SAEVRoute::to_string(size_t vehicleId) {
     std::string routeString;
-    SAEVKeyPoint* currentKeyPoint = &getOriginDepot(vehicleId);
+    SAEVKeyPoint const* currentKeyPoint = &getOriginDepot(vehicleId);
     while(currentKeyPoint != nullptr) {
         routeString += currentKeyPoint->to_string() + " --> ";
         currentKeyPoint = currentKeyPoint->getSuccessor();
-- 
GitLab


From 3cdaa5fc62f9d4b9fad976a641132373cfb4058e Mon Sep 17 00:00:00 2001
From: Romain BERNARD <romain.bernard@uca.fr>
Date: Fri, 7 Jun 2024 18:20:47 +0200
Subject: [PATCH 074/327] add time windows check function for debugging
 purposes (next : do request/insertion generation methods)

---
 src/routes/vehicle/SAEVRoute.cpp | 30 ++++++++++++++++++++++++++++++
 src/routes/vehicle/SAEVRoute.h   |  7 +++++++
 2 files changed, 37 insertions(+)

diff --git a/src/routes/vehicle/SAEVRoute.cpp b/src/routes/vehicle/SAEVRoute.cpp
index 06d627d..5914f6a 100644
--- a/src/routes/vehicle/SAEVRoute.cpp
+++ b/src/routes/vehicle/SAEVRoute.cpp
@@ -315,3 +315,33 @@ void SAEVRoute::exportToFile() {
     //TODO
 }
 
+bool SAEVRoute::checkRouteTimeWindows(size_t vehicleId) {
+    SAEVKeyPoint const* currentKeyPoint = &getOriginDepot(vehicleId);
+    SAEVKeyPoint const* succKP;
+    SAEVKeyPoint const* counterpartKP;
+    while(currentKeyPoint != nullptr) {
+        succKP = currentKeyPoint->getSuccessor();
+        counterpartKP = currentKeyPoint->getCounterpart();
+        //MIN/MAX
+        if(succKP != nullptr) {
+            if(currentKeyPoint->getMinTw() + _graph->getShortestSAEVPath(currentKeyPoint->getNodeIndex(), succKP->getNodeIndex()) > succKP->getMaxTw() ) {
+                DEBUG_MSG("MIN TW VIOLATION : " + currentKeyPoint->to_string() + " > " + succKP->to_string());
+                return false;
+            }
+            if(currentKeyPoint->getMaxTw() + _graph->getShortestSAEVPath(currentKeyPoint->getNodeIndex(), succKP->getNodeIndex()) < succKP->getMaxTw() ) {
+                DEBUG_MSG("MAX TW VIOLATION : " + currentKeyPoint->to_string() + " < " + succKP->to_string());
+                return false;
+            }
+        }
+        //DELTA
+        if((!currentKeyPoint->isDepot() && currentKeyPoint->isOrigin() && counterpartKP != nullptr)
+        && (counterpartKP->getMinTw() - currentKeyPoint->getMinTw() > currentKeyPoint->getRequest()->getDeltaTime()
+        ||  counterpartKP->getMaxTw() - currentKeyPoint->getMaxTw() > currentKeyPoint->getRequest()->getDeltaTime())) {
+            DEBUG_MSG("DELTA VIOLATION : " + currentKeyPoint->to_string() + " " + counterpartKP->to_string());
+            return false;
+        }
+    }
+
+    return true;
+}
+
diff --git a/src/routes/vehicle/SAEVRoute.h b/src/routes/vehicle/SAEVRoute.h
index d91b566..1dfed77 100644
--- a/src/routes/vehicle/SAEVRoute.h
+++ b/src/routes/vehicle/SAEVRoute.h
@@ -105,6 +105,13 @@ public:
     [[nodiscard]] size_t getOriginDepotIdx(const size_t vehicleId) const { return _nbRequest + vehicleId*2;}
     [[nodiscard]] size_t getDestinationDepotIdx(const size_t vehicleId) const { return _nbRequest + vehicleId*2 + 1;}
 
+    /**
+     * Verifies that time windows have been properly propagated for a given vehicle's route
+     * @param vehicleId
+     * @return true iff all time windows have been properly shrunk
+     */
+    bool checkRouteTimeWindows(size_t vehicleId);
+
     std::string to_string(size_t vehicleId);
     void exportToFile();
 };
-- 
GitLab


From b7f0df2c03f8ffcb14c8e1ba58e831ad2d91d0e7 Mon Sep 17 00:00:00 2001
From: Romain BERNARD <romain.bernard@uca.fr>
Date: Tue, 11 Jun 2024 16:04:23 +0200
Subject: [PATCH 075/327] I swear that line was here last I checked

---
 src/routes/vehicle/SAEVRoute.cpp | 1 +
 1 file changed, 1 insertion(+)

diff --git a/src/routes/vehicle/SAEVRoute.cpp b/src/routes/vehicle/SAEVRoute.cpp
index 5914f6a..d21a965 100644
--- a/src/routes/vehicle/SAEVRoute.cpp
+++ b/src/routes/vehicle/SAEVRoute.cpp
@@ -340,6 +340,7 @@ bool SAEVRoute::checkRouteTimeWindows(size_t vehicleId) {
             DEBUG_MSG("DELTA VIOLATION : " + currentKeyPoint->to_string() + " " + counterpartKP->to_string());
             return false;
         }
+        currentKeyPoint = currentKeyPoint->getSuccessor();
     }
 
     return true;
-- 
GitLab


From f56593de6098233795598bd6e542210e64c329d4 Mon Sep 17 00:00:00 2001
From: Romain BERNARD <romain.bernard@uca.fr>
Date: Tue, 11 Jun 2024 16:09:11 +0200
Subject: [PATCH 076/327] add special cases for start/end depots in min/max
 check (due to min propagation being done only to the right from new
 insertions and max propagations to the left from new insertions)

---
 src/routes/vehicle/SAEVRoute.cpp | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/src/routes/vehicle/SAEVRoute.cpp b/src/routes/vehicle/SAEVRoute.cpp
index d21a965..4ce7207 100644
--- a/src/routes/vehicle/SAEVRoute.cpp
+++ b/src/routes/vehicle/SAEVRoute.cpp
@@ -324,11 +324,11 @@ bool SAEVRoute::checkRouteTimeWindows(size_t vehicleId) {
         counterpartKP = currentKeyPoint->getCounterpart();
         //MIN/MAX
         if(succKP != nullptr) {
-            if(currentKeyPoint->getMinTw() + _graph->getShortestSAEVPath(currentKeyPoint->getNodeIndex(), succKP->getNodeIndex()) > succKP->getMaxTw() ) {
+            if(!currentKeyPoint->isDepot() && currentKeyPoint->getMinTw() + _graph->getShortestSAEVPath(currentKeyPoint->getNodeIndex(), succKP->getNodeIndex()) > succKP->getMaxTw() ) {
                 DEBUG_MSG("MIN TW VIOLATION : " + currentKeyPoint->to_string() + " > " + succKP->to_string());
                 return false;
             }
-            if(currentKeyPoint->getMaxTw() + _graph->getShortestSAEVPath(currentKeyPoint->getNodeIndex(), succKP->getNodeIndex()) < succKP->getMaxTw() ) {
+            if(!succKP->isDepot() && currentKeyPoint->getMaxTw() + _graph->getShortestSAEVPath(currentKeyPoint->getNodeIndex(), succKP->getNodeIndex()) < succKP->getMaxTw() ) {
                 DEBUG_MSG("MAX TW VIOLATION : " + currentKeyPoint->to_string() + " < " + succKP->to_string());
                 return false;
             }
-- 
GitLab


From 947964dbe77edca875fb63f63b8d3c2a7926f369 Mon Sep 17 00:00:00 2001
From: Romain BERNARD <romain.bernard@uca.fr>
Date: Tue, 11 Jun 2024 16:09:53 +0200
Subject: [PATCH 077/327] use uint for time windows

---
 CMakeLists.txt     |  2 +-
 src/TimeWindow.cpp | 10 +++++-----
 src/TimeWindow.h   | 16 +++++++++-------
 3 files changed, 15 insertions(+), 13 deletions(-)

diff --git a/CMakeLists.txt b/CMakeLists.txt
index a95788a..aa63dd1 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -1,4 +1,4 @@
-cmake_minimum_required(VERSION 3.27)
+cmake_minimum_required(VERSION 3.28.1)
 project(GreedyAlgorithm)
 
 set(CMAKE_CXX_STANDARD 23)
diff --git a/src/TimeWindow.cpp b/src/TimeWindow.cpp
index 0e829bc..2ac1dd3 100644
--- a/src/TimeWindow.cpp
+++ b/src/TimeWindow.cpp
@@ -5,21 +5,21 @@
 #include "TimeWindow.h"
 
 
-TimeWindow TimeWindow::operator+(int rhs) const {
+TimeWindow TimeWindow::operator+(uint rhs) const {
     return TimeWindow(this->min + rhs, this->max + rhs);
 }
 
-TimeWindow& TimeWindow::operator+=(int rhs) {
+TimeWindow& TimeWindow::operator+=(uint rhs) {
     this->min += rhs;
     this->max += rhs;
     return *this;
 }
 
-TimeWindow TimeWindow::operator-(int rhs) const {
+TimeWindow TimeWindow::operator-(uint rhs) const {
     return TimeWindow(this->min - rhs, this->max - rhs);
 }
 
-TimeWindow& TimeWindow::operator-=(int rhs) {
+TimeWindow& TimeWindow::operator-=(uint rhs) {
     this->min -= rhs;
     this->max -= rhs;
     return *this;
@@ -45,7 +45,7 @@ TimeWindow& TimeWindow::operator-=(const TimeWindow& rhs) {
     return *this;
 }
 
-bool TimeWindow::isInTimeWindow(int instant) const {
+bool TimeWindow::isInTimeWindow(uint instant) const {
     return this->min <= instant && this->max >= instant;
 }
 
diff --git a/src/TimeWindow.h b/src/TimeWindow.h
index ef2f72f..04daa4b 100644
--- a/src/TimeWindow.h
+++ b/src/TimeWindow.h
@@ -5,29 +5,31 @@
 #ifndef GREEDYALGORITHM_TIMEWINDOW_H
 #define GREEDYALGORITHM_TIMEWINDOW_H
 
+#include <cstdlib>
+
 /**
  * Represents [min, max] time windows with appropriate operators for TW operations (+,-,isInTimeWindow).
  * Prefer using +=/-= notations to modify in place, as + and - operators return a new TimeWindow object.
  */
 struct TimeWindow {
-    int min = 0, max = 0;
+    uint min = 0, max = 0;
     TimeWindow() = default;
-    TimeWindow(int min, int max) : min(min), max(max) {}
+    TimeWindow(uint min, uint max) : min(min), max(max) {}
     /**
      * Checks if the given instant is inside the [min,max] interval
      * @return True iff instant is in the time window, false otherwise
      */
-    [[nodiscard]] bool isInTimeWindow(int instant) const;
+    [[nodiscard]] bool isInTimeWindow(uint instant) const;
     /**
     * Checks if the given time window is contained inside the [min,max] interval of this
     * @return True iff instant is in the time window, false otherwise
     */
     [[nodiscard]] bool isInTimeWindow(const TimeWindow& instant) const;
 
-    TimeWindow operator+(int rhs) const;
-    TimeWindow& operator+=(int rhs);
-    TimeWindow operator-(int rhs) const;
-    TimeWindow& operator-=(int rhs);
+    TimeWindow operator+(uint rhs) const;
+    TimeWindow& operator+=(uint rhs);
+    TimeWindow operator-(uint rhs) const;
+    TimeWindow& operator-=(uint rhs);
     TimeWindow operator+(const TimeWindow& rhs) const;
     TimeWindow& operator+=(const TimeWindow& rhs);
     TimeWindow operator-(const TimeWindow& rhs) const;
-- 
GitLab


From ed5e5305b07ba3ffe34e86ddcdc8f9677b8729b6 Mon Sep 17 00:00:00 2001
From: Romain BERNARD <romain.bernard@uca.fr>
Date: Tue, 11 Jun 2024 16:34:31 +0200
Subject: [PATCH 078/327] constraint violation messages

---
 src/routes/vehicle/SAEVRoute.cpp | 12 +++++++-----
 1 file changed, 7 insertions(+), 5 deletions(-)

diff --git a/src/routes/vehicle/SAEVRoute.cpp b/src/routes/vehicle/SAEVRoute.cpp
index 4ce7207..0ad775e 100644
--- a/src/routes/vehicle/SAEVRoute.cpp
+++ b/src/routes/vehicle/SAEVRoute.cpp
@@ -105,6 +105,7 @@ SAEVRoute::tryAddRequest(const size_t requestId, const size_t originRequestPrede
     SAEVKeyPoint const* currentKP = originPredecessor;
     do {
         if(currentKP->getCurrentOccupation() + request->getWeight() > SAEVehicle::getCapacity()) {
+            DEBUG_MSG("WEIGHT VIOLATION : request weight = " + std::to_string(request->getWeight()) + " incompatible KP = " + currentKP->to_string());
             return SAEVRouteChangelist(this, requestId, originRequestPredecessorIdx, destinationRequestPredecessorIdx);
         }
         currentKP = currentKP->getSuccessor();
@@ -113,11 +114,12 @@ SAEVRoute::tryAddRequest(const size_t requestId, const size_t originRequestPrede
     //Do basic checks on neighbouring nodes from our Origin/Destination insertion points
     bool isValid = doNeighbouringTWChecks(requestId, request->getOriginNodeIndex(), request->getDestinationNodeIndex(), originPredecessor, destinationPredecessor);
 
-    if(isValid)
+    if(isValid) {
         return insertRequestWithPropagation(requestId, originRequestPredecessorIdx, destinationRequestPredecessorIdx);
-    else
+    } else {
+        DEBUG_MSG("TW VIOLATION on neighbour KPs");
         return SAEVRouteChangelist(this, requestId, originRequestPredecessorIdx, destinationRequestPredecessorIdx);
-
+    }
 }
 
 bool
@@ -219,7 +221,7 @@ SAEVRouteChangelist SAEVRoute::insertRequestWithPropagation(const size_t request
             newValue = keyPoint->getMinTw() - keyPoint->getDeltaTime();
             if(!keyPoint->isDepot() && keyPoint->isDestination() && oldValue < newValue) {
                 if (newValue > counterpartKP->getMaxTw()) {
-                    DEBUG_MSG("Infaisabilité MIN DELTA Destination->Origine");
+                    DEBUG_MSG("\tMIN DELTA Destination->Origine");
                     return changelist;
                 }
                 DEBUG_MSG("\tMIN Counterpart KP=" + counterpartKP->to_string() + "\n\tModif Min=" + std::to_string(oldValue) + "->" + std::to_string(newValue));
@@ -252,7 +254,7 @@ SAEVRouteChangelist SAEVRoute::insertRequestWithPropagation(const size_t request
             newValue = keyPoint->getMaxTw() + keyPoint->getDeltaTime();
             if(!keyPoint->isDepot() && keyPoint->isOrigin() && oldValue > newValue) {
                 if (counterpartKP->getMinTw() > newValue) {
-                    DEBUG_MSG("Infaisabilité MAX DELTA Origine->Destination");
+                    DEBUG_MSG("\tMAX DELTA Origine->Destination");
                     return changelist;
                 }
                 changelist.emplace_back(*counterpartKP, Max, oldValue - newValue);
-- 
GitLab


From 1ae35c37e9effbe2b1099b5c2d6d952ad553e3cf Mon Sep 17 00:00:00 2001
From: Romain BERNARD <romain.bernard@uca.fr>
Date: Tue, 11 Jun 2024 16:38:30 +0200
Subject: [PATCH 079/327] asserts in debug script

---
 test/src/ConstraintPropagationDebug.cpp | 3 +++
 1 file changed, 3 insertions(+)

diff --git a/test/src/ConstraintPropagationDebug.cpp b/test/src/ConstraintPropagationDebug.cpp
index 90fd60f..6624618 100644
--- a/test/src/ConstraintPropagationDebug.cpp
+++ b/test/src/ConstraintPropagationDebug.cpp
@@ -25,11 +25,14 @@ TEST(TransitPreprocessUnitTest, DebugFunction) {
 
     std::cout << "------------------Fin parsing instance et route-------------------" << std::endl << std::endl;
     int vehicleId = 1;
+    assert(routesContainer.checkRouteTimeWindows(vehicleId));
     SAEVRouteChangelist req0Changelist = routesContainer.tryAddRequest(0, routesContainer.getOriginDepotIdx(vehicleId), routesContainer.getOriginDepotIdx(1));
     std::cout << routesContainer.to_string(vehicleId) << std::endl;
+    assert(routesContainer.checkRouteTimeWindows(vehicleId));
     std::cout << "------------------------------------------------------------------" << std::endl;
     SAEVRouteChangelist req1Changelist = routesContainer.tryAddRequest(1, routesContainer.getOriginDepotIdx(vehicleId), routesContainer.getRequestDestinationIdx(0));
     std::cout << routesContainer.to_string(vehicleId) << std::endl << std::endl;
+    assert(!routesContainer.checkRouteTimeWindows(vehicleId));
     std::cout << "------------------------------------------------------------------" << std::endl;
 
     //Test changelist revert/apply
-- 
GitLab


From fa41cc35c12dd9726255d956ca1c30ba8d7755ce Mon Sep 17 00:00:00 2001
From: Romain BERNARD <romain.bernard@uca.fr>
Date: Tue, 11 Jun 2024 18:11:05 +0200
Subject: [PATCH 080/327] create a parametric request generator

---
 CMakeLists.txt                  |  2 ++
 src/utils/InstanceGenerator.cpp | 49 +++++++++++++++++++++++++++++++++
 src/utils/InstanceGenerator.h   | 49 +++++++++++++++++++++++++++++++++
 test/CMakeLists.txt             |  2 ++
 4 files changed, 102 insertions(+)
 create mode 100644 src/utils/InstanceGenerator.cpp
 create mode 100644 src/utils/InstanceGenerator.h

diff --git a/CMakeLists.txt b/CMakeLists.txt
index aa63dd1..fcb3c6c 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -58,6 +58,8 @@ add_executable(GreedyAlgorithm
         src/routes/vehicle/propagation/SAEVRouteChangelist.h
         src/routes/vehicle/propagation/SAEVRouteChange.cpp
         src/routes/vehicle/propagation/SAEVRouteChange.h
+        src/utils/InstanceGenerator.cpp
+        src/utils/InstanceGenerator.h
 )
 
 target_include_directories(GreedyAlgorithm PRIVATE ${PYTHON_INCLUDE_DIRS})
diff --git a/src/utils/InstanceGenerator.cpp b/src/utils/InstanceGenerator.cpp
new file mode 100644
index 0000000..badb1e7
--- /dev/null
+++ b/src/utils/InstanceGenerator.cpp
@@ -0,0 +1,49 @@
+//
+// Created by romain on 11/06/24.
+//
+
+#include "InstanceGenerator.h"
+
+std::vector<Request>
+InstanceGenerator::generateRequests(const Graph &graph, size_t requestAmount, double deltaRatio, uint deltaMinDuration,
+                                    uint timeWindowWidth, uint periodStartTime, uint periodEndTime, ulong rngSeed) {
+    std::mt19937 rng(rngSeed);
+    std::vector<Request> requests;
+    requests.reserve(requestAmount);
+    //reduce period window time to account for TW width
+    std::uniform_int_distribution<uint32_t> requestTWStartDistribution(periodStartTime + timeWindowWidth, periodEndTime - timeWindowWidth);
+    std::uniform_int_distribution<ulong> nodeDistribution(0, graph.getNbNodes() - 1);
+
+    //Init request variables
+    uint deltaTime;
+    uint requestTWStart;
+    ulong originNodeIdx, destinationNodeIdx;
+    for(size_t i = 0; i < requestAmount; ++i) {
+        //Reset values
+        originNodeIdx = -1;
+        destinationNodeIdx = -1;
+
+        //Generate new values
+        requestTWStart = requestTWStartDistribution(rng);
+        originNodeIdx = nodeDistribution(rng);
+        destinationNodeIdx = nodeDistribution(rng);
+        while (destinationNodeIdx == originNodeIdx) { //retry random node as much as needed for origin to be different from destination
+            destinationNodeIdx = nodeDistribution(rng);
+        }
+        //Set delta time with a guaranteed leeway compared to the shortest path
+        deltaTime = graph.getShortestSAEVPath(originNodeIdx, destinationNodeIdx);
+        if(floor(deltaTime * (deltaRatio - 1)) < deltaMinDuration) {
+            deltaTime = deltaTime + deltaMinDuration;
+        } else {
+            deltaTime = floor(deltaTime * deltaRatio);
+        }
+        requests.emplace_back(originNodeIdx, destinationNodeIdx,
+                              TimeWindow(requestTWStart, requestTWStart + timeWindowWidth), //TODO : could be replaced with a min/max width ?
+                              deltaTime, 1);
+    }
+    return requests;
+}
+
+std::vector<Request> InstanceGenerator::generateRequests(const Graph &graph, size_t requestAmount, ulong rngSeed) {
+    return generateRequests(graph, requestAmount, 1.25, 10, 30, 360, 660, rngSeed);
+}
diff --git a/src/utils/InstanceGenerator.h b/src/utils/InstanceGenerator.h
new file mode 100644
index 0000000..4a5ec47
--- /dev/null
+++ b/src/utils/InstanceGenerator.h
@@ -0,0 +1,49 @@
+//
+// Created by romain on 11/06/24.
+//
+
+#ifndef GREEDYALGORITHM_INSTANCEGENERATOR_H
+#define GREEDYALGORITHM_INSTANCEGENERATOR_H
+
+
+#include <vector>
+#include "../instance/requests/Request.h"
+
+class InstanceGenerator {
+public:
+
+    /**
+     * Parametrized request generation method.
+     * @param graph the graph on which requests are generated (required for node lists and shortest paths between nodes)
+     * @param requestAmount How many requests to generate
+     * @param deltaRatio ratio by which the direct path duration for a request is multiplied to get the max routing time
+     * @param deltaMinDuration minimum delta value added to the direct path duration to get a max delta time
+     * @param timeWindowWidth size of the time window available on arrival
+     * @param periodStartTime start time for the period during which requests can be served
+     * @param periodEndTime end time for the period during which requests can be served
+     * @param rngSeed a seed to ensure reproducibility
+     * @return a vector of randomly generated requests according to the given parameters
+     */
+    [[nodiscard]] static std::vector<Request> generateRequests(const Graph& graph, size_t requestAmount,
+                                          double deltaRatio, uint deltaMinDuration, uint timeWindowWidth,
+                                          uint periodStartTime, uint periodEndTime, ulong rngSeed);
+
+    /**
+     * Default parameter request generation.
+     * Parameters :
+     *  Delta ratio = 1.25 (users will accept at most a trip 25% longer than the shortest path)
+     *  Time Window width = 30 (users will have a 30 minute range of acceptable arrival dates)
+     *  Delta ratio = 1.25
+     *  Delta min leeway = 10 minutes of minimum possible detour time to calculate delta value
+     *  periodStartTime = 360 (requests start after 6am)
+     *  periodEndTime = 660 (requests end before 11am)
+     * @param graph the graph on which requests are generated (required for node lists and shortest paths between nodes)
+     * @param requestAmount How many requests to generate
+     * @param rngSeed a seed to ensure reproducibility
+     * @return a vector of randomly generated requests according to the given parameters
+     */
+    [[nodiscard]] static std::vector<Request> generateRequests(const Graph& graph, size_t requestAmount, ulong rngSeed);
+};
+
+
+#endif //GREEDYALGORITHM_INSTANCEGENERATOR_H
diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt
index eef950b..3916656 100644
--- a/test/CMakeLists.txt
+++ b/test/CMakeLists.txt
@@ -66,6 +66,8 @@ add_executable(Constraint_Propag_DEB
         ../src/routes/RequestKeyPoint.h
         ../src/routes/RequestRoute.cpp
         ../src/routes/RequestRoute.h
+        ../src/utils/InstanceGenerator.cpp
+        ../src/utils/InstanceGenerator.h
 )
 
 target_link_libraries(Line_UT gtest gtest_main)
-- 
GitLab


From 250345ae3351523444d71e6debdcd4d3894349f2 Mon Sep 17 00:00:00 2001
From: Romain BERNARD <romain.bernard@uca.fr>
Date: Tue, 11 Jun 2024 18:11:50 +0200
Subject: [PATCH 081/327] test parametric request generator with default and
 given parameters

---
 test/src/ConstraintPropagationDebug.cpp | 23 ++++++++++++++++++++++-
 1 file changed, 22 insertions(+), 1 deletion(-)

diff --git a/test/src/ConstraintPropagationDebug.cpp b/test/src/ConstraintPropagationDebug.cpp
index 6624618..6471ef8 100644
--- a/test/src/ConstraintPropagationDebug.cpp
+++ b/test/src/ConstraintPropagationDebug.cpp
@@ -8,8 +8,9 @@
 #include "../../src/ShortestPath/Transit/TransitShortestPathPrecompute.h"
 #include "../../src/instance/Instance.h"
 #include "../../src/routes/vehicle/SAEVRoute.h"
+#include "../../src/utils/InstanceGenerator.h"
 
-TEST(TransitPreprocessUnitTest, DebugFunction) {
+TEST(ConstraintPropagationDebug, DebugBaseInstance) {
     std::string instancesPath = "../../resources/test/instances/Constraint Propagation/";
     std::string instanceFolder = "basic_debug_instance/";
     std::string graphDatFile = "graph.dat";
@@ -42,6 +43,26 @@ TEST(TransitPreprocessUnitTest, DebugFunction) {
     req0Changelist.revertChanges();
 }
 
+TEST(ConstraintPropagationDebug, DebugRequestGeneration) {
+    std::string instancesPath = "../../resources/test/instances/Constraint Propagation/";
+    std::string instanceFolder = "basic_debug_instance/";
+    std::string graphDatFile = "graph.dat";
+    std::string requestsDatFile = "requests.dat";
+
+    //Parse graph
+    Graph graphFromSingleFile(instancesPath + instanceFolder + graphDatFile);
+    std::vector<Request> requests = InstanceGenerator::generateRequests(graphFromSingleFile, 100, 110620241720);
+    std::vector<Request> requestsParameterized = InstanceGenerator::generateRequests(graphFromSingleFile, 100, 1.5, 15, 15, 480, 600, 110620241739);
+
+    assert(requests.size() == 100);
+    assert(requestsParameterized.size() == 100);
+
+    //Init instance
+    Instance instance(requests,graphFromSingleFile,4);
+    SAEVRoute routesContainer(graphFromSingleFile, requests);
+
+}
+
 int main(int argc, char* argv[]) {
     testing::InitGoogleTest(&argc, argv);
     return RUN_ALL_TESTS();
-- 
GitLab


From c911617c4a9286a81aeb40230a59dd56efe5d4e5 Mon Sep 17 00:00:00 2001
From: Romain BERNARD <romain.bernard@uca.fr>
Date: Wed, 12 Jun 2024 16:19:58 +0200
Subject: [PATCH 082/327] graph file export upate (export matrix, fix PT lines
 errors)

---
 src/instance/graph/Graph.cpp | 94 ++++++++++++++++++++----------------
 src/instance/graph/Graph.h   |  2 +-
 2 files changed, 53 insertions(+), 43 deletions(-)

diff --git a/src/instance/graph/Graph.cpp b/src/instance/graph/Graph.cpp
index 3eb551a..6ccb34c 100644
--- a/src/instance/graph/Graph.cpp
+++ b/src/instance/graph/Graph.cpp
@@ -118,65 +118,75 @@ Graph::Graph(const std::string& datFilePath) {
 }
 
 namespace fs = std::filesystem;
-void Graph::exportGraphToFiles(fs::path exportFolderPath) {
+void Graph::exportGraphToFile(const fs::path& exportFolderPath) {
     fs::create_directories(exportFolderPath);
 
     //Nodes
-    std::ofstream outfileNodes(exportFolderPath.string() + "nodes.txt", std::ofstream::out | std::ofstream::trunc); //open and clear file if it already existed
-    for(auto& node : this->nodesVector)
+    std::ofstream outfileGraph(exportFolderPath.string() + "graph.txt", std::ofstream::out | std::ofstream::trunc); //open and clear file if it already existed
+    outfileGraph << "#Nodes format : status (work, leisure, residential),x,y" << std::endl;
+    for(auto const& node : this->nodesVector)
     {
-        outfileNodes << node.getX() << " " << node.getY() << std::endl;
+        outfileGraph << node.getStatus() << "," << node.getX() << "," << node.getY() << std::endl;
     }
-    outfileNodes.close();
 
     //Edges
-    std::ofstream outfileEdges(exportFolderPath.string() + "edges.txt", std::ofstream::out |  std::ofstream::trunc); //open and clear file if it already existed
-    for(auto& edge : this->edgesVector)
-    {
-        outfileEdges << edge.getNodeStart() << " " << edge.getNodeEnd() << " " << edge.getLength() << std::endl;
+    if(!edgesVector.empty()) {
+        outfileGraph << "#Edges format : node_in,node_out,length" << std::endl;
+        for (auto &edge: this->edgesVector) {
+            outfileGraph << edge.getNodeStart() << "," << edge.getNodeEnd() << "," << edge.getLength() << std::endl;
+        }
     }
-    outfileEdges.close();
-
-    //Transit lines
-    std::ofstream outfilePT(exportFolderPath.string() + "ptlines.txt", std::ofstream::out |  std::ofstream::trunc); //open and clear file if it already existed
-    for(auto& ptline : this->transitLines)
-    {
-        //Print nodes in order on one line
-        std::ostringstream ossNodes;
-        std::vector<int> lineNodesVector = ptline.getNodes();
-        if (!lineNodesVector.empty())
-        {
-            // Convert all but the last element to avoid a trailing ","
-            std::copy(lineNodesVector.begin(), lineNodesVector.end()-1,
-                      std::ostream_iterator<int>(ossNodes, " "));
 
-            // Now add the last element with no delimiter
-            ossNodes << lineNodesVector.back();
+    //Matrix
+    if(!shortestSAEVPaths.empty()) {
+        outfileGraph << "#Matrix" << std::endl;
+        std::stringstream lineStringStream;
+        for (auto &matrixLine: this->shortestSAEVPaths) {
+            std::ranges::copy(matrixLine.begin(), matrixLine.end() - 1,
+                              std::ostream_iterator<int>(lineStringStream, ","));
+            lineStringStream << matrixLine.back();
+            outfileGraph << lineStringStream.rdbuf() << std::endl;
         }
-        std::cout << ossNodes.view() << std::endl;
-        outfilePT << ossNodes.str() << std::endl;
-        ossNodes.clear();
+    }
 
-        //Reuse string stream to print schedules line by line
-        for(auto& schedule : ptline.getTimetables())
-        {
-            std::ostringstream ossSchedule;
-            if (!schedule.empty())
-            {
+    //Transit lines
+    if(!getPTLines().empty()) {
+        outfileGraph << "#PT Lines" << std::endl;
+        for (auto const &ptline: this->transitLines) {
+            //Print nodes in order on one line
+            std::stringstream ossNodes;
+            std::vector<int> lineNodesVector = ptline.getNodes();
+            if (!lineNodesVector.empty()) {
                 // Convert all but the last element to avoid a trailing ","
-                std::copy(schedule.begin(), schedule.end()-1,
-                          std::ostream_iterator<int>(ossSchedule, " "));
+                std::copy(lineNodesVector.begin(), lineNodesVector.end() - 1,
+                          std::ostream_iterator<int>(ossNodes, ","));
 
                 // Now add the last element with no delimiter
-                ossSchedule << schedule.back();
+                ossNodes << lineNodesVector.back();
+            }
+            std::cout << ossNodes.view() << std::endl;
+            outfileGraph << ossNodes.rdbuf() << std::endl;
+            ossNodes.clear();
+
+            //Reuse string stream to print schedules line by line
+            std::stringstream ossSchedule;
+            for (auto &schedule: ptline.getTimetables()) {
+                if (!schedule.empty()) {
+                    // Convert all but the last element to avoid a trailing ","
+                    std::copy(schedule.begin(), schedule.end() - 1,
+                              std::ostream_iterator<int>(ossSchedule, ","));
+
+                    // Now add the last element with no delimiter
+                    ossSchedule << schedule.back();
+                }
+                std::cout << ossSchedule.view() << std::endl;
+                outfileGraph << ossSchedule.rdbuf() << std::endl;
+                ossSchedule.str("");
+                ossSchedule.clear();
             }
-            std::cout << ossSchedule.view() << std::endl;
-            outfilePT << ossSchedule.str() << std::endl;
-            ossSchedule.clear();
         }
-        outfilePT << "#PT line end" <<std::endl;
     }
-    outfilePT.close();
+    outfileGraph.close();
     std::cout << "results of graph validations : " << this->check() << std::endl;
 }
 
diff --git a/src/instance/graph/Graph.h b/src/instance/graph/Graph.h
index 1e37b62..389b8e5 100644
--- a/src/instance/graph/Graph.h
+++ b/src/instance/graph/Graph.h
@@ -134,7 +134,7 @@ public:
      * The function creates the folders if need be, and will overwrite existing files if data has been outputted to this folder before
      * @param exportFolderPath A path to a folder where we can export edges.txt, nodes.txt and ptlines.txt
      */
-    void exportGraphToFiles(std::filesystem::path exportFolderPath);
+    void exportGraphToFile(const std::filesystem::path& exportFolderPath);
 
     /**
      * Executes defined check functions on every node and transit line in the graph
-- 
GitLab


From ba4ac825f74ab17bb985630ce896e70e927535d4 Mon Sep 17 00:00:00 2001
From: Romain BERNARD <romain.bernard@uca.fr>
Date: Wed, 12 Jun 2024 16:20:40 +0200
Subject: [PATCH 083/327] minor fixes

---
 src/instance/graph/Graph.cpp | 10 +++++-----
 src/instance/graph/Line.h    | 10 +++++-----
 2 files changed, 10 insertions(+), 10 deletions(-)

diff --git a/src/instance/graph/Graph.cpp b/src/instance/graph/Graph.cpp
index 6ccb34c..36e2858 100644
--- a/src/instance/graph/Graph.cpp
+++ b/src/instance/graph/Graph.cpp
@@ -192,7 +192,7 @@ void Graph::exportGraphToFile(const fs::path& exportFolderPath) {
 
 bool Graph::check() {
     bool checkResult = true;
-    for(auto& transitLine : this->transitLines)
+    for(auto const& transitLine : this->transitLines)
     {
         checkResult &= transitLine.check();
     }
@@ -202,12 +202,12 @@ bool Graph::check() {
 
 bool Graph::checkLineToNodeLinks() {
     int nodeIndexFromLine;
-    Node* nodeFromGraph; //Forced to init here
+    Node const* nodeFromGraph; //Forced to init here
 
     bool checkResult = true;
-    for(auto& node : nodesVector)
+    for(auto const& node : nodesVector)
     {
-        for(auto& lineStop : node.getPTLinesSet())
+        for(auto const& lineStop : node.getPTLinesSet())
         {
             nodeIndexFromLine = lineStop.getLineRef().getNode(lineStop.getStopIndex());
             nodeFromGraph = &this->nodesVector.at(nodeIndexFromLine);
@@ -280,7 +280,7 @@ void Graph::parseLineRandomizedSchedule(const DATRow& row, std::mt19937 rng,
     }
 
     //Create subsequent timetables according to preceding timetable and travel time
-    for(int i = 1; i < newLine.getNodes().size(); ++i)
+    for(size_t i = 1; i < newLine.getNodes().size(); ++i)
     {
         int travelTime = travelTimeDistribution(rng); //FIXME travel time is randomized for now, we should get edge length if it exists I guess
         std::vector<int> precedingTimeTable = newLine.getTimetable(i - 1);
diff --git a/src/instance/graph/Line.h b/src/instance/graph/Line.h
index c9bc6f7..3f94c1e 100644
--- a/src/instance/graph/Line.h
+++ b/src/instance/graph/Line.h
@@ -22,14 +22,14 @@ public:
     [[nodiscard]] const std::string &getLineId() const;
     void setLineId(const std::string &lineId);
     [[nodiscard]] std::vector<int> getNodes() const { return _nodes;};
-    [[nodiscard]] int getNode(int index) const { return _nodes.at(index);};
+    [[nodiscard]] int getNode(size_t index) const { return _nodes.at(index);};
     void addNode(const int node){this->_nodes.emplace_back(node);};
     [[nodiscard]] bool isEmpty() const{return this->_nodes.empty() || _timetables.empty();}
 
-    [[nodiscard]] std::vector<int> getTimetable(int pos) const{ return _timetables.at(pos);};
+    [[nodiscard]] std::vector<int> getTimetable(size_t pos) const{ return _timetables.at(pos);};
     [[nodiscard]] std::vector<std::vector<int>> getTimetables() const{ return _timetables;};
     void addTimetable(const std::vector<int>& timetable) { _timetables.push_back(timetable);};
-    void setTimetable(int pos, const std::vector<int>& timetable) { _timetables.insert(_timetables.begin() + pos, timetable);};
+    void setTimetable(size_t pos, const std::vector<int>& timetable) { _timetables.insert(_timetables.begin() + pos, timetable);};
 
     /**
      * Searches for the next scheduled passage at a given station after a given instant O(log n)
@@ -37,7 +37,7 @@ public:
      * @param instant The instant of arrival at the station, hence we look for the value itself or the first greater instant
      * @return a vector index corresponding to the next valid passage at the given station and after or at the given instant
      */
-    [[nodiscard]] size_t findNextScheduledPassage(int stationIdx, int instant) const {
+    [[nodiscard]] size_t findNextScheduledPassage(size_t stationIdx, uint instant) const {
         return SearchAlgorithms<int>::findNextSortedValue(_timetables.at(stationIdx), instant);
     }
     /**
@@ -46,7 +46,7 @@ public:
      * @param scheduleIdx The expected index of our passage
      * @return The instant associated with the given station at the given schedule position
      */
-    [[nodiscard]] int getInstant(int stationIdx, int scheduleIdx) const { return _timetables.at(stationIdx).at(scheduleIdx); }
+    [[nodiscard]] int getInstant(size_t stationIdx, size_t scheduleIdx) const { return _timetables.at(stationIdx).at(scheduleIdx); }
 
     [[nodiscard]] size_t size() const {return _nodes.size();}
     [[nodiscard]] size_t scheduleSize() const {return _timetables.empty() ? 0 : _timetables.at(0).size();}
-- 
GitLab


From 546b93b069cc793ca03a9b0a0fc3967a2c612e97 Mon Sep 17 00:00:00 2001
From: Romain BERNARD <romain.bernard@uca.fr>
Date: Wed, 12 Jun 2024 16:21:26 +0200
Subject: [PATCH 084/327] fix transit preprocess test

---
 test/CMakeLists.txt                 | 8 ++++----
 test/src/TransitPreprocessDebug.cpp | 4 ++--
 2 files changed, 6 insertions(+), 6 deletions(-)

diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt
index 3916656..8d09977 100644
--- a/test/CMakeLists.txt
+++ b/test/CMakeLists.txt
@@ -19,7 +19,7 @@ add_executable(Line_UT
         ../src/instance/graph/Line.h
 )
 
-add_executable(Transit_preprocess_DEB
+add_executable(Transit_Preprocess_DEB
         src/TransitPreprocessDebug.cpp
         ../src/instance/graph/Node.cpp
         ../src/instance/graph/Node.h
@@ -66,10 +66,10 @@ add_executable(Constraint_Propag_DEB
         ../src/routes/RequestKeyPoint.h
         ../src/routes/RequestRoute.cpp
         ../src/routes/RequestRoute.h
-        ../src/utils/InstanceGenerator.cpp
-        ../src/utils/InstanceGenerator.h
+        ../src/utils/RequestsGenerator.cpp
+        ../src/utils/RequestsGenerator.h
 )
 
 target_link_libraries(Line_UT gtest gtest_main)
-target_link_libraries(Transit_preprocess_DEB gtest gtest_main)
+target_link_libraries(Transit_Preprocess_DEB gtest gtest_main)
 target_link_libraries(Constraint_Propag_DEB gtest gtest_main)
\ No newline at end of file
diff --git a/test/src/TransitPreprocessDebug.cpp b/test/src/TransitPreprocessDebug.cpp
index 66d1bba..66d32f3 100644
--- a/test/src/TransitPreprocessDebug.cpp
+++ b/test/src/TransitPreprocessDebug.cpp
@@ -7,13 +7,13 @@
 #include "../../src/ShortestPath/Transit/TransitShortestPathContainer.h"
 #include "../../src/ShortestPath/Transit/TransitShortestPathPrecompute.h"
 
-TEST(TransitPreprocessUnitTest, DebugFunction) {
+TEST(Transit_Preprocess_DEB, DebugFunction) {
     std::string instancesPath = "../../resources/test/instances/PT Shortest Path/";
     std::string instanceFolder = "contiguous_lines_debug_instance/";
     std::string datFile = "graph.dat";
 
     Graph graphFromSingleFile(instancesPath + instanceFolder + datFile);
-    graphFromSingleFile.exportGraphToFiles("../resources/test/outputs/" + instanceFolder);
+    graphFromSingleFile.exportGraphToFile("../../resources/test/outputs/" + instanceFolder);
     TransitShortestPathContainer contiguousContainer(graphFromSingleFile.getNbNodes());
     for(auto& ptLine : graphFromSingleFile.getPTLines()) {
         for(int i = 0; i < ptLine.size(); ++i) {
-- 
GitLab


From 1137299b05cec20c8d25dbbd8700ea036a0f493e Mon Sep 17 00:00:00 2001
From: Romain BERNARD <romain.bernard@uca.fr>
Date: Wed, 12 Jun 2024 16:23:44 +0200
Subject: [PATCH 085/327] refactor InstanceGenerator to RequestsGenerator for
 better class specification

---
 CMakeLists.txt                                |  4 +-
 src/utils/InstanceGenerator.h                 | 49 -----------
 ...nceGenerator.cpp => RequestsGenerator.cpp} | 23 ++++-
 src/utils/RequestsGenerator.h                 | 84 +++++++++++++++++++
 test/src/ConstraintPropagationDebug.cpp       |  6 +-
 5 files changed, 109 insertions(+), 57 deletions(-)
 delete mode 100644 src/utils/InstanceGenerator.h
 rename src/utils/{InstanceGenerator.cpp => RequestsGenerator.cpp} (65%)
 create mode 100644 src/utils/RequestsGenerator.h

diff --git a/CMakeLists.txt b/CMakeLists.txt
index fcb3c6c..34b1194 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -58,8 +58,8 @@ add_executable(GreedyAlgorithm
         src/routes/vehicle/propagation/SAEVRouteChangelist.h
         src/routes/vehicle/propagation/SAEVRouteChange.cpp
         src/routes/vehicle/propagation/SAEVRouteChange.h
-        src/utils/InstanceGenerator.cpp
-        src/utils/InstanceGenerator.h
+        src/utils/RequestsGenerator.cpp
+        src/utils/RequestsGenerator.h
 )
 
 target_include_directories(GreedyAlgorithm PRIVATE ${PYTHON_INCLUDE_DIRS})
diff --git a/src/utils/InstanceGenerator.h b/src/utils/InstanceGenerator.h
deleted file mode 100644
index 4a5ec47..0000000
--- a/src/utils/InstanceGenerator.h
+++ /dev/null
@@ -1,49 +0,0 @@
-//
-// Created by romain on 11/06/24.
-//
-
-#ifndef GREEDYALGORITHM_INSTANCEGENERATOR_H
-#define GREEDYALGORITHM_INSTANCEGENERATOR_H
-
-
-#include <vector>
-#include "../instance/requests/Request.h"
-
-class InstanceGenerator {
-public:
-
-    /**
-     * Parametrized request generation method.
-     * @param graph the graph on which requests are generated (required for node lists and shortest paths between nodes)
-     * @param requestAmount How many requests to generate
-     * @param deltaRatio ratio by which the direct path duration for a request is multiplied to get the max routing time
-     * @param deltaMinDuration minimum delta value added to the direct path duration to get a max delta time
-     * @param timeWindowWidth size of the time window available on arrival
-     * @param periodStartTime start time for the period during which requests can be served
-     * @param periodEndTime end time for the period during which requests can be served
-     * @param rngSeed a seed to ensure reproducibility
-     * @return a vector of randomly generated requests according to the given parameters
-     */
-    [[nodiscard]] static std::vector<Request> generateRequests(const Graph& graph, size_t requestAmount,
-                                          double deltaRatio, uint deltaMinDuration, uint timeWindowWidth,
-                                          uint periodStartTime, uint periodEndTime, ulong rngSeed);
-
-    /**
-     * Default parameter request generation.
-     * Parameters :
-     *  Delta ratio = 1.25 (users will accept at most a trip 25% longer than the shortest path)
-     *  Time Window width = 30 (users will have a 30 minute range of acceptable arrival dates)
-     *  Delta ratio = 1.25
-     *  Delta min leeway = 10 minutes of minimum possible detour time to calculate delta value
-     *  periodStartTime = 360 (requests start after 6am)
-     *  periodEndTime = 660 (requests end before 11am)
-     * @param graph the graph on which requests are generated (required for node lists and shortest paths between nodes)
-     * @param requestAmount How many requests to generate
-     * @param rngSeed a seed to ensure reproducibility
-     * @return a vector of randomly generated requests according to the given parameters
-     */
-    [[nodiscard]] static std::vector<Request> generateRequests(const Graph& graph, size_t requestAmount, ulong rngSeed);
-};
-
-
-#endif //GREEDYALGORITHM_INSTANCEGENERATOR_H
diff --git a/src/utils/InstanceGenerator.cpp b/src/utils/RequestsGenerator.cpp
similarity index 65%
rename from src/utils/InstanceGenerator.cpp
rename to src/utils/RequestsGenerator.cpp
index badb1e7..1c989fe 100644
--- a/src/utils/InstanceGenerator.cpp
+++ b/src/utils/RequestsGenerator.cpp
@@ -2,10 +2,10 @@
 // Created by romain on 11/06/24.
 //
 
-#include "InstanceGenerator.h"
+#include "RequestsGenerator.h"
 
 std::vector<Request>
-InstanceGenerator::generateRequests(const Graph &graph, size_t requestAmount, double deltaRatio, uint deltaMinDuration,
+RequestsGenerator::generateRequests(const Graph &graph, size_t requestAmount, double deltaRatio, uint deltaMinDuration,
                                     uint timeWindowWidth, uint periodStartTime, uint periodEndTime, ulong rngSeed) {
     std::mt19937 rng(rngSeed);
     std::vector<Request> requests;
@@ -44,6 +44,23 @@ InstanceGenerator::generateRequests(const Graph &graph, size_t requestAmount, do
     return requests;
 }
 
-std::vector<Request> InstanceGenerator::generateRequests(const Graph &graph, size_t requestAmount, ulong rngSeed) {
+std::vector<Request> RequestsGenerator::generateRequests(const Graph &graph, size_t requestAmount, ulong rngSeed) {
     return generateRequests(graph, requestAmount, 1.25, 10, 30, 360, 660, rngSeed);
 }
+
+bool
+RequestsGenerator::generateAndExportRequests(const std::string exportFolderPath, const Graph &graph,
+                                             size_t requestAmount, ulong rngSeed) {
+    std::vector<Request> generatedRequests = generateRequests(graph, requestAmount, rngSeed);
+
+    return true;
+}
+
+bool
+RequestsGenerator::generateAndExportRequests(const std::string exportFolderPath, const Graph &graph, size_t requestAmount,
+                                             double deltaRatio, uint deltaMinDuration, uint timeWindowWidth,
+                                             uint periodStartTime, uint periodEndTime, ulong rngSeed) {
+    std::vector<Request> generatedRequests = generateRequests(graph, requestAmount, deltaRatio, deltaMinDuration, timeWindowWidth,
+                                                              periodStartTime, periodEndTime, rngSeed);
+    return true;
+}
diff --git a/src/utils/RequestsGenerator.h b/src/utils/RequestsGenerator.h
new file mode 100644
index 0000000..90081eb
--- /dev/null
+++ b/src/utils/RequestsGenerator.h
@@ -0,0 +1,84 @@
+//
+// Created by romain on 11/06/24.
+//
+
+#ifndef GREEDYALGORITHM_REQUESTSGENERATOR_H
+#define GREEDYALGORITHM_REQUESTSGENERATOR_H
+
+
+#include <vector>
+#include "../instance/requests/Request.h"
+
+class RequestsGenerator {
+public:
+
+    /**
+     * Parametrized request generation method.
+     * @param graph the graph on which requests are generated (required for node lists and shortest paths between nodes)
+     * @param requestAmount How many requests to generate
+     * @param deltaRatio ratio by which the direct path duration for a request is multiplied to get the max routing time
+     * @param deltaMinDuration minimum delta value added to the direct path duration to get a max delta time
+     * @param timeWindowWidth size of the time window available on arrival
+     * @param periodStartTime start time for the period during which requests can be served
+     * @param periodEndTime end time for the period during which requests can be served
+     * @param rngSeed a seed to ensure reproducibility
+     * @return a vector of randomly generated requests according to the given parameters
+     */
+    [[nodiscard]] static std::vector<Request> generateRequests(const Graph& graph, size_t requestAmount,
+                                          double deltaRatio, uint deltaMinDuration, uint timeWindowWidth,
+                                          uint periodStartTime, uint periodEndTime, ulong rngSeed);
+
+    /**
+     * Default parameter request generation.
+     * Parameters :
+     *  Delta ratio = 1.25 (users will accept at most a trip 25% longer than the shortest path)
+     *  Time Window width = 30 (users will have a 30 minute range of acceptable arrival dates)
+     *  Delta ratio = 1.25
+     *  Delta min leeway = 10 minutes of minimum possible detour time to calculate delta value
+     *  periodStartTime = 360 (requests start after 6am)
+     *  periodEndTime = 660 (requests end before 11am)
+     * @param graph the graph on which requests are generated (required for node lists and shortest paths between nodes)
+     * @param requestAmount How many requests to generate
+     * @param rngSeed a seed to ensure reproducibility
+     * @return a vector of randomly generated requests according to the given parameters
+     */
+    [[nodiscard]] static std::vector<Request> generateRequests(const Graph& graph, size_t requestAmount, ulong rngSeed);
+
+    /**
+     * Default parameter request generation with file export.
+     * Parameters :
+     *  Delta ratio = 1.25 (users will accept at most a trip 25% longer than the shortest path)
+     *  Time Window width = 30 (users will have a 30 minute range of acceptable arrival dates)
+     *  Delta ratio = 1.25
+     *  Delta min leeway = 10 minutes of minimum possible detour time to calculate delta value
+     *  periodStartTime = 360 (requests start after 6am)
+     *  periodEndTime = 660 (requests end before 11am)
+     * @param exportFolderPath folder path to which the requests will be exported in a "requests.dat" file, a requestsInfo.txt will be exported with seed/parameter info (will overwrite any existing content)
+     * @param graph the graph on which requests are generated (required for node lists and shortest paths between nodes)
+     * @param requestAmount How many requests to generate
+     * @param rngSeed a seed to ensure reproducibility
+     * @return True iff all requests were generated and exported properly
+     */
+    [[nodiscard]] static bool generateAndExportRequests(const std::string exportFolderPath, const Graph& graph, size_t requestAmount, ulong rngSeed);
+
+    /**
+     * Parametrized request generation method with file export.
+     * @param exportFolderPath folder path to which the requests will be exported in a "requests.dat" file, a requestsInfo.txt will be exported with seed/parameter info (will overwrite any existing content)
+     * @param graph the graph on which requests are generated (required for node lists and shortest paths between nodes)
+     * @param requestAmount How many requests to generate
+     * @param deltaRatio ratio by which the direct path duration for a request is multiplied to get the max routing time
+     * @param deltaMinDuration minimum delta value added to the direct path duration to get a max delta time
+     * @param timeWindowWidth size of the time window available on arrival
+     * @param periodStartTime start time for the period during which requests can be served
+     * @param periodEndTime end time for the period during which requests can be served
+     * @param rngSeed a seed to ensure reproducibility
+     * @return True iff all requests were generated and exported properly
+     */
+    [[nodiscard]] static bool generateAndExportRequests(const std::string exportFolderPath, const Graph& graph, size_t requestAmount,
+                                                        double deltaRatio, uint deltaMinDuration, uint timeWindowWidth,
+                                                        uint periodStartTime, uint periodEndTime, ulong rngSeed);
+
+};
+
+
+#endif //GREEDYALGORITHM_REQUESTSGENERATOR_H
diff --git a/test/src/ConstraintPropagationDebug.cpp b/test/src/ConstraintPropagationDebug.cpp
index 6471ef8..8f28a61 100644
--- a/test/src/ConstraintPropagationDebug.cpp
+++ b/test/src/ConstraintPropagationDebug.cpp
@@ -8,7 +8,7 @@
 #include "../../src/ShortestPath/Transit/TransitShortestPathPrecompute.h"
 #include "../../src/instance/Instance.h"
 #include "../../src/routes/vehicle/SAEVRoute.h"
-#include "../../src/utils/InstanceGenerator.h"
+#include "../../src/utils/RequestsGenerator.h"
 
 TEST(ConstraintPropagationDebug, DebugBaseInstance) {
     std::string instancesPath = "../../resources/test/instances/Constraint Propagation/";
@@ -51,8 +51,8 @@ TEST(ConstraintPropagationDebug, DebugRequestGeneration) {
 
     //Parse graph
     Graph graphFromSingleFile(instancesPath + instanceFolder + graphDatFile);
-    std::vector<Request> requests = InstanceGenerator::generateRequests(graphFromSingleFile, 100, 110620241720);
-    std::vector<Request> requestsParameterized = InstanceGenerator::generateRequests(graphFromSingleFile, 100, 1.5, 15, 15, 480, 600, 110620241739);
+    std::vector<Request> requests = RequestsGenerator::generateRequests(graphFromSingleFile, 100, 110620241720);
+    std::vector<Request> requestsParameterized = RequestsGenerator::generateRequests(graphFromSingleFile, 100, 1.5, 15, 15, 480, 600, 110620241739);
 
     assert(requests.size() == 100);
     assert(requestsParameterized.size() == 100);
-- 
GitLab


From f2df5cd1b04ce16f944690174cbd1d4f7f454340 Mon Sep 17 00:00:00 2001
From: Romain BERNARD <romain.bernard@uca.fr>
Date: Wed, 12 Jun 2024 17:19:12 +0200
Subject: [PATCH 086/327] remove unnecessary assignment

---
 src/utils/RequestsGenerator.cpp | 4 ----
 1 file changed, 4 deletions(-)

diff --git a/src/utils/RequestsGenerator.cpp b/src/utils/RequestsGenerator.cpp
index 1c989fe..c852490 100644
--- a/src/utils/RequestsGenerator.cpp
+++ b/src/utils/RequestsGenerator.cpp
@@ -19,10 +19,6 @@ RequestsGenerator::generateRequests(const Graph &graph, size_t requestAmount, do
     uint requestTWStart;
     ulong originNodeIdx, destinationNodeIdx;
     for(size_t i = 0; i < requestAmount; ++i) {
-        //Reset values
-        originNodeIdx = -1;
-        destinationNodeIdx = -1;
-
         //Generate new values
         requestTWStart = requestTWStartDistribution(rng);
         originNodeIdx = nodeDistribution(rng);
-- 
GitLab


From 5001f33c0e27afcf62bed08be05ccf1eadcae65c Mon Sep 17 00:00:00 2001
From: Romain BERNARD <romain.bernard@uca.fr>
Date: Wed, 12 Jun 2024 18:30:32 +0200
Subject: [PATCH 087/327] encapsulate request generation parameters in their
 own class

---
 CMakeLists.txt                          |   1 +
 src/utils/RequestGenerationParameters.h | 121 ++++++++++++++++++++++++
 src/utils/RequestsGenerator.cpp         |  20 +++-
 src/utils/RequestsGenerator.h           |  63 ++----------
 test/CMakeLists.txt                     |   1 +
 test/src/ConstraintPropagationDebug.cpp |   6 +-
 6 files changed, 151 insertions(+), 61 deletions(-)
 create mode 100644 src/utils/RequestGenerationParameters.h

diff --git a/CMakeLists.txt b/CMakeLists.txt
index 34b1194..d886435 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -60,6 +60,7 @@ add_executable(GreedyAlgorithm
         src/routes/vehicle/propagation/SAEVRouteChange.h
         src/utils/RequestsGenerator.cpp
         src/utils/RequestsGenerator.h
+        src/utils/RequestGenerationParameters.h
 )
 
 target_include_directories(GreedyAlgorithm PRIVATE ${PYTHON_INCLUDE_DIRS})
diff --git a/src/utils/RequestGenerationParameters.h b/src/utils/RequestGenerationParameters.h
new file mode 100644
index 0000000..e400a10
--- /dev/null
+++ b/src/utils/RequestGenerationParameters.h
@@ -0,0 +1,121 @@
+//
+// Created by romain on 12/06/24.
+//
+
+#ifndef GREEDYALGORITHM_REQUESTGENERATIONPARAMETERS_H
+#define GREEDYALGORITHM_REQUESTGENERATIONPARAMETERS_H
+
+
+#include <cstdlib>
+#include <ostream>
+
+class RequestGenerationParameters {
+private:
+    size_t _requestAmount;
+    double _deltaRatio;
+    uint _deltaMinDuration;
+    uint _timeWindowWidth;
+    uint _periodStartTime;
+    uint _periodEndTime;
+    ulong _rngSeed;
+    //finding a way to add the graph to these parameters would be good, but adding a dependency between graph and request generation parameters doesn't feel right
+public:
+    /**
+     * Generates a request generation parameter container with default parameters (giving a seed is mandatory still !)
+     * Default parameters :
+     *  Delta ratio = 1.25 (users will accept at most a trip 25% longer than the shortest path)
+     *  Time Window width = 30 (users will have a 30 minute range of acceptable arrival dates)
+     *  Delta ratio = 1.25
+     *  Delta min leeway = 10 minutes of minimum possible detour time to calculate delta value
+     *  periodStartTime = 360 (requests start after 6am)
+     *  periodEndTime = 660 (requests end before 11am)
+     * @param requestAmount How many requests to generate
+     * @param rngSeed a seed to ensure reproducibility of the generation
+     */
+    explicit RequestGenerationParameters(size_t requestAmount, ulong rngSeed) : _requestAmount(requestAmount), _deltaRatio(1.25), _deltaMinDuration(10), _timeWindowWidth(30),
+    _periodStartTime(360), _periodEndTime(660), _rngSeed(rngSeed) {}
+
+    /**
+     * Generates a request generation parameter container with the given parameters
+     * @param requestAmount How many requests to generate
+     * @param deltaRatio ratio by which the direct path duration for a request is multiplied to get the max routing time
+     * @param deltaMinDuration minimum delta value added to the direct path duration to get a max delta time
+     * @param timeWindowWidth size of the time window available on arrival
+     * @param periodStartTime start time for the period during which requests can be served
+     * @param periodEndTime end time for the period during which requests can be served
+     * @param rngSeed a seed to ensure reproducibility of the generation
+     */
+    RequestGenerationParameters(size_t requestAmount, double deltaRatio, uint deltaMinDuration, uint timeWindowWidth,
+                                uint periodStartTime, uint periodEndTime, ulong rngSeed) : _requestAmount(
+            requestAmount), _deltaRatio(deltaRatio), _deltaMinDuration(deltaMinDuration), _timeWindowWidth(
+            timeWindowWidth), _periodStartTime(periodStartTime), _periodEndTime(periodEndTime), _rngSeed(rngSeed) {}
+
+    size_t getRequestAmount() const {
+        return _requestAmount;
+    }
+
+    void setRequestAmount(size_t requestAmount) {
+        _requestAmount = requestAmount;
+    }
+
+    double getDeltaRatio() const {
+        return _deltaRatio;
+    }
+
+    void setDeltaRatio(double deltaRatio) {
+        _deltaRatio = deltaRatio;
+    }
+
+    uint getDeltaMinDuration() const {
+        return _deltaMinDuration;
+    }
+
+    void setDeltaMinDuration(uint deltaMinDuration) {
+        _deltaMinDuration = deltaMinDuration;
+    }
+
+    uint getTimeWindowWidth() const {
+        return _timeWindowWidth;
+    }
+
+    void setTimeWindowWidth(uint timeWindowWidth) {
+        _timeWindowWidth = timeWindowWidth;
+    }
+
+    uint getPeriodStartTime() const {
+        return _periodStartTime;
+    }
+
+    void setPeriodStartTime(uint periodStartTime) {
+        _periodStartTime = periodStartTime;
+    }
+
+    uint getPeriodEndTime() const {
+        return _periodEndTime;
+    }
+
+    void setPeriodEndTime(uint periodEndTime) {
+        _periodEndTime = periodEndTime;
+    }
+
+    ulong getRngSeed() const {
+        return _rngSeed;
+    }
+
+    void setRngSeed(ulong rngSeed) {
+        _rngSeed = rngSeed;
+    }
+
+    friend std::ostream &operator<<(std::ostream &os, const RequestGenerationParameters &parameters) {
+        os << "_requestAmount: " << parameters._requestAmount << "\n_deltaRatio: " << parameters._deltaRatio
+           << "\n_deltaMinDuration: " << parameters._deltaMinDuration << "\n_timeWindowWidth: "
+           << parameters._timeWindowWidth << "\n_periodStartTime: " << parameters._periodStartTime << "\n_periodEndTime: "
+           << parameters._periodEndTime << "\n_rngSeed: " << parameters._rngSeed;
+        return os;
+    }
+
+    bool operator==(const RequestGenerationParameters &rhs) const = default;
+};
+
+
+#endif //GREEDYALGORITHM_REQUESTGENERATIONPARAMETERS_H
diff --git a/src/utils/RequestsGenerator.cpp b/src/utils/RequestsGenerator.cpp
index c852490..f5aa7c6 100644
--- a/src/utils/RequestsGenerator.cpp
+++ b/src/utils/RequestsGenerator.cpp
@@ -2,16 +2,26 @@
 // Created by romain on 11/06/24.
 //
 
+#include <filesystem>
+#include <fstream>
 #include "RequestsGenerator.h"
+#include "RequestGenerationParameters.h"
+
+namespace fs = std::filesystem;
 
 std::vector<Request>
-RequestsGenerator::generateRequests(const Graph &graph, size_t requestAmount, double deltaRatio, uint deltaMinDuration,
-                                    uint timeWindowWidth, uint periodStartTime, uint periodEndTime, ulong rngSeed) {
-    std::mt19937 rng(rngSeed);
+RequestsGenerator::generateRequests(const Graph &graph, RequestGenerationParameters generationParameters) {
+    size_t requestAmount = generationParameters.getRequestAmount();
+    double deltaRatio = generationParameters.getDeltaRatio();
+    double deltaMinDuration = generationParameters.getDeltaMinDuration();
+    uint timeWindowWidth = generationParameters.getTimeWindowWidth();
+
     std::vector<Request> requests;
     requests.reserve(requestAmount);
-    //reduce period window time to account for TW width
-    std::uniform_int_distribution<uint32_t> requestTWStartDistribution(periodStartTime + timeWindowWidth, periodEndTime - timeWindowWidth);
+    std::mt19937 rng(generationParameters.getRngSeed());
+    std::uniform_int_distribution<uint32_t> requestTWStartDistribution(generationParameters.getPeriodStartTime() + timeWindowWidth,
+                                                                       generationParameters.getPeriodEndTime() - timeWindowWidth); //reduce period window time to account for TW width
+
     std::uniform_int_distribution<ulong> nodeDistribution(0, graph.getNbNodes() - 1);
 
     //Init request variables
diff --git a/src/utils/RequestsGenerator.h b/src/utils/RequestsGenerator.h
index 90081eb..2c39d7e 100644
--- a/src/utils/RequestsGenerator.h
+++ b/src/utils/RequestsGenerator.h
@@ -7,7 +7,11 @@
 
 
 #include <vector>
+#include <filesystem>
 #include "../instance/requests/Request.h"
+#include "RequestGenerationParameters.h"
+
+namespace fs = std::filesystem;
 
 class RequestsGenerator {
 public:
@@ -15,68 +19,19 @@ public:
     /**
      * Parametrized request generation method.
      * @param graph the graph on which requests are generated (required for node lists and shortest paths between nodes)
-     * @param requestAmount How many requests to generate
-     * @param deltaRatio ratio by which the direct path duration for a request is multiplied to get the max routing time
-     * @param deltaMinDuration minimum delta value added to the direct path duration to get a max delta time
-     * @param timeWindowWidth size of the time window available on arrival
-     * @param periodStartTime start time for the period during which requests can be served
-     * @param periodEndTime end time for the period during which requests can be served
-     * @param rngSeed a seed to ensure reproducibility
-     * @return a vector of randomly generated requests according to the given parameters
-     */
-    [[nodiscard]] static std::vector<Request> generateRequests(const Graph& graph, size_t requestAmount,
-                                          double deltaRatio, uint deltaMinDuration, uint timeWindowWidth,
-                                          uint periodStartTime, uint periodEndTime, ulong rngSeed);
-
-    /**
-     * Default parameter request generation.
-     * Parameters :
-     *  Delta ratio = 1.25 (users will accept at most a trip 25% longer than the shortest path)
-     *  Time Window width = 30 (users will have a 30 minute range of acceptable arrival dates)
-     *  Delta ratio = 1.25
-     *  Delta min leeway = 10 minutes of minimum possible detour time to calculate delta value
-     *  periodStartTime = 360 (requests start after 6am)
-     *  periodEndTime = 660 (requests end before 11am)
-     * @param graph the graph on which requests are generated (required for node lists and shortest paths between nodes)
-     * @param requestAmount How many requests to generate
-     * @param rngSeed a seed to ensure reproducibility
+     * @param generationParameters the list of generation parameters to use for this request generation (see RequestGeberationParameters constructors)
      * @return a vector of randomly generated requests according to the given parameters
      */
-    [[nodiscard]] static std::vector<Request> generateRequests(const Graph& graph, size_t requestAmount, ulong rngSeed);
-
-    /**
-     * Default parameter request generation with file export.
-     * Parameters :
-     *  Delta ratio = 1.25 (users will accept at most a trip 25% longer than the shortest path)
-     *  Time Window width = 30 (users will have a 30 minute range of acceptable arrival dates)
-     *  Delta ratio = 1.25
-     *  Delta min leeway = 10 minutes of minimum possible detour time to calculate delta value
-     *  periodStartTime = 360 (requests start after 6am)
-     *  periodEndTime = 660 (requests end before 11am)
-     * @param exportFolderPath folder path to which the requests will be exported in a "requests.dat" file, a requestsInfo.txt will be exported with seed/parameter info (will overwrite any existing content)
-     * @param graph the graph on which requests are generated (required for node lists and shortest paths between nodes)
-     * @param requestAmount How many requests to generate
-     * @param rngSeed a seed to ensure reproducibility
-     * @return True iff all requests were generated and exported properly
-     */
-    [[nodiscard]] static bool generateAndExportRequests(const std::string exportFolderPath, const Graph& graph, size_t requestAmount, ulong rngSeed);
+    [[nodiscard]] static std::vector<Request> generateRequests(const Graph& graph, RequestGenerationParameters generationParameters);
 
     /**
      * Parametrized request generation method with file export.
      * @param exportFolderPath folder path to which the requests will be exported in a "requests.dat" file, a requestsInfo.txt will be exported with seed/parameter info (will overwrite any existing content)
      * @param graph the graph on which requests are generated (required for node lists and shortest paths between nodes)
-     * @param requestAmount How many requests to generate
-     * @param deltaRatio ratio by which the direct path duration for a request is multiplied to get the max routing time
-     * @param deltaMinDuration minimum delta value added to the direct path duration to get a max delta time
-     * @param timeWindowWidth size of the time window available on arrival
-     * @param periodStartTime start time for the period during which requests can be served
-     * @param periodEndTime end time for the period during which requests can be served
-     * @param rngSeed a seed to ensure reproducibility
-     * @return True iff all requests were generated and exported properly
+     * @param generationParameters the list of generation parameters to use for this request generation (see RequestGeberationParameters constructors)
+     * @return a vector of randomly generated requests according to the given parameters
      */
-    [[nodiscard]] static bool generateAndExportRequests(const std::string exportFolderPath, const Graph& graph, size_t requestAmount,
-                                                        double deltaRatio, uint deltaMinDuration, uint timeWindowWidth,
-                                                        uint periodStartTime, uint periodEndTime, ulong rngSeed);
+    [[nodiscard]] static std::vector<Request> generateAndExportRequests(const fs::path &exportFolderPath, const Graph& graph, const RequestGenerationParameters &generationParameters);
 
 };
 
diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt
index 8d09977..831009b 100644
--- a/test/CMakeLists.txt
+++ b/test/CMakeLists.txt
@@ -68,6 +68,7 @@ add_executable(Constraint_Propag_DEB
         ../src/routes/RequestRoute.h
         ../src/utils/RequestsGenerator.cpp
         ../src/utils/RequestsGenerator.h
+        ../src/utils/RequestGenerationParameters.h
 )
 
 target_link_libraries(Line_UT gtest gtest_main)
diff --git a/test/src/ConstraintPropagationDebug.cpp b/test/src/ConstraintPropagationDebug.cpp
index 8f28a61..e2b2e7d 100644
--- a/test/src/ConstraintPropagationDebug.cpp
+++ b/test/src/ConstraintPropagationDebug.cpp
@@ -51,8 +51,10 @@ TEST(ConstraintPropagationDebug, DebugRequestGeneration) {
 
     //Parse graph
     Graph graphFromSingleFile(instancesPath + instanceFolder + graphDatFile);
-    std::vector<Request> requests = RequestsGenerator::generateRequests(graphFromSingleFile, 100, 110620241720);
-    std::vector<Request> requestsParameterized = RequestsGenerator::generateRequests(graphFromSingleFile, 100, 1.5, 15, 15, 480, 600, 110620241739);
+    std::vector<Request> requests = RequestsGenerator::generateAndExportRequests("../../resources/test/outputs/propag/" + instanceFolder, graphFromSingleFile,
+                                                                                 RequestGenerationParameters(100, 110620241720));
+    std::vector<Request> requestsParameterized = RequestsGenerator::generateAndExportRequests("../../resources/test/outputs/propag/" + instanceFolder,graphFromSingleFile,
+                                                                                              RequestGenerationParameters(100, 1.5, 15, 15, 480, 600, 110620241739));
 
     assert(requests.size() == 100);
     assert(requestsParameterized.size() == 100);
-- 
GitLab


From b723b2bd9a80c47cb7078eb6890c991d402460c1 Mon Sep 17 00:00:00 2001
From: Romain BERNARD <romain.bernard@uca.fr>
Date: Wed, 12 Jun 2024 18:32:22 +0200
Subject: [PATCH 088/327] export requests and gen info to file after generation

---
 src/instance/requests/Request.cpp |  7 +++++++
 src/instance/requests/Request.h   |  7 +++++++
 src/utils/RequestsGenerator.cpp   | 34 ++++++++++++++-----------------
 3 files changed, 29 insertions(+), 19 deletions(-)

diff --git a/src/instance/requests/Request.cpp b/src/instance/requests/Request.cpp
index 72c822f..2b71256 100644
--- a/src/instance/requests/Request.cpp
+++ b/src/instance/requests/Request.cpp
@@ -196,3 +196,10 @@ void Request::setLineStop(int routeIndex, LineStop *lineStop) {
 void Request::resetKeyPoint(int routeIndex) {
     _currentRoute.resetKeyPoint(routeIndex);
 }
+
+std::string Request::to_string_export() {
+    std::string res = std::to_string(_originNodeIndex) + "," + std::to_string(_destinationNodeIndex) //FIXME:replace with std::format whenever possible
+            + "," + std::to_string(_arrivalTW.min) + "," + std::to_string(_arrivalTW.max)
+            + "," + std::to_string(_deltaTime) + "," + std::to_string(_weight);
+    return res;
+}
diff --git a/src/instance/requests/Request.h b/src/instance/requests/Request.h
index ccedd76..bec3589 100644
--- a/src/instance/requests/Request.h
+++ b/src/instance/requests/Request.h
@@ -76,6 +76,13 @@ public:
 
     void resetKeyPoint(int routeIndex);
 
+    /**
+     * Creates a string in an appropriate format for the request to be exported to a file that can be imported again
+     * <br> <br>
+     * Format : origin_idx,destination_idx,min,max,delta,capacity
+     * @return A properly formatted string to import back again
+     */
+    std::string to_string_export();
 };
 
 
diff --git a/src/utils/RequestsGenerator.cpp b/src/utils/RequestsGenerator.cpp
index f5aa7c6..f6fa0d9 100644
--- a/src/utils/RequestsGenerator.cpp
+++ b/src/utils/RequestsGenerator.cpp
@@ -50,23 +50,19 @@ RequestsGenerator::generateRequests(const Graph &graph, RequestGenerationParamet
     return requests;
 }
 
-std::vector<Request> RequestsGenerator::generateRequests(const Graph &graph, size_t requestAmount, ulong rngSeed) {
-    return generateRequests(graph, requestAmount, 1.25, 10, 30, 360, 660, rngSeed);
-}
-
-bool
-RequestsGenerator::generateAndExportRequests(const std::string exportFolderPath, const Graph &graph,
-                                             size_t requestAmount, ulong rngSeed) {
-    std::vector<Request> generatedRequests = generateRequests(graph, requestAmount, rngSeed);
-
-    return true;
-}
-
-bool
-RequestsGenerator::generateAndExportRequests(const std::string exportFolderPath, const Graph &graph, size_t requestAmount,
-                                             double deltaRatio, uint deltaMinDuration, uint timeWindowWidth,
-                                             uint periodStartTime, uint periodEndTime, ulong rngSeed) {
-    std::vector<Request> generatedRequests = generateRequests(graph, requestAmount, deltaRatio, deltaMinDuration, timeWindowWidth,
-                                                              periodStartTime, periodEndTime, rngSeed);
-    return true;
+std::vector<Request>
+RequestsGenerator::generateAndExportRequests(const fs::path &exportFolderPath, const Graph &graph, const RequestGenerationParameters &generationParameters) {
+    std::vector<Request> generatedRequests = generateRequests(graph, generationParameters);
+    //Write requests to files
+    fs::create_directories(exportFolderPath);
+    std::ofstream outfileGraph(exportFolderPath.string() + "requests.txt", std::ofstream::out | std::ofstream::trunc); //open and clear file if it already existed
+    for(Request request : generatedRequests) {
+        outfileGraph << request.to_string_export() << std::endl;
+    }
+    outfileGraph.close();
+    //Export parameters to file
+    std::ofstream outfileParams(exportFolderPath.string() + "requestParameters.txt", std::ofstream::out | std::ofstream::trunc); //open and clear file if it already existed
+    outfileParams << generationParameters;
+    outfileParams.close();
+    return generatedRequests;
 }
-- 
GitLab


From 953704ca8cab6333222678f50d9efe3fc8695035 Mon Sep 17 00:00:00 2001
From: Romain BERNARD <romain.bernard@uca.fr>
Date: Wed, 12 Jun 2024 18:33:29 +0200
Subject: [PATCH 089/327] googletest update

---
 test/lib/googletest | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/test/lib/googletest b/test/lib/googletest
index 33af80a..a7f443b 160000
--- a/test/lib/googletest
+++ b/test/lib/googletest
@@ -1 +1 @@
-Subproject commit 33af80a883ddc33d9c0fac0a5b4578301efb18de
+Subproject commit a7f443b80b105f940225332ed3c31f2790092f47
-- 
GitLab


From b496f5328c06f0955bc764d8e94b1744ffb40675 Mon Sep 17 00:00:00 2001
From: Romain BERNARD <romain.bernard@uca.fr>
Date: Thu, 13 Jun 2024 14:51:07 +0200
Subject: [PATCH 090/327] instance generators refactor

---
 CMakeLists.txt                                | 55 ++++++++++++++++++-
 .../Graph/GraphGenerator.h                    | 22 ++++++++
 .../Graph/OSRMGraphGenerator.h                | 17 ++++++
 .../Requests}/RequestGenerationParameters.h   |  0
 .../Requests}/RequestsGenerator.cpp           |  0
 .../Requests}/RequestsGenerator.h             |  2 +-
 test/CMakeLists.txt                           |  7 ++-
 test/src/ConstraintPropagationDebug.cpp       |  2 +-
 8 files changed, 97 insertions(+), 8 deletions(-)
 create mode 100644 src/utils/Instance Generation/Graph/GraphGenerator.h
 create mode 100644 src/utils/Instance Generation/Graph/OSRMGraphGenerator.h
 rename src/utils/{ => Instance Generation/Requests}/RequestGenerationParameters.h (100%)
 rename src/utils/{ => Instance Generation/Requests}/RequestsGenerator.cpp (100%)
 rename src/utils/{ => Instance Generation/Requests}/RequestsGenerator.h (97%)

diff --git a/CMakeLists.txt b/CMakeLists.txt
index d886435..68b0161 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -58,9 +58,58 @@ add_executable(GreedyAlgorithm
         src/routes/vehicle/propagation/SAEVRouteChangelist.h
         src/routes/vehicle/propagation/SAEVRouteChange.cpp
         src/routes/vehicle/propagation/SAEVRouteChange.h
-        src/utils/RequestsGenerator.cpp
-        src/utils/RequestsGenerator.h
-        src/utils/RequestGenerationParameters.h
+        "src/utils/Instance Generation/Requests/RequestsGenerator.cpp"
+        "src/utils/Instance Generation/Requests/RequestsGenerator.h"
+        "src/utils/Instance Generation/Requests/RequestGenerationParameters.h"
+        "src/utils/Instance Generation/Graph/OSRMGraphGenerator.h"
+)
+
+add_executable(RequestGenerator
+        src/instance/graph/Node.cpp
+        src/instance/graph/Node.h
+        src/instance/graph/Edge.cpp
+        src/instance/graph/Edge.h
+        src/instance/graph/Graph.cpp
+        src/instance/graph/Graph.h
+        src/instance/requests/Request.cpp
+        src/instance/requests/Request.h
+        src/instance/Instance.cpp
+        src/instance/Instance.h
+        src/instance/graph/Line.cpp
+        src/instance/graph/Line.h
+        src/services/CSV/CSVRange.h
+        src/services/CSV/CSVIterator.h
+        src/instance/graph/LineStop.cpp
+        src/instance/graph/LineStop.h
+        src/services/DatFile/DATRow.h
+        src/routes/vehicle/SAEVRoute.cpp
+        src/routes/vehicle/SAEVRoute.h
+        src/TimeWindow.cpp
+        src/TimeWindow.h
+        "src/utils/Instance Generation/Requests/RequestsGenerator.cpp"
+        "src/utils/Instance Generation/Requests/RequestsGenerator.h"
+        "src/utils/Instance Generation/Requests/RequestGenerationParameters.h"
+        "src/utils/Instance Generation/Graph/OSRMGraphGenerator.h"
+)
+
+add_executable(GraphGeneration
+        src/instance/graph/Node.cpp
+        src/instance/graph/Node.h
+        src/instance/graph/Edge.cpp
+        src/instance/graph/Edge.h
+        src/instance/graph/Graph.cpp
+        src/instance/graph/Graph.h
+        src/instance/Instance.cpp
+        src/instance/Instance.h
+        src/instance/graph/Line.cpp
+        src/instance/graph/Line.h
+        src/services/CSV/CSVRange.h
+        src/services/CSV/CSVIterator.h
+        src/instance/graph/LineStop.cpp
+        src/instance/graph/LineStop.h
+        src/services/DatFile/DATRow.h
+        "src/utils/Instance Generation/Graph/OSRMGraphGenerator.h"
+        "src/utils/Instance Generation/Graph/GraphGenerator.h"
 )
 
 target_include_directories(GreedyAlgorithm PRIVATE ${PYTHON_INCLUDE_DIRS})
diff --git a/src/utils/Instance Generation/Graph/GraphGenerator.h b/src/utils/Instance Generation/Graph/GraphGenerator.h
new file mode 100644
index 0000000..3f8785b
--- /dev/null
+++ b/src/utils/Instance Generation/Graph/GraphGenerator.h	
@@ -0,0 +1,22 @@
+//
+// Created by romain on 13/06/24.
+//
+
+#ifndef GREEDYALGORITHM_GRAPHGENERATOR_H
+#define GREEDYALGORITHM_GRAPHGENERATOR_H
+
+
+#include "../../../instance/graph/Graph.h"
+
+class GraphGenerator {
+    /**
+     * Overwrites the node vector in the given graph with data imported from the given file in a CSV-like format (status,x,y)
+     * @param baseGraph The graph in which to update node data
+     * @param nodeFile The file containing the required data. Format : (status,x,y)
+     */
+    static void importNodeFromCSV(Graph baseGraph, std::filesystem::path nodeFile);
+    static void importPTNetworkFromCSV(Graph baseGraph, std::filesystem::path ptNetworkFile);
+};
+
+
+#endif //GREEDYALGORITHM_GRAPHGENERATOR_H
diff --git a/src/utils/Instance Generation/Graph/OSRMGraphGenerator.h b/src/utils/Instance Generation/Graph/OSRMGraphGenerator.h
new file mode 100644
index 0000000..5e3bbf7
--- /dev/null
+++ b/src/utils/Instance Generation/Graph/OSRMGraphGenerator.h	
@@ -0,0 +1,17 @@
+//
+// Created by romain on 12/06/24.
+//
+
+#ifndef GREEDYALGORITHM_OSRMGRAPHGENERATOR_H
+#define GREEDYALGORITHM_OSRMGRAPHGENERATOR_H
+
+
+#include "../../../instance/graph/Graph.h"
+
+class OSRMGraphGenerator {
+    static void initOSRMEngine();
+    static Graph createMatrixFromOSRM(Graph graph);
+};
+
+
+#endif //GREEDYALGORITHM_OSRMGRAPHGENERATOR_H
diff --git a/src/utils/RequestGenerationParameters.h b/src/utils/Instance Generation/Requests/RequestGenerationParameters.h
similarity index 100%
rename from src/utils/RequestGenerationParameters.h
rename to src/utils/Instance Generation/Requests/RequestGenerationParameters.h
diff --git a/src/utils/RequestsGenerator.cpp b/src/utils/Instance Generation/Requests/RequestsGenerator.cpp
similarity index 100%
rename from src/utils/RequestsGenerator.cpp
rename to src/utils/Instance Generation/Requests/RequestsGenerator.cpp
diff --git a/src/utils/RequestsGenerator.h b/src/utils/Instance Generation/Requests/RequestsGenerator.h
similarity index 97%
rename from src/utils/RequestsGenerator.h
rename to src/utils/Instance Generation/Requests/RequestsGenerator.h
index 2c39d7e..50ad4f3 100644
--- a/src/utils/RequestsGenerator.h
+++ b/src/utils/Instance Generation/Requests/RequestsGenerator.h	
@@ -8,7 +8,7 @@
 
 #include <vector>
 #include <filesystem>
-#include "../instance/requests/Request.h"
+#include "../../../instance/requests/Request.h"
 #include "RequestGenerationParameters.h"
 
 namespace fs = std::filesystem;
diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt
index 831009b..ed48629 100644
--- a/test/CMakeLists.txt
+++ b/test/CMakeLists.txt
@@ -66,9 +66,10 @@ add_executable(Constraint_Propag_DEB
         ../src/routes/RequestKeyPoint.h
         ../src/routes/RequestRoute.cpp
         ../src/routes/RequestRoute.h
-        ../src/utils/RequestsGenerator.cpp
-        ../src/utils/RequestsGenerator.h
-        ../src/utils/RequestGenerationParameters.h
+        "../src/utils/Instance Generation/Requests/RequestsGenerator.cpp"
+        "../src/utils/Instance Generation/Requests/RequestsGenerator.h"
+        "../src/utils/Instance Generation/Requests/RequestGenerationParameters.h"
+        "../src/utils/Instance Generation/Graph/OSRMGraphGenerator.h"
 )
 
 target_link_libraries(Line_UT gtest gtest_main)
diff --git a/test/src/ConstraintPropagationDebug.cpp b/test/src/ConstraintPropagationDebug.cpp
index e2b2e7d..a072a46 100644
--- a/test/src/ConstraintPropagationDebug.cpp
+++ b/test/src/ConstraintPropagationDebug.cpp
@@ -8,7 +8,7 @@
 #include "../../src/ShortestPath/Transit/TransitShortestPathPrecompute.h"
 #include "../../src/instance/Instance.h"
 #include "../../src/routes/vehicle/SAEVRoute.h"
-#include "../../src/utils/RequestsGenerator.h"
+#include "../../src/utils/Instance Generation/Requests/RequestsGenerator.h"
 
 TEST(ConstraintPropagationDebug, DebugBaseInstance) {
     std::string instancesPath = "../../resources/test/instances/Constraint Propagation/";
-- 
GitLab


From 998ebc2a415a7ef1a1c3a59d21d1cfb22bcf3734 Mon Sep 17 00:00:00 2001
From: Romain BERNARD <romain.bernard@uca.fr>
Date: Thu, 13 Jun 2024 16:42:09 +0200
Subject: [PATCH 091/327] properly set TW when applying/reverting changes

---
 src/routes/vehicle/propagation/SAEVRouteChange.cpp | 8 ++++----
 1 file changed, 4 insertions(+), 4 deletions(-)

diff --git a/src/routes/vehicle/propagation/SAEVRouteChange.cpp b/src/routes/vehicle/propagation/SAEVRouteChange.cpp
index d7fabb3..63894fd 100644
--- a/src/routes/vehicle/propagation/SAEVRouteChange.cpp
+++ b/src/routes/vehicle/propagation/SAEVRouteChange.cpp
@@ -6,16 +6,16 @@
 
 void SAEVRouteChange::applyChange() {
     if(_bound == Min) {
-        _kpPointer->getMinTw() + _value;
+        _kpPointer->setMinTw(_kpPointer->getMinTw() + _value);
     } else {
-        _kpPointer->getMaxTw() - _value;
+        _kpPointer->setMaxTw(_kpPointer->getMaxTw() - _value);
     }
 }
 
 void SAEVRouteChange::revertChange() {
     if(_bound == Min) {
-        _kpPointer->getMinTw() - _value;
+        _kpPointer->setMinTw(_kpPointer->getMinTw() - _value);
     } else {
-        _kpPointer->getMaxTw() + _value;
+        _kpPointer->setMaxTw(_kpPointer->getMaxTw() + _value);
     }
 }
-- 
GitLab


From fb5bae4a8d87029189bb95e1f9b7859516287173 Mon Sep 17 00:00:00 2001
From: Romain BERNARD <romain.bernard@uca.fr>
Date: Thu, 13 Jun 2024 16:57:55 +0200
Subject: [PATCH 092/327] properly check weight until the request leaves the
 vehicle

---
 src/routes/vehicle/SAEVRoute.cpp | 3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)

diff --git a/src/routes/vehicle/SAEVRoute.cpp b/src/routes/vehicle/SAEVRoute.cpp
index 0ad775e..32a0476 100644
--- a/src/routes/vehicle/SAEVRoute.cpp
+++ b/src/routes/vehicle/SAEVRoute.cpp
@@ -100,6 +100,7 @@ SAEVRoute::tryAddRequest(const size_t requestId, const size_t originRequestPrede
     const Request* request = &_requestList->at(requestId);
     SAEVKeyPoint const* originPredecessor = &_route.at(originRequestPredecessorIdx);
     SAEVKeyPoint const* destinationPredecessor = &_route.at(destinationRequestPredecessorIdx);
+    SAEVKeyPoint const* destinationSuccessor = destinationPredecessor->getSuccessor();
 
     //Check vehicle capacity
     SAEVKeyPoint const* currentKP = originPredecessor;
@@ -109,7 +110,7 @@ SAEVRoute::tryAddRequest(const size_t requestId, const size_t originRequestPrede
             return SAEVRouteChangelist(this, requestId, originRequestPredecessorIdx, destinationRequestPredecessorIdx);
         }
         currentKP = currentKP->getSuccessor();
-    } while (currentKP != destinationPredecessor && currentKP != nullptr);
+    } while (currentKP != destinationSuccessor && currentKP != nullptr);
 
     //Do basic checks on neighbouring nodes from our Origin/Destination insertion points
     bool isValid = doNeighbouringTWChecks(requestId, request->getOriginNodeIndex(), request->getDestinationNodeIndex(), originPredecessor, destinationPredecessor);
-- 
GitLab


From 9ec82ecd0f129a093e8b4baee1ca8ed2490f32b1 Mon Sep 17 00:00:00 2001
From: Romain BERNARD <romain.bernard@uca.fr>
Date: Thu, 13 Jun 2024 18:16:56 +0200
Subject: [PATCH 093/327] set weight values for key points after insertion and
 reset after removal

---
 src/routes/vehicle/SAEVRoute.cpp | 16 ++++++++++++++++
 src/routes/vehicle/SAEVRoute.h   |  9 +++++++++
 2 files changed, 25 insertions(+)

diff --git a/src/routes/vehicle/SAEVRoute.cpp b/src/routes/vehicle/SAEVRoute.cpp
index 32a0476..a335dc9 100644
--- a/src/routes/vehicle/SAEVRoute.cpp
+++ b/src/routes/vehicle/SAEVRoute.cpp
@@ -93,6 +93,8 @@ void SAEVRoute::removeRequest(int requestId) {
     originKp.setMaxTw(_requestList->at(requestId).getMaxDepartureTw());
     destinationKp.setMinTw(_requestList->at(requestId).getMinArrivalTw());
     destinationKp.setMaxTw(_requestList->at(requestId).getMaxArrivalTw());
+    originKp.setCurrentOccupation(0);
+    destinationKp.setCurrentOccupation(0);
 }
 
 SAEVRouteChangelist
@@ -349,3 +351,17 @@ bool SAEVRoute::checkRouteTimeWindows(size_t vehicleId) {
     return true;
 }
 
+void SAEVRoute::finalizeRequestInsertion(const size_t requestId) {
+    SAEVKeyPoint * currentKeyPoint = &_route.at(getRequestOriginIdx(requestId));
+    SAEVKeyPoint const * counterpartKP = currentKeyPoint->getCounterpart();
+    int requestWeight = counterpartKP->getRequest()->getWeight();
+    //Init weight value for Origin KP
+    currentKeyPoint->setCurrentOccupation(currentKeyPoint->getPredecessor()->getCurrentOccupation() + requestWeight);
+    //Iterate over KPs in-between Origin and Destination
+    currentKeyPoint = currentKeyPoint->getSuccessor();
+    while(currentKeyPoint != counterpartKP) {
+        currentKeyPoint->setCurrentOccupation(currentKeyPoint->getCurrentOccupation() + requestWeight);
+        currentKeyPoint = currentKeyPoint->getSuccessor();
+    }
+}
+
diff --git a/src/routes/vehicle/SAEVRoute.h b/src/routes/vehicle/SAEVRoute.h
index 1dfed77..e3ee0a7 100644
--- a/src/routes/vehicle/SAEVRoute.h
+++ b/src/routes/vehicle/SAEVRoute.h
@@ -56,6 +56,15 @@ public:
      */
     SAEVRouteChangelist tryAddRequest(const size_t requestId, const size_t originRequestPredecessorIdx, const size_t destinationRequestPredecessorIdx);
 
+    /**
+     * Call this function whenever a request insertion is considered final (Insertion success + satisfied with result)
+     * Currently only updates Key Point weights, but other post insertion processes will go here
+     * Processe(s) :
+     * 1) Update weights between the request's origin and destination in the vehicle's key points
+     * @param requestId ID of the request that was inserted
+     */
+    void finalizeRequestInsertion(const size_t requestId);
+
     /**
      * Verifies time window constraints on our request's origin/destination's projected neighbour, aka originPredecessor/destinationPredecessor and their successor.
      * There is a special case taken into account if originPredecessor and destinationPredecessor are the same KeyPoint, since then, Origin's successor would be Destination
-- 
GitLab


From 6a63577ba8a81638499dca1063c8297bd6dde9a4 Mon Sep 17 00:00:00 2001
From: Romain BERNARD <romain.bernard@uca.fr>
Date: Fri, 14 Jun 2024 18:15:29 +0200
Subject: [PATCH 094/327] add new debug instance

---
 .../Instance_Alain_140624/graph.dat           | 30 +++++++++++++++++++
 .../Instance_Alain_140624/requests.dat        |  9 ++++++
 test/src/ConstraintPropagationDebug.cpp       | 25 +++++++++++++++-
 3 files changed, 63 insertions(+), 1 deletion(-)
 create mode 100644 resources/test/instances/Constraint Propagation/Instance_Alain_140624/graph.dat
 create mode 100644 resources/test/instances/Constraint Propagation/Instance_Alain_140624/requests.dat

diff --git a/resources/test/instances/Constraint Propagation/Instance_Alain_140624/graph.dat b/resources/test/instances/Constraint Propagation/Instance_Alain_140624/graph.dat
new file mode 100644
index 0000000..3e3c961
--- /dev/null
+++ b/resources/test/instances/Constraint Propagation/Instance_Alain_140624/graph.dat	
@@ -0,0 +1,30 @@
+#Params (seed)
+123456789
+#Nodes format : status (work, leisure, residential),x,y
+,0,0
+,1,1
+,1,2
+,2,2
+,2,3
+,3,3
+,3,4
+,4,4
+,4,5
+,5,5
+,5,6
+,6,6
+,6,7
+#Matrix
+0,4,60,60,60,60,60,1,60,60,60,60,60
+60,0,15,3,60,60,60,60,60,60,60,60,60
+60,60,0,60,60,60,7,60,60,60,60,60,60
+60,60,60,0,5,5,60,60,60,60,60,60,60
+60,60,6,60,0,5,60,60,60,60,60,60,60
+60,60,60,60,2,0,16,60,60,60,60,60,60
+2,60,60,60,60,60,0,16,60,60,60,60,60
+60,60,60,60,60,60,60,0,10,3,60,60,60
+60,60,60,60,60,60,60,60,0,60,60,5,60
+60,60,60,60,60,60,60,60,6,0,18,60,60
+3,60,60,60,60,60,60,60,60,60,0,60,60
+60,60,60,60,60,60,60,60,60,60,60,0,4
+60,60,60,60,60,60,60,60,60,60,2,60,0
diff --git a/resources/test/instances/Constraint Propagation/Instance_Alain_140624/requests.dat b/resources/test/instances/Constraint Propagation/Instance_Alain_140624/requests.dat
new file mode 100644
index 0000000..cf14961
--- /dev/null
+++ b/resources/test/instances/Constraint Propagation/Instance_Alain_140624/requests.dat	
@@ -0,0 +1,9 @@
+#Global Params (delta ratio)
+1
+#Requests (origin_idx,destination_idx,min,max,delta baseline,capacity)
+1,2,19,22,16,1
+3,4,14,17,8,1
+5,6,19,21,18,1
+7,8,13,17,13,1
+9,10,24,29,22,1
+11,12,20,22,6,1
\ No newline at end of file
diff --git a/test/src/ConstraintPropagationDebug.cpp b/test/src/ConstraintPropagationDebug.cpp
index a072a46..5416444 100644
--- a/test/src/ConstraintPropagationDebug.cpp
+++ b/test/src/ConstraintPropagationDebug.cpp
@@ -47,7 +47,6 @@ TEST(ConstraintPropagationDebug, DebugRequestGeneration) {
     std::string instancesPath = "../../resources/test/instances/Constraint Propagation/";
     std::string instanceFolder = "basic_debug_instance/";
     std::string graphDatFile = "graph.dat";
-    std::string requestsDatFile = "requests.dat";
 
     //Parse graph
     Graph graphFromSingleFile(instancesPath + instanceFolder + graphDatFile);
@@ -62,6 +61,30 @@ TEST(ConstraintPropagationDebug, DebugRequestGeneration) {
     //Init instance
     Instance instance(requests,graphFromSingleFile,4);
     SAEVRoute routesContainer(graphFromSingleFile, requests);
+TEST(ConstraintPropagationDebug, DebugInstanceAlain) {
+    std::string instancesPath = "../../resources/test/instances/Constraint Propagation/";
+    std::string instanceFolder = "Instance_Alain_140624/";
+    std::string graphDatFile = "graph.dat";
+    std::string requestsDatFile = "requests.dat";
+
+    //Parse graph
+    Graph graphFromSingleFile(instancesPath + instanceFolder + graphDatFile);
+    std::vector<Request> requests = Request::getRequestsFromFile(instancesPath + instanceFolder + requestsDatFile, graphFromSingleFile);
+
+    //Init instance
+    Instance instance(requests,graphFromSingleFile,4);
+    SAEVRoute routesContainer(graphFromSingleFile, requests);
+
+    //Vehicle 1 insertions
+    routesContainer.tryAddRequest(0,routesContainer.getOriginDepotIdx(0),routesContainer.getOriginDepotIdx(0));
+    routesContainer.tryAddRequest(1,routesContainer.getRequestOriginIdx(0),routesContainer.getRequestOriginIdx(0));
+    routesContainer.tryAddRequest(2,routesContainer.getRequestOriginIdx(1),routesContainer.getRequestDestinationIdx(0));
+
+    //Vehicle 2 insertions
+    routesContainer.tryAddRequest(5,routesContainer.getOriginDepotIdx(1),routesContainer.getOriginDepotIdx(1));
+    routesContainer.tryAddRequest(4,routesContainer.getOriginDepotIdx(1),routesContainer.getRequestDestinationIdx(5));
+    routesContainer.tryAddRequest(3,routesContainer.getOriginDepotIdx(1),routesContainer.getRequestOriginIdx(4));
+}
 
 }
 
-- 
GitLab


From d959cacce12415efd1e792899c3cb45dbd0cbc65 Mon Sep 17 00:00:00 2001
From: Romain BERNARD <romain.bernard@uca.fr>
Date: Fri, 14 Jun 2024 18:19:46 +0200
Subject: [PATCH 095/327] use the appropriate delta time to fix departure tw

---
 src/instance/requests/Request.cpp | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/src/instance/requests/Request.cpp b/src/instance/requests/Request.cpp
index 2b71256..00ea969 100644
--- a/src/instance/requests/Request.cpp
+++ b/src/instance/requests/Request.cpp
@@ -35,7 +35,7 @@ Request::Request(const DATRow& currentRow, const Graph& graph) {
     std::from_chars(currentRow[4].data(), currentRow[4].data() + currentRow[4].size(), _deltaTime);
     std::from_chars(currentRow[5].data(), currentRow[5].data() + currentRow[5].size(), _weight);
 
-    _departureTW.min = _arrivalTW.min - _currentDeltaTime;
+    _departureTW.min = _arrivalTW.min - _deltaTime;
     _departureTW.max = _arrivalTW.max - graph.getShortestSAEVPath(_originNodeIndex, _destinationNodeIndex);
 }
 
@@ -54,7 +54,7 @@ Request::Request(const DATRow& currentRow, double deltaRatio, const Graph& graph
 
     std::from_chars(currentRow[5].data(), currentRow[5].data() + currentRow[5].size(), _weight);
 
-    _departureTW.min = _arrivalTW.min - _currentDeltaTime;
+    _departureTW.min = _arrivalTW.min - _deltaTime;
     _departureTW.max = _arrivalTW.max - graph.getShortestSAEVPath(_originNodeIndex, _destinationNodeIndex);
 }
 
-- 
GitLab


From caeaede786394ea72166443c66bf2e83bb029191 Mon Sep 17 00:00:00 2001
From: Romain BERNARD <romain.bernard@uca.fr>
Date: Fri, 14 Jun 2024 18:25:29 +0200
Subject: [PATCH 096/327] add TW violation messages

---
 src/routes/vehicle/SAEVRoute.cpp | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/src/routes/vehicle/SAEVRoute.cpp b/src/routes/vehicle/SAEVRoute.cpp
index a335dc9..6cddf74 100644
--- a/src/routes/vehicle/SAEVRoute.cpp
+++ b/src/routes/vehicle/SAEVRoute.cpp
@@ -209,6 +209,7 @@ SAEVRouteChangelist SAEVRoute::insertRequestWithPropagation(const size_t request
                 newValue = keyPoint->getMinTw() + _graph->getShortestSAEVPath(keyPoint->getNodeIndex(), successorKP->getNodeIndex());
                 if (oldValue < newValue) {
                     if (newValue > successorKP->getMaxTw()) {
+                        DEBUG_MSG("\tMIN TW VIOLATION");
                         return changelist;
                     }
                     DEBUG_MSG("\tMIN Successeur KP=" + successorKP->to_string() + "\n\tModif Min=" + std::to_string(oldValue) + "->" + std::to_string(newValue));
@@ -242,6 +243,7 @@ SAEVRouteChangelist SAEVRoute::insertRequestWithPropagation(const size_t request
                 newValue = keyPoint->getMaxTw() - _graph->getShortestSAEVPath(predecessorKP->getNodeIndex(), keyPoint->getNodeIndex());
                 if(oldValue > newValue) {
                     if (predecessorKP->getMinTw() > newValue) {
+                        DEBUG_MSG("\tMAX TW VIOLATION");
                         return changelist;
                     }
                     DEBUG_MSG("\tMAX Predecessor KP=" + predecessorKP->to_string() + "\n\tModif Max=" + std::to_string(oldValue) + "->" + std::to_string(newValue));
-- 
GitLab


From 306f50d3c994b44a6a54c00c31d1615a83522c64 Mon Sep 17 00:00:00 2001
From: Romain BERNARD <romain.bernard@uca.fr>
Date: Fri, 14 Jun 2024 18:32:18 +0200
Subject: [PATCH 097/327] gt the appropriate depot index

---
 src/routes/vehicle/SAEVRoute.h | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/src/routes/vehicle/SAEVRoute.h b/src/routes/vehicle/SAEVRoute.h
index e3ee0a7..04a4fc2 100644
--- a/src/routes/vehicle/SAEVRoute.h
+++ b/src/routes/vehicle/SAEVRoute.h
@@ -111,8 +111,8 @@ public:
     [[nodiscard]] size_t getRequestOriginIdx(const size_t requestId) const { return requestId * 2;}
     [[nodiscard]] size_t getRequestDestinationIdx(const size_t requestId) const { return requestId * 2 + 1;}
 
-    [[nodiscard]] size_t getOriginDepotIdx(const size_t vehicleId) const { return _nbRequest + vehicleId*2;}
-    [[nodiscard]] size_t getDestinationDepotIdx(const size_t vehicleId) const { return _nbRequest + vehicleId*2 + 1;}
+    [[nodiscard]] size_t getOriginDepotIdx(const size_t vehicleId) const { return _nbRequest*2 + vehicleId*2;}
+    [[nodiscard]] size_t getDestinationDepotIdx(const size_t vehicleId) const { return _nbRequest*2 + vehicleId*2 + 1;}
 
     /**
      * Verifies that time windows have been properly propagated for a given vehicle's route
-- 
GitLab


From 8df2a0f6c798346717658dd5e3cc0101e96d10cc Mon Sep 17 00:00:00 2001
From: Romain BERNARD <romain.bernard@uca.fr>
Date: Tue, 18 Jun 2024 10:32:11 +0200
Subject: [PATCH 098/327] fix precondition test i=j

---
 src/routes/vehicle/SAEVRoute.cpp | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/src/routes/vehicle/SAEVRoute.cpp b/src/routes/vehicle/SAEVRoute.cpp
index 6cddf74..49c75bf 100644
--- a/src/routes/vehicle/SAEVRoute.cpp
+++ b/src/routes/vehicle/SAEVRoute.cpp
@@ -162,7 +162,7 @@ SAEVRoute::doNeighbouringTWChecks(const size_t requestId, const size_t originNod
             return false;
         else if(predMinTWToDest + _graph->getShortestSAEVPath(destinationNodeIndex, originSuccessor->getNodeIndex()) > originSuccessor->getMaxTw()) //Path from pred to successor
             return false;
-        else if(originSuccessor->getMinTw() + _graph->getShortestSAEVPath(destinationNodeIndex, originSuccessor->getNodeIndex()) > originSuccessor->getMaxTw()) //Path from D to successor
+        else if(destinationKP.getMinTw() + _graph->getShortestSAEVPath(destinationNodeIndex, originSuccessor->getNodeIndex()) > originSuccessor->getMaxTw()) //Path from D to successor
             return false;
         else if(originKP.getMinTw() + _graph->getShortestSAEVPath(originNodeIndex, destinationNodeIndex) //Path from O to successor
         + _graph->getShortestSAEVPath(destinationNodeIndex, originSuccessor->getNodeIndex()) > originSuccessor->getMaxTw())
-- 
GitLab


From b45875d762a74ab77e1ad6667e89657f2bf7b4f0 Mon Sep 17 00:00:00 2001
From: Romain BERNARD <romain.bernard@uca.fr>
Date: Tue, 18 Jun 2024 10:32:34 +0200
Subject: [PATCH 099/327] Fix instance test Alain

---
 .../Instance_Alain_140624/graph.dat                |  4 ++--
 .../Instance_Alain_140624/requests.dat             | 14 +++++++-------
 2 files changed, 9 insertions(+), 9 deletions(-)

diff --git a/resources/test/instances/Constraint Propagation/Instance_Alain_140624/graph.dat b/resources/test/instances/Constraint Propagation/Instance_Alain_140624/graph.dat
index 3e3c961..9f90059 100644
--- a/resources/test/instances/Constraint Propagation/Instance_Alain_140624/graph.dat	
+++ b/resources/test/instances/Constraint Propagation/Instance_Alain_140624/graph.dat	
@@ -15,7 +15,7 @@
 ,6,6
 ,6,7
 #Matrix
-0,4,60,60,60,60,60,1,60,60,60,60,60
+0,4,60,60,60,60,60,1,60,5,60,10,60
 60,0,15,3,60,60,60,60,60,60,60,60,60
 60,60,0,60,60,60,7,60,60,60,60,60,60
 60,60,60,0,5,5,60,60,60,60,60,60,60
@@ -24,7 +24,7 @@
 2,60,60,60,60,60,0,16,60,60,60,60,60
 60,60,60,60,60,60,60,0,10,3,60,60,60
 60,60,60,60,60,60,60,60,0,60,60,5,60
-60,60,60,60,60,60,60,60,6,0,18,60,60
+60,60,60,60,60,60,60,60,6,0,18,10,60
 3,60,60,60,60,60,60,60,60,60,0,60,60
 60,60,60,60,60,60,60,60,60,60,60,0,4
 60,60,60,60,60,60,60,60,60,60,2,60,0
diff --git a/resources/test/instances/Constraint Propagation/Instance_Alain_140624/requests.dat b/resources/test/instances/Constraint Propagation/Instance_Alain_140624/requests.dat
index cf14961..d4e1219 100644
--- a/resources/test/instances/Constraint Propagation/Instance_Alain_140624/requests.dat	
+++ b/resources/test/instances/Constraint Propagation/Instance_Alain_140624/requests.dat	
@@ -1,9 +1,9 @@
 #Global Params (delta ratio)
 1
-#Requests (origin_idx,destination_idx,min,max,delta baseline,capacity)
-1,2,19,22,16,1
-3,4,14,17,8,1
-5,6,19,21,18,1
-7,8,13,17,13,1
-9,10,24,29,22,1
-11,12,20,22,6,1
\ No newline at end of file
+#Requests (origin_idx,destination_idx,min_tw_start,max_tw_start,min_tw_end,max_tw_end,delta baseline,capacity)
+1,2,3,6,,,16,1
+3,4,6,9,,,8,1
+5,6,11,13,,,18,1
+7,8,0,4,,,13,1
+9,10,2,7,,,22,1
+11,12,14,16,,,6,1
\ No newline at end of file
-- 
GitLab


From a8403e4cbe92757e98f39c7cc363e812fd4d476b Mon Sep 17 00:00:00 2001
From: Romain BERNARD <romain.bernard@uca.fr>
Date: Tue, 18 Jun 2024 18:45:13 +0200
Subject: [PATCH 100/327] fix getOrigin/DestinationDepot wrong index

---
 src/routes/vehicle/SAEVRoute.h | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/src/routes/vehicle/SAEVRoute.h b/src/routes/vehicle/SAEVRoute.h
index 04a4fc2..a7f7a51 100644
--- a/src/routes/vehicle/SAEVRoute.h
+++ b/src/routes/vehicle/SAEVRoute.h
@@ -105,8 +105,8 @@ public:
     SAEVKeyPoint& getOrigin(const size_t requestId) { return _route.at(requestId * 2);}
     SAEVKeyPoint& getDestination(const size_t requestId) { return _route.at(requestId * 2 + 1);}
 
-    SAEVKeyPoint& getOriginDepot(const size_t vehicleId) { return _route.at(_nbRequest + vehicleId*2);}
-    SAEVKeyPoint& getDestinationDepot(const size_t vehicleId) { return _route.at(_nbRequest + vehicleId*2 + 1);}
+    SAEVKeyPoint& getOriginDepot(const size_t vehicleId) { return _route.at(_nbRequest*2 + vehicleId*2);}
+    SAEVKeyPoint& getDestinationDepot(const size_t vehicleId) { return _route.at(_nbRequest*2 + vehicleId*2 + 1);}
 
     [[nodiscard]] size_t getRequestOriginIdx(const size_t requestId) const { return requestId * 2;}
     [[nodiscard]] size_t getRequestDestinationIdx(const size_t requestId) const { return requestId * 2 + 1;}
-- 
GitLab


From ac9a67d02abc848568ea4b3fce3339624f70f35d Mon Sep 17 00:00:00 2001
From: Romain BERNARD <romain.bernard@uca.fr>
Date: Tue, 18 Jun 2024 18:49:44 +0200
Subject: [PATCH 101/327] [IMPORT BREAKING CHANGE] allow setting min TW in
 imports

---
 src/instance/requests/Request.cpp   | 48 +++++++++++++++--------------
 src/routes/vehicle/SAEVKeyPoint.cpp |  5 ++-
 2 files changed, 27 insertions(+), 26 deletions(-)

diff --git a/src/instance/requests/Request.cpp b/src/instance/requests/Request.cpp
index 00ea969..6de343d 100644
--- a/src/instance/requests/Request.cpp
+++ b/src/instance/requests/Request.cpp
@@ -28,34 +28,36 @@ Request::Request(const DATRow& currentRow, const Graph& graph) {
     std::from_chars(currentRow[1].data(), currentRow[1].data() + currentRow[1].size(), _destinationNodeIndex);
 
     int twMin, twMax;
-    std::from_chars(currentRow[2].data(), currentRow[2].data() + currentRow[2].size(), twMin);
-    std::from_chars(currentRow[3].data(), currentRow[3].data() + currentRow[3].size(), twMax);
-    _arrivalTW = TimeWindow(twMin, twMax);
+    bool setDepartureTW{false};
+    bool setArrivalTW{false};
+    if(!currentRow[2].empty() && !currentRow[3].empty()) { //Departure TW
+        std::from_chars(currentRow[2].data(), currentRow[2].data() + currentRow[2].size(), twMin);
+        std::from_chars(currentRow[3].data(), currentRow[3].data() + currentRow[3].size(), twMax);
+        _departureTW = TimeWindow(twMin, twMax);
+        setDepartureTW = true;
+    }
+    if(!currentRow[4].empty() && !currentRow[5].empty()) { //Arrival TW
+        std::from_chars(currentRow[4].data(), currentRow[4].data() + currentRow[4].size(), twMin);
+        std::from_chars(currentRow[5].data(), currentRow[5].data() + currentRow[5].size(), twMax);
+        _arrivalTW = TimeWindow(twMin, twMax);
+        setArrivalTW = true;
+    }
 
-    std::from_chars(currentRow[4].data(), currentRow[4].data() + currentRow[4].size(), _deltaTime);
-    std::from_chars(currentRow[5].data(), currentRow[5].data() + currentRow[5].size(), _weight);
+    std::from_chars(currentRow[6].data(), currentRow[6].data() + currentRow[6].size(), _deltaTime);
+    std::from_chars(currentRow[7].data(), currentRow[7].data() + currentRow[7].size(), _weight);
 
-    _departureTW.min = _arrivalTW.min - _deltaTime;
-    _departureTW.max = _arrivalTW.max - graph.getShortestSAEVPath(_originNodeIndex, _destinationNodeIndex);
+    if(!setDepartureTW) {
+        _departureTW.min = _arrivalTW.min - _deltaTime;
+        _departureTW.max = _arrivalTW.max - graph.getShortestSAEVPath(_originNodeIndex, _destinationNodeIndex);
+    }
+    if(!setArrivalTW) {
+        _arrivalTW.min = _departureTW.min + graph.getShortestSAEVPath(_originNodeIndex, _destinationNodeIndex);
+        _arrivalTW.max = _departureTW.max + _deltaTime;
+    }
 }
 
-Request::Request(const DATRow& currentRow, double deltaRatio, const Graph& graph) {
-    std::from_chars(currentRow[0].data(), currentRow[0].data() + currentRow[0].size(), _originNodeIndex);
-    std::from_chars(currentRow[1].data(), currentRow[1].data() + currentRow[1].size(), _destinationNodeIndex);
-
-    int twMin, twMax;
-    std::from_chars(currentRow[2].data(), currentRow[2].data() + currentRow[2].size(), twMin);
-    std::from_chars(currentRow[3].data(), currentRow[3].data() + currentRow[3].size(), twMax);
-    _arrivalTW = TimeWindow(twMin, twMax);
-
-    //Assign value (direct time to
-    std::from_chars(currentRow[4].data(), currentRow[4].data() + currentRow[4].size(), _deltaTime);
+Request::Request(const DATRow& currentRow, double deltaRatio, const Graph& graph) : Request(currentRow, graph){
     _deltaTime = floor(_deltaTime * deltaRatio);
-
-    std::from_chars(currentRow[5].data(), currentRow[5].data() + currentRow[5].size(), _weight);
-
-    _departureTW.min = _arrivalTW.min - _deltaTime;
-    _departureTW.max = _arrivalTW.max - graph.getShortestSAEVPath(_originNodeIndex, _destinationNodeIndex);
 }
 
 std::vector<Request> Request::getRequestsFromFile(const std::string& datFilePath, const Graph& graph) {
diff --git a/src/routes/vehicle/SAEVKeyPoint.cpp b/src/routes/vehicle/SAEVKeyPoint.cpp
index aea9863..15511b8 100644
--- a/src/routes/vehicle/SAEVKeyPoint.cpp
+++ b/src/routes/vehicle/SAEVKeyPoint.cpp
@@ -51,9 +51,8 @@ void SAEVKeyPoint::setMaxTw(int maxTw) {
 SAEVKeyPoint::SAEVKeyPoint(const Graph &graph, const Request &request, bool isOrigin) : _isOrigin(isOrigin), _requestPointer(&request) {
     if(isOrigin) {
         setNodeIndex(request.getOriginNodeIndex());
-        _minTW = request.getArrivalTw().min - request.getDeltaTime();
-        _maxTW = request.getArrivalTw().max - graph.getShortestSAEVPath(request.getOriginNodeIndex(),
-                                                                        request.getDestinationNodeIndex());
+        _minTW = request.getDepartureTw().min;
+        _maxTW = request.getDepartureTw().max;
     } else {
         setNodeIndex(request.getDestinationNodeIndex());
         _minTW = request.getArrivalTw().min;
-- 
GitLab


From 65508bca026f6e25e3de3ca663852930ea9b42df Mon Sep 17 00:00:00 2001
From: Romain BERNARD <romain.bernard@uca.fr>
Date: Tue, 18 Jun 2024 18:50:50 +0200
Subject: [PATCH 102/327] fix test (error during commit ?)

---
 test/src/ConstraintPropagationDebug.cpp | 3 +++
 1 file changed, 3 insertions(+)

diff --git a/test/src/ConstraintPropagationDebug.cpp b/test/src/ConstraintPropagationDebug.cpp
index 5416444..1c159f5 100644
--- a/test/src/ConstraintPropagationDebug.cpp
+++ b/test/src/ConstraintPropagationDebug.cpp
@@ -61,6 +61,9 @@ TEST(ConstraintPropagationDebug, DebugRequestGeneration) {
     //Init instance
     Instance instance(requests,graphFromSingleFile,4);
     SAEVRoute routesContainer(graphFromSingleFile, requests);
+}
+
+
 TEST(ConstraintPropagationDebug, DebugInstanceAlain) {
     std::string instancesPath = "../../resources/test/instances/Constraint Propagation/";
     std::string instanceFolder = "Instance_Alain_140624/";
-- 
GitLab


From d13eb869eb68923a744aef276088f4d78412bb52 Mon Sep 17 00:00:00 2001
From: Romain BERNARD <romain.bernard@uca.fr>
Date: Tue, 18 Jun 2024 18:51:42 +0200
Subject: [PATCH 103/327] WIP init PT Line generation parameters object

---
 CMakeLists.txt                                     |  1 +
 .../Graph/PTLineGenerationParameters.h             | 14 ++++++++++++++
 2 files changed, 15 insertions(+)
 create mode 100644 src/utils/Instance Generation/Graph/PTLineGenerationParameters.h

diff --git a/CMakeLists.txt b/CMakeLists.txt
index 68b0161..5c5a090 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -110,6 +110,7 @@ add_executable(GraphGeneration
         src/services/DatFile/DATRow.h
         "src/utils/Instance Generation/Graph/OSRMGraphGenerator.h"
         "src/utils/Instance Generation/Graph/GraphGenerator.h"
+        "src/utils/Instance Generation/Graph/PTLineGenerationParameters.h"
 )
 
 target_include_directories(GreedyAlgorithm PRIVATE ${PYTHON_INCLUDE_DIRS})
diff --git a/src/utils/Instance Generation/Graph/PTLineGenerationParameters.h b/src/utils/Instance Generation/Graph/PTLineGenerationParameters.h
new file mode 100644
index 0000000..05a1970
--- /dev/null
+++ b/src/utils/Instance Generation/Graph/PTLineGenerationParameters.h	
@@ -0,0 +1,14 @@
+//
+// Created by romain on 18/06/24.
+//
+
+#ifndef GREEDYALGORITHM_PTLINEGENERATIONPARAMETERS_H
+#define GREEDYALGORITHM_PTLINEGENERATIONPARAMETERS_H
+
+
+class PTLineGenerationParameters {
+
+};
+
+
+#endif //GREEDYALGORITHM_PTLINEGENERATIONPARAMETERS_H
-- 
GitLab


From 1a82381452509cfaf0ea268a02b3ae9524fc9aac Mon Sep 17 00:00:00 2001
From: Romain BERNARD <romain.bernard@uca.fr>
Date: Tue, 18 Jun 2024 18:52:48 +0200
Subject: [PATCH 104/327] WIP define core functions to generate graphs

---
 src/utils/Instance Generation/Graph/GraphGenerator.h | 7 +++++++
 1 file changed, 7 insertions(+)

diff --git a/src/utils/Instance Generation/Graph/GraphGenerator.h b/src/utils/Instance Generation/Graph/GraphGenerator.h
index 3f8785b..9e8fc97 100644
--- a/src/utils/Instance Generation/Graph/GraphGenerator.h	
+++ b/src/utils/Instance Generation/Graph/GraphGenerator.h	
@@ -7,6 +7,7 @@
 
 
 #include "../../../instance/graph/Graph.h"
+#include "PTLineGenerationParameters.h"
 
 class GraphGenerator {
     /**
@@ -15,7 +16,13 @@ class GraphGenerator {
      * @param nodeFile The file containing the required data. Format : (status,x,y)
      */
     static void importNodeFromCSV(Graph baseGraph, std::filesystem::path nodeFile);
+    static void generateNodes(Graph baseGraph, uint maxX, uint maxY, uint nbNodes) {
+
+    }
+    static void importDistanceMatrixFromCSV(Graph baseGraph, std::filesystem::path nodeFile);
+    static void generateDistanceMatrix(Graph baseGraph, std::filesystem::path nodeFile);
     static void importPTNetworkFromCSV(Graph baseGraph, std::filesystem::path ptNetworkFile);
+    static void generatePTNetwork(Graph baseGraph, PTLineGenerationParameters parameters);
 };
 
 
-- 
GitLab


From 73f13600aeb05af50ec6d29c66d3b33066c73042 Mon Sep 17 00:00:00 2001
From: Romain BERNARD <romain.bernard@uca.fr>
Date: Tue, 18 Jun 2024 18:54:51 +0200
Subject: [PATCH 105/327] fix constraint propagation, missing min/max
 propagation on the Origin and Destination themselves

---
 CMakeLists.txt                   | 2 ++
 src/routes/vehicle/SAEVRoute.cpp | 4 ++++
 2 files changed, 6 insertions(+)

diff --git a/CMakeLists.txt b/CMakeLists.txt
index 5c5a090..60080e1 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -62,6 +62,8 @@ add_executable(GreedyAlgorithm
         "src/utils/Instance Generation/Requests/RequestsGenerator.h"
         "src/utils/Instance Generation/Requests/RequestGenerationParameters.h"
         "src/utils/Instance Generation/Graph/OSRMGraphGenerator.h"
+        src/routes/vehicle/BestRequestInsertion.h
+        src/routes/vehicle/BestInsertionQueue.h
 )
 
 add_executable(RequestGenerator
diff --git a/src/routes/vehicle/SAEVRoute.cpp b/src/routes/vehicle/SAEVRoute.cpp
index 49c75bf..2554dcc 100644
--- a/src/routes/vehicle/SAEVRoute.cpp
+++ b/src/routes/vehicle/SAEVRoute.cpp
@@ -183,6 +183,10 @@ SAEVRouteChangelist SAEVRoute::insertRequestWithPropagation(const size_t request
     std::queue<std::pair<Bound, SAEVKeyPoint *>> boundPropagationQueue{};
     SAEVKeyPoint * originKP = &getOrigin(requestId);
     SAEVKeyPoint * destinationKP = &getDestination(requestId);
+    boundPropagationQueue.emplace(Min, originKP->getPredecessor());
+    boundPropagationQueue.emplace(Max, originKP->getSuccessor());
+    boundPropagationQueue.emplace(Min, destinationKP->getPredecessor());
+    boundPropagationQueue.emplace(Max, destinationKP->getSuccessor());
     boundPropagationQueue.emplace(Min, originKP);
     boundPropagationQueue.emplace(Max, originKP);
     boundPropagationQueue.emplace(Min, destinationKP);
-- 
GitLab


From c1265aa37067425c6377ccacfb2b48033faaf519 Mon Sep 17 00:00:00 2001
From: Romain BERNARD <romain.bernard@uca.fr>
Date: Tue, 18 Jun 2024 19:02:10 +0200
Subject: [PATCH 106/327] WIP DEBUG add best request insertion queue to order
 possible insertions depending on score (TODO : debug detour score, use
 KeyPoints or appropriate indexes)

---
 src/routes/vehicle/BestInsertionQueue.h   | 36 ++++++++++
 src/routes/vehicle/BestRequestInsertion.h | 65 ++++++++++++++++++
 src/routes/vehicle/SAEVRoute.cpp          | 35 ++++++++++
 src/routes/vehicle/SAEVRoute.h            |  4 ++
 test/CMakeLists.txt                       | 35 +++++++++-
 test/src/BestInsertionHeuristicDebug.cpp  | 83 +++++++++++++++++++++++
 6 files changed, 257 insertions(+), 1 deletion(-)
 create mode 100644 src/routes/vehicle/BestInsertionQueue.h
 create mode 100644 src/routes/vehicle/BestRequestInsertion.h
 create mode 100644 test/src/BestInsertionHeuristicDebug.cpp

diff --git a/src/routes/vehicle/BestInsertionQueue.h b/src/routes/vehicle/BestInsertionQueue.h
new file mode 100644
index 0000000..fa08426
--- /dev/null
+++ b/src/routes/vehicle/BestInsertionQueue.h
@@ -0,0 +1,36 @@
+//
+// Created by romain on 18/06/24.
+//
+
+#ifndef GREEDYALGORITHM_BESTINSERTIONQUEUE_H
+#define GREEDYALGORITHM_BESTINSERTIONQUEUE_H
+
+
+#include <queue>
+#include "BestRequestInsertion.h"
+
+class BestInsertionQueue : public std::priority_queue<BestRequestInsertion, std::vector<BestRequestInsertion>> {
+private:
+    size_t _requestId{std::numeric_limits<size_t>::max()};
+    size_t _vehicleId{std::numeric_limits<size_t>::max()};
+
+public:
+    BestInsertionQueue(size_t requestId, size_t vehicleId) : _requestId(requestId), _vehicleId(vehicleId) {}
+
+    BestInsertionQueue(size_t requestId, size_t vehicleId, size_t nbRequests) : BestInsertionQueue(requestId, vehicleId) {
+        c.reserve(nbRequests^2);
+    }
+
+    /**
+     * Returns and removes the top value from the priority queue
+     * @return The top value in the priority queue
+     */
+    BestRequestInsertion topAndPop() {
+        BestRequestInsertion top = this->top();
+        this->pop();
+        return top;
+    }
+};
+
+
+#endif //GREEDYALGORITHM_BESTINSERTIONQUEUE_H
diff --git a/src/routes/vehicle/BestRequestInsertion.h b/src/routes/vehicle/BestRequestInsertion.h
new file mode 100644
index 0000000..798b9cc
--- /dev/null
+++ b/src/routes/vehicle/BestRequestInsertion.h
@@ -0,0 +1,65 @@
+//
+// Created by romain on 18/06/24.
+//
+
+#ifndef GREEDYALGORITHM_BESTREQUESTINSERTION_H
+#define GREEDYALGORITHM_BESTREQUESTINSERTION_H
+
+
+#include <cstddef>
+#include <compare>
+#include <cstdint>
+#include <limits>
+
+class BestRequestInsertion {
+private:
+    size_t _originInsertionIndex{std::numeric_limits<size_t>::max()};
+    size_t _destinationInsertionIndex{std::numeric_limits<size_t>::max()};
+    double _score{ std::numeric_limits<double>::max() };
+
+public:
+    /**
+     * Default constructor to allow pre-sizing containers
+     */
+    BestRequestInsertion() {};
+    /**
+     * Constructs a BestRequestInsertion object, containing Origin/Destination insertion indexes and the score associated
+     * @param originInsertionIndex Index of insertion for the origin of the request in the route
+     * @param destinationInsertionIndex Index of insertion for the destination of the request in the route
+     * @param score
+     */
+    BestRequestInsertion(size_t originInsertionIndex, size_t destinationInsertionIndex, double score)
+            : _originInsertionIndex(originInsertionIndex), _destinationInsertionIndex(destinationInsertionIndex),
+              _score(score) {};
+
+    [[nodiscard]] size_t getOriginInsertionIndex() const {
+        return _originInsertionIndex;
+    }
+
+    void setOriginInsertionIndex(size_t originInsertionIndex) {
+        BestRequestInsertion::_originInsertionIndex = originInsertionIndex;
+    }
+
+    [[nodiscard]] size_t getDestinationInsertionIndex() const {
+        return _destinationInsertionIndex;
+    }
+
+    void setDestinationInsertionIndex(size_t destinationInsertionIndex) {
+        BestRequestInsertion::_destinationInsertionIndex = destinationInsertionIndex;
+    }
+
+    [[nodiscard]] double getScore() const {
+        return _score;
+    }
+
+    void setScore(double score) {
+        BestRequestInsertion::_score = score;
+    }
+
+    std::partial_ordering operator<=>(const BestRequestInsertion &rhs) const {
+        return _score <=> rhs._score;
+    }
+};
+
+
+#endif //GREEDYALGORITHM_BESTREQUESTINSERTION_H
diff --git a/src/routes/vehicle/SAEVRoute.cpp b/src/routes/vehicle/SAEVRoute.cpp
index 2554dcc..6e815a0 100644
--- a/src/routes/vehicle/SAEVRoute.cpp
+++ b/src/routes/vehicle/SAEVRoute.cpp
@@ -5,6 +5,7 @@
 #include <queue>
 #include <iostream>
 #include "SAEVRoute.h"
+#include "BestInsertionQueue.h"
 
 #ifdef DEBUG_TRANSIT_PRECOMPUTE
 #include <iostream>
@@ -371,3 +372,37 @@ void SAEVRoute::finalizeRequestInsertion(const size_t requestId) {
     }
 }
 
+/**
+ * Initializes a BestInsertionQueue to guide the best insertion heuristic
+ * @param requestId
+ * @param vehicleId
+ * @return
+ */
+BestInsertionQueue SAEVRoute::getBestInsertionsQueue(size_t requestId, size_t vehicleId) {
+    BestInsertionQueue bestInsertionQueue(requestId, vehicleId, _nbRequest^2);
+
+    //Init variables used during iteration
+    double score;
+    size_t originNodeIndex;
+    size_t destinationNodeIndex;
+    SAEVKeyPoint const* originKeyPoint = &getOriginDepot(vehicleId);
+    SAEVKeyPoint const* destinationKeyPoint = originKeyPoint;
+
+    //iterate over possible origin/destination pairs for the given vehicle
+    while(originKeyPoint->getSuccessor() != nullptr) {
+        originNodeIndex = originKeyPoint->getNodeIndex();
+        while(destinationKeyPoint->getSuccessor() != nullptr) {
+            destinationNodeIndex = destinationKeyPoint->getNodeIndex();
+            score = getDetourScore(requestId, originNodeIndex, destinationNodeIndex);
+            bestInsertionQueue.emplace(originNodeIndex, destinationNodeIndex,score);
+            destinationKeyPoint = destinationKeyPoint->getSuccessor();
+        }
+
+        //Iterate over possible origins and reset destination to being the same point as the origin
+        originKeyPoint = originKeyPoint->getSuccessor();
+        destinationKeyPoint = originKeyPoint;
+    }
+
+    return bestInsertionQueue;
+}
+
diff --git a/src/routes/vehicle/SAEVRoute.h b/src/routes/vehicle/SAEVRoute.h
index a7f7a51..89714e9 100644
--- a/src/routes/vehicle/SAEVRoute.h
+++ b/src/routes/vehicle/SAEVRoute.h
@@ -8,6 +8,8 @@
 
 #include <vector>
 #include "SAEVKeyPoint.h"
+#include "BestRequestInsertion.h"
+#include "BestInsertionQueue.h"
 
 class SAEVRouteChangelist;
 class SAEVRoute {
@@ -102,6 +104,8 @@ public:
      */
     double getDetourScore(const size_t requestId, const size_t originRequestPredecessorIdx, const size_t destinationRequestPredecessorIdx);
 
+    BestInsertionQueue getBestInsertionsQueue(size_t requestId, size_t vehicleId);
+
     SAEVKeyPoint& getOrigin(const size_t requestId) { return _route.at(requestId * 2);}
     SAEVKeyPoint& getDestination(const size_t requestId) { return _route.at(requestId * 2 + 1);}
 
diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt
index ed48629..bb085d9 100644
--- a/test/CMakeLists.txt
+++ b/test/CMakeLists.txt
@@ -72,6 +72,39 @@ add_executable(Constraint_Propag_DEB
         "../src/utils/Instance Generation/Graph/OSRMGraphGenerator.h"
 )
 
+add_executable(BestInsertionHeuristic_DEB
+        src/BestInsertionHeuristicDebug.cpp
+        ../src/TimeWindow.cpp
+        ../src/TimeWindow.h
+        ../src/instance/graph/Node.cpp
+        ../src/instance/graph/Node.h
+        ../src/instance/graph/Edge.cpp
+        ../src/instance/graph/Edge.h
+        ../src/instance/graph/Graph.cpp
+        ../src/instance/graph/Graph.h
+        ../src/instance/graph/Line.cpp
+        ../src/instance/graph/Line.h
+        ../src/instance/requests/Request.cpp
+        ../src/instance/requests/Request.h
+        ../src/routes/vehicle/SAEVRoute.cpp
+        ../src/routes/vehicle/SAEVRoute.h
+        ../src/routes/vehicle/propagation/SAEVRouteChange.cpp
+        ../src/routes/vehicle/propagation/SAEVRouteChange.h
+        ../src/routes/vehicle/propagation/SAEVRouteChangelist.cpp
+        ../src/routes/vehicle/propagation/SAEVRouteChangelist.h
+        ../src/routes/vehicle/SAEVKeyPoint.cpp
+        ../src/routes/vehicle/SAEVKeyPoint.h
+        ../src/routes/KeyPoint.cpp
+        ../src/routes/KeyPoint.h
+        ../src/routes/RequestKeyPoint.cpp
+        ../src/routes/RequestKeyPoint.h
+        ../src/routes/RequestRoute.cpp
+        ../src/routes/RequestRoute.h
+        ../src/routes/vehicle/BestRequestInsertion.h
+        ../src/routes/vehicle/BestInsertionQueue.h
+)
+
 target_link_libraries(Line_UT gtest gtest_main)
 target_link_libraries(Transit_Preprocess_DEB gtest gtest_main)
-target_link_libraries(Constraint_Propag_DEB gtest gtest_main)
\ No newline at end of file
+target_link_libraries(Constraint_Propag_DEB gtest gtest_main)
+target_link_libraries(BestInsertionHeuristic_DEB gtest gtest_main)
\ No newline at end of file
diff --git a/test/src/BestInsertionHeuristicDebug.cpp b/test/src/BestInsertionHeuristicDebug.cpp
new file mode 100644
index 0000000..9d000e2
--- /dev/null
+++ b/test/src/BestInsertionHeuristicDebug.cpp
@@ -0,0 +1,83 @@
+//
+// Created by romain on 20/03/24.
+//
+
+#include "../lib/googletest/googletest/include/gtest/gtest.h"
+#include "../../src/instance/graph/Graph.h"
+#include "../../src/ShortestPath/Transit/TransitShortestPathContainer.h"
+#include "../../src/ShortestPath/Transit/TransitShortestPathPrecompute.h"
+#include "../../src/instance/Instance.h"
+#include "../../src/routes/vehicle/SAEVRoute.h"
+
+TEST(BestInsertionHeuristicDebug, DebugBaseInstance) {
+    std::string instancesPath = "../../resources/test/instances/Constraint Propagation/";
+    std::string instanceFolder = "basic_debug_instance/";
+    std::string graphDatFile = "graph.dat";
+    std::string requestsDatFile = "requests.dat";
+
+    //Parse graph
+    Graph graphFromSingleFile(instancesPath + instanceFolder + graphDatFile);
+    std::vector<Request> requests = Request::getRequestsFromFile(instancesPath + instanceFolder + requestsDatFile, graphFromSingleFile);
+
+    //Init instance
+    Instance instance(requests,graphFromSingleFile,4);
+    SAEVRoute routesContainer(graphFromSingleFile, requests);
+
+    std::cout << "------------------Fin parsing instance et route-------------------" << std::endl << std::endl;
+    int vehicleId = 1;
+    assert(routesContainer.checkRouteTimeWindows(vehicleId));
+    SAEVRouteChangelist req0Changelist = routesContainer.tryAddRequest(0, routesContainer.getOriginDepotIdx(vehicleId), routesContainer.getOriginDepotIdx(1));
+    std::cout << routesContainer.to_string(vehicleId) << std::endl;
+    assert(routesContainer.checkRouteTimeWindows(vehicleId));
+    std::cout << "------------------------------------------------------------------" << std::endl;
+    SAEVRouteChangelist req1Changelist = routesContainer.tryAddRequest(1, routesContainer.getOriginDepotIdx(vehicleId), routesContainer.getRequestDestinationIdx(0));
+    std::cout << routesContainer.to_string(vehicleId) << std::endl << std::endl;
+    assert(!routesContainer.checkRouteTimeWindows(vehicleId));
+    std::cout << "------------------------------------------------------------------" << std::endl;
+
+    //Test changelist revert/apply
+    req1Changelist.revertChanges();
+    req1Changelist.applyChanges();
+    req1Changelist.revertChanges();
+    req0Changelist.revertChanges();
+}
+
+TEST(BestInsertionHeuristicDebug, DebugInstanceAlain) {
+    std::string instancesPath = "../../resources/test/instances/Constraint Propagation/";
+    std::string instanceFolder = "Instance_Alain_140624/";
+    std::string graphDatFile = "graph2.dat";
+    std::string requestsDatFile = "requests.dat";
+
+    //Parse graph
+    Graph graphFromSingleFile(instancesPath + instanceFolder + graphDatFile);
+    std::vector<Request> requests = Request::getRequestsFromFile(instancesPath + instanceFolder + requestsDatFile, graphFromSingleFile);
+
+    //Init instance
+    Instance instance(requests,graphFromSingleFile,4);
+    SAEVRoute routesContainer(graphFromSingleFile, requests);
+
+    //Vehicle 1 insertions
+    BestInsertionQueue biQueue = routesContainer.getBestInsertionsQueue(0,0);
+    routesContainer.tryAddRequest(0,routesContainer.getOriginDepotIdx(0),routesContainer.getOriginDepotIdx(0));
+    biQueue = routesContainer.getBestInsertionsQueue(1,0);
+    routesContainer.tryAddRequest(1,routesContainer.getRequestOriginIdx(0),routesContainer.getRequestOriginIdx(0));
+    biQueue = routesContainer.getBestInsertionsQueue(2,0);
+    SAEVRouteChangelist cl = routesContainer.tryAddRequest(2,routesContainer.getRequestOriginIdx(1),routesContainer.getRequestDestinationIdx(1));
+    biQueue = routesContainer.getBestInsertionsQueue(3,0);
+
+    //Vehicle 2 insertions
+    biQueue = routesContainer.getBestInsertionsQueue(5,1);
+    routesContainer.tryAddRequest(5,routesContainer.getOriginDepotIdx(1),routesContainer.getOriginDepotIdx(1));
+    biQueue = routesContainer.getBestInsertionsQueue(4,1);
+    routesContainer.tryAddRequest(4,routesContainer.getOriginDepotIdx(1),routesContainer.getRequestDestinationIdx(5));
+    biQueue = routesContainer.getBestInsertionsQueue(3,1);
+    routesContainer.tryAddRequest(3,routesContainer.getOriginDepotIdx(1),routesContainer.getRequestOriginIdx(4));
+    biQueue = routesContainer.getBestInsertionsQueue(0,1);
+    biQueue = routesContainer.getBestInsertionsQueue(1,1);
+    biQueue = routesContainer.getBestInsertionsQueue(2,1);
+}
+
+int main(int argc, char* argv[]) {
+    testing::InitGoogleTest(&argc, argv);
+    return RUN_ALL_TESTS();
+}
\ No newline at end of file
-- 
GitLab


From 1e28e573c2263f78184cb12d054f7c3177b31f60 Mon Sep 17 00:00:00 2001
From: Romain BERNARD <romain.bernard@uca.fr>
Date: Tue, 18 Jun 2024 19:04:23 +0200
Subject: [PATCH 107/327] add insertion status enum to make debugging easier

---
 src/routes/vehicle/propagation/SAEVRouteChangelist.h | 10 ++++++++++
 1 file changed, 10 insertions(+)

diff --git a/src/routes/vehicle/propagation/SAEVRouteChangelist.h b/src/routes/vehicle/propagation/SAEVRouteChangelist.h
index 790c534..6db14fb 100644
--- a/src/routes/vehicle/propagation/SAEVRouteChangelist.h
+++ b/src/routes/vehicle/propagation/SAEVRouteChangelist.h
@@ -15,6 +15,16 @@
  * To allow comparison and ordering between multiple insertions if necessary, it also memorizes a score associated with this constraint propagation (lower is better)
  */
 class SAEVRouteChangelist {
+public:
+    enum class InsertionStatus{
+        SUCCESS,
+        FAILURE_PRECONDITION_TW,
+        FAILURE_PRECONDITION_WEIGHT,//To check if you need to remove a request, check status > FAILURE_PRECONDITION_WEIGHT
+        FAILURE_MIN,
+        FAILURE_MAX,
+        FAILURE_DELTA_MIN,
+        FAILURE_DELTA_MAX
+    };
 private:
     SAEVRoute * const _routePtr;
     const size_t _requestId;
-- 
GitLab


From 0377af8278206021772c1b17530848cce41dcf1e Mon Sep 17 00:00:00 2001
From: Romain BERNARD <romain.bernard@uca.fr>
Date: Wed, 19 Jun 2024 15:07:11 +0200
Subject: [PATCH 108/327] REFACTOR directly refer to insertion key points
 wherever possible to prevent any divergence in the kind of index expected by
 the function's implementation

---
 src/routes/vehicle/BestRequestInsertion.h     | 28 +++----
 src/routes/vehicle/SAEVRoute.cpp              | 81 +++++++++----------
 src/routes/vehicle/SAEVRoute.h                | 24 +++---
 .../propagation/SAEVRouteChangelist.cpp       | 10 +--
 .../vehicle/propagation/SAEVRouteChangelist.h | 25 +++---
 test/src/BestInsertionHeuristicDebug.cpp      | 16 ++--
 test/src/ConstraintPropagationDebug.cpp       | 18 ++---
 7 files changed, 95 insertions(+), 107 deletions(-)

diff --git a/src/routes/vehicle/BestRequestInsertion.h b/src/routes/vehicle/BestRequestInsertion.h
index 798b9cc..0a19ab7 100644
--- a/src/routes/vehicle/BestRequestInsertion.h
+++ b/src/routes/vehicle/BestRequestInsertion.h
@@ -13,8 +13,8 @@
 
 class BestRequestInsertion {
 private:
-    size_t _originInsertionIndex{std::numeric_limits<size_t>::max()};
-    size_t _destinationInsertionIndex{std::numeric_limits<size_t>::max()};
+    const SAEVKeyPoint* _originInsertionKP;
+    const SAEVKeyPoint* _destinationInsertionKP;
     double _score{ std::numeric_limits<double>::max() };
 
 public:
@@ -24,28 +24,28 @@ public:
     BestRequestInsertion() {};
     /**
      * Constructs a BestRequestInsertion object, containing Origin/Destination insertion indexes and the score associated
-     * @param originInsertionIndex Index of insertion for the origin of the request in the route
-     * @param destinationInsertionIndex Index of insertion for the destination of the request in the route
+     * @param originInsertionKP Index of insertion for the origin of the request in the route
+     * @param destinationInsertionKP Index of insertion for the destination of the request in the route
      * @param score
      */
-    BestRequestInsertion(size_t originInsertionIndex, size_t destinationInsertionIndex, double score)
-            : _originInsertionIndex(originInsertionIndex), _destinationInsertionIndex(destinationInsertionIndex),
+    BestRequestInsertion(const SAEVKeyPoint *originInsertionKP, const SAEVKeyPoint *destinationInsertionKP, double score)
+            : _originInsertionKP(originInsertionKP), _destinationInsertionKP(destinationInsertionKP),
               _score(score) {};
 
-    [[nodiscard]] size_t getOriginInsertionIndex() const {
-        return _originInsertionIndex;
+    [[nodiscard]] const SAEVKeyPoint *getOriginInsertionKp() const {
+        return _originInsertionKP;
     }
 
-    void setOriginInsertionIndex(size_t originInsertionIndex) {
-        BestRequestInsertion::_originInsertionIndex = originInsertionIndex;
+    void setOriginInsertionKp(SAEVKeyPoint *originInsertionKp) {
+        _originInsertionKP = originInsertionKp;
     }
 
-    [[nodiscard]] size_t getDestinationInsertionIndex() const {
-        return _destinationInsertionIndex;
+    [[nodiscard]] const SAEVKeyPoint *getDestinationInsertionKp() const {
+        return _destinationInsertionKP;
     }
 
-    void setDestinationInsertionIndex(size_t destinationInsertionIndex) {
-        BestRequestInsertion::_destinationInsertionIndex = destinationInsertionIndex;
+    void setDestinationInsertionKp(SAEVKeyPoint *destinationInsertionKp) {
+        _destinationInsertionKP = destinationInsertionKp;
     }
 
     [[nodiscard]] double getScore() const {
diff --git a/src/routes/vehicle/SAEVRoute.cpp b/src/routes/vehicle/SAEVRoute.cpp
index 6e815a0..dccb0a4 100644
--- a/src/routes/vehicle/SAEVRoute.cpp
+++ b/src/routes/vehicle/SAEVRoute.cpp
@@ -37,36 +37,34 @@ SAEVRoute::SAEVRoute(const Graph& graph, const std::vector<Request>& requestList
     }
 }
 
-void SAEVRoute::insertRequest(size_t requestId, size_t originRequestPredecessorIdx, size_t destinationRequestPredecessorIdx) {
+void SAEVRoute::insertRequest(size_t requestId, SAEVKeyPoint &originRequestPredecessorKP, SAEVKeyPoint &destinationRequestPredecessorKP) {
     SAEVKeyPoint& originKp = getOrigin(requestId);
     SAEVKeyPoint& destinationKp = getDestination(requestId);
 
-    SAEVKeyPoint& originPredKp = _route.at(originRequestPredecessorIdx);
-    SAEVKeyPoint *originSuccKp = originPredKp.getSuccessor();
-    SAEVKeyPoint& destinationPredKp = _route.at(destinationRequestPredecessorIdx);
-    SAEVKeyPoint *destinationSuccKp = destinationPredKp.getSuccessor();
+    SAEVKeyPoint *originSuccKp = originRequestPredecessorKP.getSuccessor();
+    SAEVKeyPoint *destinationSuccKp = destinationRequestPredecessorKP.getSuccessor();
 
-    if(originRequestPredecessorIdx != destinationRequestPredecessorIdx) {
+    if(originRequestPredecessorKP != destinationRequestPredecessorKP) {
         //Set values for O/D KPs
-        originKp.setPredecessor(&originPredKp);
+        originKp.setPredecessor(&originRequestPredecessorKP);
         originKp.setSuccessor(originSuccKp);
-        destinationKp.setPredecessor(&destinationPredKp);
+        destinationKp.setPredecessor(&destinationRequestPredecessorKP);
         destinationKp.setSuccessor(destinationSuccKp);
 
         //Set values for predecessors/successors
-        originPredKp.setSuccessor(&originKp);
+        originRequestPredecessorKP.setSuccessor(&originKp);
         originSuccKp->setPredecessor(&originKp);
-        destinationPredKp.setSuccessor(&destinationKp);
+        destinationRequestPredecessorKP.setSuccessor(&destinationKp);
         destinationSuccKp->setPredecessor(&destinationKp);
     } else {
         //Set values for O/D KPs
-        originKp.setPredecessor(&originPredKp);
+        originKp.setPredecessor(&originRequestPredecessorKP);
         originKp.setSuccessor(&destinationKp);
         destinationKp.setPredecessor(&originKp);
         destinationKp.setSuccessor(destinationSuccKp);
 
         //Set values for predecessors/successors
-        originPredKp.setSuccessor(&originKp);
+        originRequestPredecessorKP.setSuccessor(&originKp);
         originSuccKp->setPredecessor(&destinationKp);
     }
 }
@@ -99,30 +97,28 @@ void SAEVRoute::removeRequest(int requestId) {
 }
 
 SAEVRouteChangelist
-SAEVRoute::tryAddRequest(const size_t requestId, const size_t originRequestPredecessorIdx, const size_t destinationRequestPredecessorIdx) {
+SAEVRoute::tryAddRequest(const size_t requestId, SAEVKeyPoint &originRequestPredecessorKP, SAEVKeyPoint &destinationRequestPredecessorKP) {
     const Request* request = &_requestList->at(requestId);
-    SAEVKeyPoint const* originPredecessor = &_route.at(originRequestPredecessorIdx);
-    SAEVKeyPoint const* destinationPredecessor = &_route.at(destinationRequestPredecessorIdx);
-    SAEVKeyPoint const* destinationSuccessor = destinationPredecessor->getSuccessor();
+    SAEVKeyPoint const* destinationSuccessor = destinationRequestPredecessorKP.getSuccessor();
 
     //Check vehicle capacity
-    SAEVKeyPoint const* currentKP = originPredecessor;
+    SAEVKeyPoint const* currentKP = &originRequestPredecessorKP;
     do {
         if(currentKP->getCurrentOccupation() + request->getWeight() > SAEVehicle::getCapacity()) {
             DEBUG_MSG("WEIGHT VIOLATION : request weight = " + std::to_string(request->getWeight()) + " incompatible KP = " + currentKP->to_string());
-            return SAEVRouteChangelist(this, requestId, originRequestPredecessorIdx, destinationRequestPredecessorIdx);
+            return SAEVRouteChangelist(this, requestId, originRequestPredecessorKP, destinationRequestPredecessorKP);
         }
         currentKP = currentKP->getSuccessor();
     } while (currentKP != destinationSuccessor && currentKP != nullptr);
 
     //Do basic checks on neighbouring nodes from our Origin/Destination insertion points
-    bool isValid = doNeighbouringTWChecks(requestId, request->getOriginNodeIndex(), request->getDestinationNodeIndex(), originPredecessor, destinationPredecessor);
+    bool isValid = doNeighbouringTWChecks(requestId, request->getOriginNodeIndex(), request->getDestinationNodeIndex(), &originRequestPredecessorKP, &destinationRequestPredecessorKP);
 
     if(isValid) {
-        return insertRequestWithPropagation(requestId, originRequestPredecessorIdx, destinationRequestPredecessorIdx);
+        return insertRequestWithPropagation(requestId, originRequestPredecessorKP, destinationRequestPredecessorKP);
     } else {
         DEBUG_MSG("TW VIOLATION on neighbour KPs");
-        return SAEVRouteChangelist(this, requestId, originRequestPredecessorIdx, destinationRequestPredecessorIdx);
+        return SAEVRouteChangelist(this, requestId, originRequestPredecessorKP, destinationRequestPredecessorKP);
     }
 }
 
@@ -173,12 +169,12 @@ SAEVRoute::doNeighbouringTWChecks(const size_t requestId, const size_t originNod
     return true;
 }
 
-SAEVRouteChangelist SAEVRoute::insertRequestWithPropagation(const size_t requestId, const size_t originRequestPredecessorIdx,
-                                                            const size_t destinationRequestPredecessorIdx) {
+SAEVRouteChangelist SAEVRoute::insertRequestWithPropagation(const size_t requestId, SAEVKeyPoint &originRequestPredecessorKP,
+                                                            SAEVKeyPoint &destinationRequestPredecessorKP) {
     //Init changelist
-    SAEVRouteChangelist changelist{this, requestId, originRequestPredecessorIdx, destinationRequestPredecessorIdx};
+    SAEVRouteChangelist changelist{this, requestId, originRequestPredecessorKP, destinationRequestPredecessorKP};
     //Properly insert the request to facilitate constraint propagation
-    insertRequest(requestId, originRequestPredecessorIdx, destinationRequestPredecessorIdx);
+    insertRequest(requestId, originRequestPredecessorKP, destinationRequestPredecessorKP);
 
     //Initialize bound propagation signal queue (each item signals a modification done on one of a KeyPoint
     std::queue<std::pair<Bound, SAEVKeyPoint *>> boundPropagationQueue{};
@@ -277,36 +273,35 @@ SAEVRouteChangelist SAEVRoute::insertRequestWithPropagation(const size_t request
         }
     }
 
-    changelist.setScore(getDetourScore(requestId, originRequestPredecessorIdx, destinationRequestPredecessorIdx));
+    changelist.setScore(getDetourScore(requestId, originRequestPredecessorKP, destinationRequestPredecessorKP));
     return changelist;
 }
 
-double SAEVRoute::getDetourScore(const size_t requestId, const size_t originRequestPredecessorIdx,
-                                 const size_t destinationRequestPredecessorIdx) {
+double SAEVRoute::getDetourScore(const size_t requestId, const SAEVKeyPoint &originRequestPredecessorKP,
+                                 const SAEVKeyPoint &destinationRequestPredecessorKP) {
     double score;
     const SAEVKeyPoint& originKP = getOrigin(requestId);
     const SAEVKeyPoint& destinationKP = getDestination(requestId);
-    const SAEVKeyPoint& originPredKP = _route.at(originRequestPredecessorIdx);
-    const SAEVKeyPoint* originSuccKP = originPredKP.getSuccessor();
+    const SAEVKeyPoint* originSuccKP = originRequestPredecessorKP.getSuccessor();
+    const SAEVKeyPoint* destinationSuccKP = destinationRequestPredecessorKP.getSuccessor();
 
-    if(originRequestPredecessorIdx != destinationRequestPredecessorIdx) {
-        const SAEVKeyPoint* destinationPredKP = destinationKP.getPredecessor();
-        const SAEVKeyPoint* destinationSuccKP = destinationKP.getSuccessor();
+    if(originRequestPredecessorKP != destinationRequestPredecessorKP) {
+        const SAEVKeyPoint* destinationPredKP = &destinationRequestPredecessorKP;
 
         //Origin Detour
-        score = _graph->getShortestSAEVPath(originPredKP.getNodeIndex(), originKP.getNodeIndex()) //T(Pred(O), D)
+        score = _graph->getShortestSAEVPath(originRequestPredecessorKP.getNodeIndex(), originKP.getNodeIndex()) //T(Pred(O), D)
                 + _graph->getShortestSAEVPath(originKP.getNodeIndex(), originSuccKP->getNodeIndex()) //T(O, Succ(D))
-                - _graph->getShortestSAEVPath(originPredKP.getNodeIndex(), originSuccKP->getNodeIndex()); //T(Pred(O), Succ(O))
+                - _graph->getShortestSAEVPath(originRequestPredecessorKP.getNodeIndex(), originSuccKP->getNodeIndex()); //T(Pred(O), Succ(O))
 
         //Destination Detour
         score += _graph->getShortestSAEVPath(destinationPredKP->getNodeIndex(), destinationKP.getNodeIndex()) //T(Pred(D), D))
                 + _graph->getShortestSAEVPath(destinationKP.getNodeIndex(), destinationSuccKP->getNodeIndex()) //T(D, Succ(D)))
                 - _graph->getShortestSAEVPath(destinationPredKP->getNodeIndex(), destinationSuccKP->getNodeIndex()); //T(Pred(D), Succ(D)))
     } else {
-        score = _graph->getShortestSAEVPath(originPredKP.getNodeIndex(), originKP.getNodeIndex()) //T(Pred(O), O)
+        score = _graph->getShortestSAEVPath(originRequestPredecessorKP.getNodeIndex(), originKP.getNodeIndex()) //T(Pred(O), O)
                 + _graph->getShortestSAEVPath(originKP.getNodeIndex(), destinationKP.getNodeIndex()) //T(O, D)
-                + _graph->getShortestSAEVPath(destinationKP.getNodeIndex(), originSuccKP->getNodeIndex()) //T(D, Succ(D))
-                - _graph->getShortestSAEVPath(originPredKP.getNodeIndex(), originSuccKP->getNodeIndex()); //T(Pred(O), Succ(D))
+                + _graph->getShortestSAEVPath(destinationKP.getNodeIndex(), destinationSuccKP->getNodeIndex()) //T(D, Succ(D))
+                - _graph->getShortestSAEVPath(originRequestPredecessorKP.getNodeIndex(), destinationSuccKP->getNodeIndex()); //T(Pred(O), Succ(D))
     }
     return score;
 }
@@ -359,7 +354,7 @@ bool SAEVRoute::checkRouteTimeWindows(size_t vehicleId) {
 }
 
 void SAEVRoute::finalizeRequestInsertion(const size_t requestId) {
-    SAEVKeyPoint * currentKeyPoint = &_route.at(getRequestOriginIdx(requestId));
+    SAEVKeyPoint * currentKeyPoint = &getOrigin(requestId);
     SAEVKeyPoint const * counterpartKP = currentKeyPoint->getCounterpart();
     int requestWeight = counterpartKP->getRequest()->getWeight();
     //Init weight value for Origin KP
@@ -383,18 +378,14 @@ BestInsertionQueue SAEVRoute::getBestInsertionsQueue(size_t requestId, size_t ve
 
     //Init variables used during iteration
     double score;
-    size_t originNodeIndex;
-    size_t destinationNodeIndex;
     SAEVKeyPoint const* originKeyPoint = &getOriginDepot(vehicleId);
     SAEVKeyPoint const* destinationKeyPoint = originKeyPoint;
 
     //iterate over possible origin/destination pairs for the given vehicle
     while(originKeyPoint->getSuccessor() != nullptr) {
-        originNodeIndex = originKeyPoint->getNodeIndex();
         while(destinationKeyPoint->getSuccessor() != nullptr) {
-            destinationNodeIndex = destinationKeyPoint->getNodeIndex();
-            score = getDetourScore(requestId, originNodeIndex, destinationNodeIndex);
-            bestInsertionQueue.emplace(originNodeIndex, destinationNodeIndex,score);
+            score = getDetourScore(requestId, *originKeyPoint, *destinationKeyPoint);
+            bestInsertionQueue.emplace(originKeyPoint, destinationKeyPoint, score);
             destinationKeyPoint = destinationKeyPoint->getSuccessor();
         }
 
diff --git a/src/routes/vehicle/SAEVRoute.h b/src/routes/vehicle/SAEVRoute.h
index 89714e9..d9ebee9 100644
--- a/src/routes/vehicle/SAEVRoute.h
+++ b/src/routes/vehicle/SAEVRoute.h
@@ -35,10 +35,10 @@ public:
     /**
      * Raw request route insertion method. Public for debug purposes, but should effectively never be called by an outside member
      * @param requestId index of the request we want to insert in the route
-     * @param originRequestPredecessorIdx Identifier/index in the route key point vector for the request origin or destination that will precede the origin of the request we want to insert
-     * @param destinationRequestPredecessorIdx Identifier/index in the route key point vector for the request origin or destination that will precede the destination of the request we want to insert
+     * @param originRequestPredecessorKP Identifier/index in the route key point vector for the request origin or destination that will precede the origin of the request we want to insert
+     * @param destinationRequestPredecessorKP Identifier/index in the route key point vector for the request origin or destination that will precede the destination of the request we want to insert
      */
-    void insertRequest(size_t requestId, size_t originRequestPredecessorIdx, size_t destinationRequestPredecessorIdx);
+    void insertRequest(size_t requestId, SAEVKeyPoint &originRequestPredecessorKP, SAEVKeyPoint &destinationRequestPredecessorKP);
 
     /**
      * Raw request removal method. Public for debug purposes, but should effectively never be called by an outside member
@@ -52,11 +52,11 @@ public:
      * Then we propagate our min/max bounds, iteratively rippling through every modification induced by min/max neighbour constraints or delta constraints. \n
      * ⚠️ In case of infeasibility, tryAdd automatically reverts changes and the change list will be effectively empty, but otherwise it's the caller's responsibility to revert changes if necessary
      * @param requestId Identifier/index in the instance's request vector for the request we wish to insert
-     * @param originRequestPredecessorIdx Identifier/index in the route key point vector for the request origin or destination that will precede our request's origin in the route
-     * @param destinationRequestPredecessorIdx Identifier/index in the route key point vector for the request origin or destination that will precede our request's destination in the route
+     * @param originRequestPredecessorKP Identifier/index in the route key point vector for the request origin or destination that will precede our request's origin in the route
+     * @param destinationRequestPredecessorKP Identifier/index in the route key point vector for the request origin or destination that will precede our request's destination in the route
      * @return A change list with every min/max bound change made during the tryAdd procedure and a score estimating insertion quality (lower is better)
      */
-    SAEVRouteChangelist tryAddRequest(const size_t requestId, const size_t originRequestPredecessorIdx, const size_t destinationRequestPredecessorIdx);
+    SAEVRouteChangelist tryAddRequest(const size_t requestId, SAEVKeyPoint &originRequestPredecessorKP, SAEVKeyPoint &destinationRequestPredecessorKP);
 
     /**
      * Call this function whenever a request insertion is considered final (Insertion success + satisfied with result)
@@ -88,21 +88,21 @@ public:
      * If the bounds become infeasible (min > max), then the propagation stops with a changelist with score= +Infinity and changes will be immediately reverted.
      * Otherwise, it's the responsibility of this method's callers to revert changes if wanted (or to defer this responsibility to its caller)
      * @param requestId Identifier/index in the instance's request vector for the request we wish to insert
-     * @param originRequestPredecessorIdx Identifier/index in the route key point vector for the request origin or destination that will precede our request's origin in the route
-     * @param destinationRequestPredecessorIdx Identifier/index in the route key point vector for the request origin or destination that will precede our request's destination in the route
+     * @param originRequestPredecessorKP Identifier/index in the route key point vector for the request origin or destination that will precede our request's origin in the route
+     * @param destinationRequestPredecessorKP Identifier/index in the route key point vector for the request origin or destination that will precede our request's destination in the route
      * @return A change list with every min/max bound change made during the insert procedure and a score estimating insertion quality (lower is better)
      */
-    SAEVRouteChangelist insertRequestWithPropagation(const size_t requestId, const size_t originRequestPredecessorIdx, const size_t destinationRequestPredecessorIdx);
+    SAEVRouteChangelist insertRequestWithPropagation(const size_t requestId, SAEVKeyPoint &originRequestPredecessorKP, SAEVKeyPoint &destinationRequestPredecessorKP);
 
     /**
      * Returns a score value equivalent to the detour implied by insertion of a request after the two given key point indexes.
      * The specific case of origin/destination being inserted one after another is taken into account
      * @param requestId Identifier/index in the instance's request vector for the request we wish to insert
-     * @param originRequestPredecessorIdx Identifier/index in the route key point vector for the request origin or destination that will precede our request's origin in the route
-     * @param destinationRequestPredecessorIdx Identifier/index in the route key point vector for the request origin or destination that will precede our request's destination in the route
+     * @param originRequestPredecessorKP Identifier/index in the route key point vector for the request origin or destination that will precede our request's origin in the route
+     * @param destinationRequestPredecessorKP Identifier/index in the route key point vector for the request origin or destination that will precede our request's destination in the route
      * @return
      */
-    double getDetourScore(const size_t requestId, const size_t originRequestPredecessorIdx, const size_t destinationRequestPredecessorIdx);
+    double getDetourScore(const size_t requestId, const SAEVKeyPoint &originRequestPredecessorKP, const SAEVKeyPoint &destinationRequestPredecessorKP);
 
     BestInsertionQueue getBestInsertionsQueue(size_t requestId, size_t vehicleId);
 
diff --git a/src/routes/vehicle/propagation/SAEVRouteChangelist.cpp b/src/routes/vehicle/propagation/SAEVRouteChangelist.cpp
index a2535b6..07ee842 100644
--- a/src/routes/vehicle/propagation/SAEVRouteChangelist.cpp
+++ b/src/routes/vehicle/propagation/SAEVRouteChangelist.cpp
@@ -21,7 +21,7 @@ void SAEVRouteChangelist::emplace_back(SAEVKeyPoint &kp, Bound bound, int value)
 }
 
 void SAEVRouteChangelist::applyChanges() const {
-    _routePtr->insertRequest(_requestId, _originPredecessorIdx, _destinationPredecessorIdx);
+    _routePtr->insertRequest(_requestId, _originPredecessorKP, _destinationPredecessorKP);
     for(SAEVRouteChange change : _changelist) {
         change.applyChange();
     }
@@ -40,12 +40,12 @@ size_t SAEVRouteChangelist::getRequestId() const {
     return _requestId;
 }
 
-int SAEVRouteChangelist::getOriginPredecessorIdx() const {
-    return _originPredecessorIdx;
+const SAEVKeyPoint &SAEVRouteChangelist::getOriginPredecessorKP() const {
+    return _originPredecessorKP;
 }
 
-int SAEVRouteChangelist::getDestinationPredecessorIdx() const {
-    return _destinationPredecessorIdx;
+const SAEVKeyPoint &SAEVRouteChangelist::getDestinationPredecessorKP() const {
+    return _destinationPredecessorKP;
 }
 
 double SAEVRouteChangelist::getScore() const {
diff --git a/src/routes/vehicle/propagation/SAEVRouteChangelist.h b/src/routes/vehicle/propagation/SAEVRouteChangelist.h
index 6db14fb..f15912a 100644
--- a/src/routes/vehicle/propagation/SAEVRouteChangelist.h
+++ b/src/routes/vehicle/propagation/SAEVRouteChangelist.h
@@ -28,8 +28,8 @@ public:
 private:
     SAEVRoute * const _routePtr;
     const size_t _requestId;
-    const size_t _originPredecessorIdx;
-    const size_t _destinationPredecessorIdx;
+    SAEVKeyPoint& _originPredecessorKP;
+    SAEVKeyPoint& _destinationPredecessorKP;
     std::vector<SAEVRouteChange> _changelist{};
     double _score{std::numeric_limits<double>::infinity()}; //Init score to infinity
 
@@ -38,11 +38,11 @@ public:
      * Initializes a change list to memorize every iterative modification made during constraint propagation
      * @param routePtr a pointer to the route the constraint propagation was applied on. revert/apply operations will be done on this route
      * @param requestId The index of the request in the global request list
-     * @param originPredecessorIdx The index of the request our origin will be inserted after
-     * @param destinationPredecessorIdx The index of the request our destination will be inserted after
+     * @param originPredecessorKP The index of the request our origin will be inserted after
+     * @param destinationPredecessorKP The index of the request our destination will be inserted after
      */
-    explicit SAEVRouteChangelist(SAEVRoute * const routePtr, const size_t requestId, const size_t originPredecessorIdx, const size_t destinationPredecessorIdx)
-    : _routePtr(routePtr), _requestId(requestId), _originPredecessorIdx(originPredecessorIdx), _destinationPredecessorIdx(destinationPredecessorIdx) {};
+    explicit SAEVRouteChangelist(SAEVRoute * const routePtr, const size_t requestId, SAEVKeyPoint &originPredecessorKP, SAEVKeyPoint &destinationPredecessorKP)
+    : _routePtr(routePtr), _requestId(requestId), _originPredecessorKP(originPredecessorKP), _destinationPredecessorKP(destinationPredecessorKP) {};
 
     /**
      * @return A pointer to the route this change list applies/reverts changes to
@@ -54,14 +54,11 @@ public:
      * @return The index of the request that we want to insert to a route
      */
     [[nodiscard]] size_t getRequestId() const;
-    /**
-     * @return The index of the request our origin will be inserted after
-     */
-    [[nodiscard]] size_t getOriginPredecessorIdx() const;
-    /**
-     * @return The index of the request our destination will be inserted after
-     */
-    [[nodiscard]] size_t getDestinationPredecessorIdx() const;
+
+    [[nodiscard]] const SAEVKeyPoint &getOriginPredecessorKP() const;
+
+    [[nodiscard]] const SAEVKeyPoint &getDestinationPredecessorKP() const;
+
     /**
      * @return A score value associated with this changelist. A lower score is better
      */
diff --git a/test/src/BestInsertionHeuristicDebug.cpp b/test/src/BestInsertionHeuristicDebug.cpp
index 9d000e2..4e20b2d 100644
--- a/test/src/BestInsertionHeuristicDebug.cpp
+++ b/test/src/BestInsertionHeuristicDebug.cpp
@@ -26,11 +26,11 @@ TEST(BestInsertionHeuristicDebug, DebugBaseInstance) {
     std::cout << "------------------Fin parsing instance et route-------------------" << std::endl << std::endl;
     int vehicleId = 1;
     assert(routesContainer.checkRouteTimeWindows(vehicleId));
-    SAEVRouteChangelist req0Changelist = routesContainer.tryAddRequest(0, routesContainer.getOriginDepotIdx(vehicleId), routesContainer.getOriginDepotIdx(1));
+    SAEVRouteChangelist req0Changelist = routesContainer.tryAddRequest(0, routesContainer.getOriginDepot(vehicleId), routesContainer.getOriginDepot(1));
     std::cout << routesContainer.to_string(vehicleId) << std::endl;
     assert(routesContainer.checkRouteTimeWindows(vehicleId));
     std::cout << "------------------------------------------------------------------" << std::endl;
-    SAEVRouteChangelist req1Changelist = routesContainer.tryAddRequest(1, routesContainer.getOriginDepotIdx(vehicleId), routesContainer.getRequestDestinationIdx(0));
+    SAEVRouteChangelist req1Changelist = routesContainer.tryAddRequest(1, routesContainer.getOriginDepot(vehicleId), routesContainer.getDestination(0));
     std::cout << routesContainer.to_string(vehicleId) << std::endl << std::endl;
     assert(!routesContainer.checkRouteTimeWindows(vehicleId));
     std::cout << "------------------------------------------------------------------" << std::endl;
@@ -58,20 +58,20 @@ TEST(BestInsertionHeuristicDebug, DebugInstanceAlain) {
 
     //Vehicle 1 insertions
     BestInsertionQueue biQueue = routesContainer.getBestInsertionsQueue(0,0);
-    routesContainer.tryAddRequest(0,routesContainer.getOriginDepotIdx(0),routesContainer.getOriginDepotIdx(0));
+    routesContainer.tryAddRequest(0,routesContainer.getOriginDepot(0),routesContainer.getOriginDepot(0));
     biQueue = routesContainer.getBestInsertionsQueue(1,0);
-    routesContainer.tryAddRequest(1,routesContainer.getRequestOriginIdx(0),routesContainer.getRequestOriginIdx(0));
+    routesContainer.tryAddRequest(1,routesContainer.getOrigin(0),routesContainer.getOrigin(0));
     biQueue = routesContainer.getBestInsertionsQueue(2,0);
-    SAEVRouteChangelist cl = routesContainer.tryAddRequest(2,routesContainer.getRequestOriginIdx(1),routesContainer.getRequestDestinationIdx(1));
+    SAEVRouteChangelist cl = routesContainer.tryAddRequest(2,routesContainer.getOrigin(1),routesContainer.getDestination(1));
     biQueue = routesContainer.getBestInsertionsQueue(3,0);
 
     //Vehicle 2 insertions
     biQueue = routesContainer.getBestInsertionsQueue(5,1);
-    routesContainer.tryAddRequest(5,routesContainer.getOriginDepotIdx(1),routesContainer.getOriginDepotIdx(1));
+    routesContainer.tryAddRequest(5,routesContainer.getOriginDepot(1),routesContainer.getOriginDepot(1));
     biQueue = routesContainer.getBestInsertionsQueue(4,1);
-    routesContainer.tryAddRequest(4,routesContainer.getOriginDepotIdx(1),routesContainer.getRequestDestinationIdx(5));
+    routesContainer.tryAddRequest(4,routesContainer.getOriginDepot(1),routesContainer.getDestination(5));
     biQueue = routesContainer.getBestInsertionsQueue(3,1);
-    routesContainer.tryAddRequest(3,routesContainer.getOriginDepotIdx(1),routesContainer.getRequestOriginIdx(4));
+    routesContainer.tryAddRequest(3,routesContainer.getOriginDepot(1),routesContainer.getOrigin(4));
     biQueue = routesContainer.getBestInsertionsQueue(0,1);
     biQueue = routesContainer.getBestInsertionsQueue(1,1);
     biQueue = routesContainer.getBestInsertionsQueue(2,1);
diff --git a/test/src/ConstraintPropagationDebug.cpp b/test/src/ConstraintPropagationDebug.cpp
index 1c159f5..dd68aad 100644
--- a/test/src/ConstraintPropagationDebug.cpp
+++ b/test/src/ConstraintPropagationDebug.cpp
@@ -27,11 +27,11 @@ TEST(ConstraintPropagationDebug, DebugBaseInstance) {
     std::cout << "------------------Fin parsing instance et route-------------------" << std::endl << std::endl;
     int vehicleId = 1;
     assert(routesContainer.checkRouteTimeWindows(vehicleId));
-    SAEVRouteChangelist req0Changelist = routesContainer.tryAddRequest(0, routesContainer.getOriginDepotIdx(vehicleId), routesContainer.getOriginDepotIdx(1));
+    SAEVRouteChangelist req0Changelist = routesContainer.tryAddRequest(0, routesContainer.getOriginDepot(vehicleId), routesContainer.getOriginDepot(1));
     std::cout << routesContainer.to_string(vehicleId) << std::endl;
     assert(routesContainer.checkRouteTimeWindows(vehicleId));
     std::cout << "------------------------------------------------------------------" << std::endl;
-    SAEVRouteChangelist req1Changelist = routesContainer.tryAddRequest(1, routesContainer.getOriginDepotIdx(vehicleId), routesContainer.getRequestDestinationIdx(0));
+    SAEVRouteChangelist req1Changelist = routesContainer.tryAddRequest(1, routesContainer.getOriginDepot(vehicleId), routesContainer.getDestination(0));
     std::cout << routesContainer.to_string(vehicleId) << std::endl << std::endl;
     assert(!routesContainer.checkRouteTimeWindows(vehicleId));
     std::cout << "------------------------------------------------------------------" << std::endl;
@@ -67,7 +67,7 @@ TEST(ConstraintPropagationDebug, DebugRequestGeneration) {
 TEST(ConstraintPropagationDebug, DebugInstanceAlain) {
     std::string instancesPath = "../../resources/test/instances/Constraint Propagation/";
     std::string instanceFolder = "Instance_Alain_140624/";
-    std::string graphDatFile = "graph.dat";
+    std::string graphDatFile = "graph2.dat";
     std::string requestsDatFile = "requests.dat";
 
     //Parse graph
@@ -79,14 +79,14 @@ TEST(ConstraintPropagationDebug, DebugInstanceAlain) {
     SAEVRoute routesContainer(graphFromSingleFile, requests);
 
     //Vehicle 1 insertions
-    routesContainer.tryAddRequest(0,routesContainer.getOriginDepotIdx(0),routesContainer.getOriginDepotIdx(0));
-    routesContainer.tryAddRequest(1,routesContainer.getRequestOriginIdx(0),routesContainer.getRequestOriginIdx(0));
-    routesContainer.tryAddRequest(2,routesContainer.getRequestOriginIdx(1),routesContainer.getRequestDestinationIdx(0));
+    routesContainer.tryAddRequest(0,routesContainer.getOriginDepot(0),routesContainer.getOriginDepot(0));
+    routesContainer.tryAddRequest(1,routesContainer.getOrigin(0),routesContainer.getOrigin(0));
+    SAEVRouteChangelist cl = routesContainer.tryAddRequest(2,routesContainer.getOrigin(1),routesContainer.getDestination(1));
 
     //Vehicle 2 insertions
-    routesContainer.tryAddRequest(5,routesContainer.getOriginDepotIdx(1),routesContainer.getOriginDepotIdx(1));
-    routesContainer.tryAddRequest(4,routesContainer.getOriginDepotIdx(1),routesContainer.getRequestDestinationIdx(5));
-    routesContainer.tryAddRequest(3,routesContainer.getOriginDepotIdx(1),routesContainer.getRequestOriginIdx(4));
+    routesContainer.tryAddRequest(5,routesContainer.getOriginDepot(1),routesContainer.getOriginDepot(1));
+    routesContainer.tryAddRequest(4,routesContainer.getOriginDepot(1),routesContainer.getDestination(5));
+    routesContainer.tryAddRequest(3,routesContainer.getOriginDepot(1),routesContainer.getOrigin(4));
 }
 
 }
-- 
GitLab


From 8a745991e42180bbf6d8eb5e975ec12055bbd503 Mon Sep 17 00:00:00 2001
From: Romain BERNARD <romain.bernard@uca.fr>
Date: Wed, 19 Jun 2024 15:08:04 +0200
Subject: [PATCH 109/327] reverse priority queue order to have least the lowest
 deviation score first

---
 src/routes/vehicle/BestInsertionQueue.h | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/src/routes/vehicle/BestInsertionQueue.h b/src/routes/vehicle/BestInsertionQueue.h
index fa08426..7a6071b 100644
--- a/src/routes/vehicle/BestInsertionQueue.h
+++ b/src/routes/vehicle/BestInsertionQueue.h
@@ -9,7 +9,7 @@
 #include <queue>
 #include "BestRequestInsertion.h"
 
-class BestInsertionQueue : public std::priority_queue<BestRequestInsertion, std::vector<BestRequestInsertion>> {
+class BestInsertionQueue : public std::priority_queue<BestRequestInsertion, std::vector<BestRequestInsertion>, std::greater<>> {
 private:
     size_t _requestId{std::numeric_limits<size_t>::max()};
     size_t _vehicleId{std::numeric_limits<size_t>::max()};
-- 
GitLab


From bd475e72f494345d81c7748221d700e9e59b238c Mon Sep 17 00:00:00 2001
From: Romain BERNARD <romain.bernard@uca.fr>
Date: Wed, 19 Jun 2024 17:53:57 +0200
Subject: [PATCH 110/327] update request weights in insert/remove request
 methods

---
 src/routes/vehicle/SAEVRoute.cpp | 35 +++++++++++++++++++++++++++-----
 src/routes/vehicle/SAEVRoute.h   | 13 +++++++++++-
 2 files changed, 42 insertions(+), 6 deletions(-)

diff --git a/src/routes/vehicle/SAEVRoute.cpp b/src/routes/vehicle/SAEVRoute.cpp
index dccb0a4..20e23ce 100644
--- a/src/routes/vehicle/SAEVRoute.cpp
+++ b/src/routes/vehicle/SAEVRoute.cpp
@@ -67,11 +67,16 @@ void SAEVRoute::insertRequest(size_t requestId, SAEVKeyPoint &originRequestPrede
         originRequestPredecessorKP.setSuccessor(&originKp);
         originSuccKp->setPredecessor(&destinationKp);
     }
+    //Once insertion is done, update weights on the route
+    addRequestWeightToRoute(requestId);
 }
 
-void SAEVRoute::removeRequest(int requestId) {
-    SAEVKeyPoint& originKp = _route.at(requestId);
-    SAEVKeyPoint& destinationKp = _route.at(requestId + 1);
+void SAEVRoute::removeRequest(size_t requestId) {
+    //Before undoing the insertion, update weights on the route
+    addRequestWeightToRoute(requestId);
+
+    SAEVKeyPoint& originKp = getOrigin(requestId);
+    SAEVKeyPoint& destinationKp = getDestination(requestId);
 
     //get predecessor and successor for request
     SAEVKeyPoint* originPredecessor = originKp.getPredecessor();
@@ -92,8 +97,6 @@ void SAEVRoute::removeRequest(int requestId) {
     originKp.setMaxTw(_requestList->at(requestId).getMaxDepartureTw());
     destinationKp.setMinTw(_requestList->at(requestId).getMinArrivalTw());
     destinationKp.setMaxTw(_requestList->at(requestId).getMaxArrivalTw());
-    originKp.setCurrentOccupation(0);
-    destinationKp.setCurrentOccupation(0);
 }
 
 SAEVRouteChangelist
@@ -397,3 +400,25 @@ BestInsertionQueue SAEVRoute::getBestInsertionsQueue(size_t requestId, size_t ve
     return bestInsertionQueue;
 }
 
+void SAEVRoute::addRequestWeightToRoute(size_t requestId) {
+    SAEVKeyPoint& currentKP = getOrigin(requestId);
+    int requestWeight = currentKP.getRequest()->getWeight();
+    currentKP.setCurrentOccupation(currentKP.getPredecessor()->getCurrentOccupation() + requestWeight); //O.Weight = Prec(O).Weight + R.Weight (request enters the vehicle=)
+    do {
+        currentKP = *currentKP.getSuccessor();
+        currentKP.setCurrentOccupation(currentKP.getCurrentOccupation() + requestWeight);
+    } while (currentKP != getDestination(requestId));
+    currentKP.setCurrentOccupation(currentKP.getPredecessor()->getCurrentOccupation() - requestWeight); //D.Weight = Prec(D).Weight - R.Weight (request leaves the vehicle)
+}
+
+void SAEVRoute::removeRequestWeightFromRoute(size_t requestId) {
+    SAEVKeyPoint& currentKP = getOrigin(requestId);
+    int requestWeight = currentKP.getRequest()->getWeight();
+    currentKP.setCurrentOccupation(0); //reset request weight on origin KP
+    do {
+        currentKP = *currentKP.getSuccessor();
+        currentKP.setCurrentOccupation(currentKP.getCurrentOccupation() - requestWeight);
+    } while (currentKP != getDestination(requestId));
+    currentKP.setCurrentOccupation(0); //reset request weight on destination KP
+}
+
diff --git a/src/routes/vehicle/SAEVRoute.h b/src/routes/vehicle/SAEVRoute.h
index d9ebee9..d879a3f 100644
--- a/src/routes/vehicle/SAEVRoute.h
+++ b/src/routes/vehicle/SAEVRoute.h
@@ -44,7 +44,18 @@ public:
      * Raw request removal method. Public for debug purposes, but should effectively never be called by an outside member
      * @param requestId index of the request we want to remove from the route
      */
-    void removeRequest(int requestId);
+    void removeRequest(size_t requestId);
+
+    /**
+     * Updates weight in-between request's Origin/Destination (both included) to account for the given request's weight
+     * @param requestId ID of the request that serves as basis for iteration and weight to add
+     */
+    void addRequestWeightToRoute(size_t requestId);
+    /**
+     * Resets current weight to 0 on the request Origin/Destination key points and decreases weight on the nodes in-between by the request's weight
+     * @param requestId ID of the request that serves as basis for iteration and weight to remove
+     */
+    void removeRequestWeightFromRoute(size_t requestId);
 
     /**
      * Tries to insert the request origin and destination next to the given origin/destination predecessors. \n \n
-- 
GitLab


From 490bdc01d821fb5042c14f37b31d74be8607e8d1 Mon Sep 17 00:00:00 2001
From: Romain BERNARD <romain.bernard@uca.fr>
Date: Wed, 19 Jun 2024 18:05:11 +0200
Subject: [PATCH 111/327] remove dead code

---
 src/routes/vehicle/SAEVRoute.cpp | 2 --
 1 file changed, 2 deletions(-)

diff --git a/src/routes/vehicle/SAEVRoute.cpp b/src/routes/vehicle/SAEVRoute.cpp
index 20e23ce..9b6a764 100644
--- a/src/routes/vehicle/SAEVRoute.cpp
+++ b/src/routes/vehicle/SAEVRoute.cpp
@@ -270,8 +270,6 @@ SAEVRouteChangelist SAEVRoute::insertRequestWithPropagation(const size_t request
                 counterpartKP->setMaxTw(newValue);
                 boundPropagationQueue.emplace(Max, counterpartKP);
                 DEBUG_MSG("\tMAX Destination KP=" + counterpartKP->to_string() + "\n\tModif Max=" + std::to_string(oldValue) + "->" + std::to_string(newValue));
-            } else if(!keyPoint->isDepot() && keyPoint->isOrigin()) {
-//                DEBUG_MSG("Pas de changement pour Max du noeud " + counterpartKP->to_string() + " via son origine " + keyPoint->to_string());
             }
         }
     }
-- 
GitLab


From 1a2ed9419f523b94a0c94f2317c95b90e282c131 Mon Sep 17 00:00:00 2001
From: Romain BERNARD <romain.bernard@uca.fr>
Date: Wed, 19 Jun 2024 18:18:41 +0200
Subject: [PATCH 112/327] fix weight update (use of mixed reference/pointer
 caused unexpected affectations)

---
 src/routes/vehicle/SAEVRoute.cpp | 28 ++++++++++++++--------------
 1 file changed, 14 insertions(+), 14 deletions(-)

diff --git a/src/routes/vehicle/SAEVRoute.cpp b/src/routes/vehicle/SAEVRoute.cpp
index 9b6a764..a447646 100644
--- a/src/routes/vehicle/SAEVRoute.cpp
+++ b/src/routes/vehicle/SAEVRoute.cpp
@@ -399,24 +399,24 @@ BestInsertionQueue SAEVRoute::getBestInsertionsQueue(size_t requestId, size_t ve
 }
 
 void SAEVRoute::addRequestWeightToRoute(size_t requestId) {
-    SAEVKeyPoint& currentKP = getOrigin(requestId);
-    int requestWeight = currentKP.getRequest()->getWeight();
-    currentKP.setCurrentOccupation(currentKP.getPredecessor()->getCurrentOccupation() + requestWeight); //O.Weight = Prec(O).Weight + R.Weight (request enters the vehicle=)
+    SAEVKeyPoint* currentKP = &getOrigin(requestId);
+    int requestWeight = currentKP->getRequest()->getWeight();
+    currentKP->setCurrentOccupation(currentKP->getPredecessor()->getCurrentOccupation() + requestWeight); //O.Weight = Prec(O).Weight + R.Weight (request enters the vehicle=)
     do {
-        currentKP = *currentKP.getSuccessor();
-        currentKP.setCurrentOccupation(currentKP.getCurrentOccupation() + requestWeight);
-    } while (currentKP != getDestination(requestId));
-    currentKP.setCurrentOccupation(currentKP.getPredecessor()->getCurrentOccupation() - requestWeight); //D.Weight = Prec(D).Weight - R.Weight (request leaves the vehicle)
+        currentKP = currentKP->getSuccessor();
+        currentKP->setCurrentOccupation(currentKP->getCurrentOccupation() + requestWeight);
+    } while (currentKP != &getDestination(requestId));
+    currentKP->setCurrentOccupation(currentKP->getPredecessor()->getCurrentOccupation() - requestWeight); //D.Weight = Prec(D).Weight - R.Weight (request leaves the vehicle)
 }
 
 void SAEVRoute::removeRequestWeightFromRoute(size_t requestId) {
-    SAEVKeyPoint& currentKP = getOrigin(requestId);
-    int requestWeight = currentKP.getRequest()->getWeight();
-    currentKP.setCurrentOccupation(0); //reset request weight on origin KP
+    SAEVKeyPoint* currentKP = &getOrigin(requestId);
+    int requestWeight = currentKP->getRequest()->getWeight();
+    currentKP->setCurrentOccupation(0); //reset request weight on origin KP
     do {
-        currentKP = *currentKP.getSuccessor();
-        currentKP.setCurrentOccupation(currentKP.getCurrentOccupation() - requestWeight);
-    } while (currentKP != getDestination(requestId));
-    currentKP.setCurrentOccupation(0); //reset request weight on destination KP
+        currentKP = currentKP->getSuccessor();
+        currentKP->setCurrentOccupation(currentKP->getCurrentOccupation() - requestWeight);
+    } while (currentKP != &getDestination(requestId));
+    currentKP->setCurrentOccupation(0); //reset request weight on destination KP
 }
 
-- 
GitLab


From 6ca2d390dd524c17c7564cbb5cc3975de9567111 Mon Sep 17 00:00:00 2001
From: Romain BERNARD <romain.bernard@uca.fr>
Date: Wed, 19 Jun 2024 18:19:46 +0200
Subject: [PATCH 113/327] Add InsertionStatus to changelists to properly
 insert/remove requests when applying/reverting changes

---
 src/routes/vehicle/SAEVRoute.cpp              | 10 ++++--
 .../propagation/SAEVRouteChangelist.cpp       | 36 +++++++++++++++----
 .../vehicle/propagation/SAEVRouteChangelist.h | 30 ++++++++++++----
 3 files changed, 60 insertions(+), 16 deletions(-)

diff --git a/src/routes/vehicle/SAEVRoute.cpp b/src/routes/vehicle/SAEVRoute.cpp
index a447646..f0068f3 100644
--- a/src/routes/vehicle/SAEVRoute.cpp
+++ b/src/routes/vehicle/SAEVRoute.cpp
@@ -109,7 +109,7 @@ SAEVRoute::tryAddRequest(const size_t requestId, SAEVKeyPoint &originRequestPred
     do {
         if(currentKP->getCurrentOccupation() + request->getWeight() > SAEVehicle::getCapacity()) {
             DEBUG_MSG("WEIGHT VIOLATION : request weight = " + std::to_string(request->getWeight()) + " incompatible KP = " + currentKP->to_string());
-            return SAEVRouteChangelist(this, requestId, originRequestPredecessorKP, destinationRequestPredecessorKP);
+            return SAEVRouteChangelist(this, requestId, originRequestPredecessorKP, destinationRequestPredecessorKP, SAEVRouteChangelist::InsertionStatus::FAILURE_PRECONDITION_WEIGHT);
         }
         currentKP = currentKP->getSuccessor();
     } while (currentKP != destinationSuccessor && currentKP != nullptr);
@@ -121,7 +121,7 @@ SAEVRoute::tryAddRequest(const size_t requestId, SAEVKeyPoint &originRequestPred
         return insertRequestWithPropagation(requestId, originRequestPredecessorKP, destinationRequestPredecessorKP);
     } else {
         DEBUG_MSG("TW VIOLATION on neighbour KPs");
-        return SAEVRouteChangelist(this, requestId, originRequestPredecessorKP, destinationRequestPredecessorKP);
+        return SAEVRouteChangelist(this, requestId, originRequestPredecessorKP, destinationRequestPredecessorKP, SAEVRouteChangelist::InsertionStatus::FAILURE_PRECONDITION_TW);
     }
 }
 
@@ -175,7 +175,7 @@ SAEVRoute::doNeighbouringTWChecks(const size_t requestId, const size_t originNod
 SAEVRouteChangelist SAEVRoute::insertRequestWithPropagation(const size_t requestId, SAEVKeyPoint &originRequestPredecessorKP,
                                                             SAEVKeyPoint &destinationRequestPredecessorKP) {
     //Init changelist
-    SAEVRouteChangelist changelist{this, requestId, originRequestPredecessorKP, destinationRequestPredecessorKP};
+    SAEVRouteChangelist changelist{this, requestId, originRequestPredecessorKP, destinationRequestPredecessorKP, SAEVRouteChangelist::InsertionStatus::FAILURE_MIN};
     //Properly insert the request to facilitate constraint propagation
     insertRequest(requestId, originRequestPredecessorKP, destinationRequestPredecessorKP);
 
@@ -214,6 +214,7 @@ SAEVRouteChangelist SAEVRoute::insertRequestWithPropagation(const size_t request
                 if (oldValue < newValue) {
                     if (newValue > successorKP->getMaxTw()) {
                         DEBUG_MSG("\tMIN TW VIOLATION");
+                        changelist.setStatus(SAEVRouteChangelist::InsertionStatus::FAILURE_MIN);
                         return changelist;
                     }
                     DEBUG_MSG("\tMIN Successeur KP=" + successorKP->to_string() + "\n\tModif Min=" + std::to_string(oldValue) + "->" + std::to_string(newValue));
@@ -230,6 +231,7 @@ SAEVRouteChangelist SAEVRoute::insertRequestWithPropagation(const size_t request
             if(!keyPoint->isDepot() && keyPoint->isDestination() && oldValue < newValue) {
                 if (newValue > counterpartKP->getMaxTw()) {
                     DEBUG_MSG("\tMIN DELTA Destination->Origine");
+                    changelist.setStatus(SAEVRouteChangelist::InsertionStatus::FAILURE_DELTA_MIN);
                     return changelist;
                 }
                 DEBUG_MSG("\tMIN Counterpart KP=" + counterpartKP->to_string() + "\n\tModif Min=" + std::to_string(oldValue) + "->" + std::to_string(newValue));
@@ -248,6 +250,7 @@ SAEVRouteChangelist SAEVRoute::insertRequestWithPropagation(const size_t request
                 if(oldValue > newValue) {
                     if (predecessorKP->getMinTw() > newValue) {
                         DEBUG_MSG("\tMAX TW VIOLATION");
+                        changelist.setStatus(SAEVRouteChangelist::InsertionStatus::FAILURE_MAX);
                         return changelist;
                     }
                     DEBUG_MSG("\tMAX Predecessor KP=" + predecessorKP->to_string() + "\n\tModif Max=" + std::to_string(oldValue) + "->" + std::to_string(newValue));
@@ -264,6 +267,7 @@ SAEVRouteChangelist SAEVRoute::insertRequestWithPropagation(const size_t request
             if(!keyPoint->isDepot() && keyPoint->isOrigin() && oldValue > newValue) {
                 if (counterpartKP->getMinTw() > newValue) {
                     DEBUG_MSG("\tMAX DELTA Origine->Destination");
+                    changelist.setStatus(SAEVRouteChangelist::InsertionStatus::FAILURE_DELTA_MAX);
                     return changelist;
                 }
                 changelist.emplace_back(*counterpartKP, Max, oldValue - newValue);
diff --git a/src/routes/vehicle/propagation/SAEVRouteChangelist.cpp b/src/routes/vehicle/propagation/SAEVRouteChangelist.cpp
index 07ee842..3e05775 100644
--- a/src/routes/vehicle/propagation/SAEVRouteChangelist.cpp
+++ b/src/routes/vehicle/propagation/SAEVRouteChangelist.cpp
@@ -20,20 +20,24 @@ void SAEVRouteChangelist::emplace_back(SAEVKeyPoint &kp, Bound bound, int value)
     _changelist.emplace_back(kp, bound, value);
 }
 
-void SAEVRouteChangelist::applyChanges() const {
-    _routePtr->insertRequest(_requestId, _originPredecessorKP, _destinationPredecessorKP);
+void SAEVRouteChangelist::applyChanges() {
+    if(_status < InsertionStatus::FAILURE_PRECONDITION_TW) {
+        _routePtr->insertRequest(_requestId, _originPredecessorKP, _destinationPredecessorKP);
+    }
     for(SAEVRouteChange change : _changelist) {
         change.applyChange();
     }
-    //TODO: update key point weights here ? (only if changelist.size > 0 & score < +Inf)
+    _currentStatus = _status;
 }
 
-void SAEVRouteChangelist::revertChanges() const {
-    _routePtr->removeRequest(_requestId);
+void SAEVRouteChangelist::revertChanges() {
+    if(_status < InsertionStatus::FAILURE_PRECONDITION_TW) {
+        _routePtr->removeRequest(_requestId);
+    }
     for(SAEVRouteChange change : _changelist) {
         change.revertChange();
     }
-    //TODO: update key point weights here ? (only if changelist.size > 0 & score < +Inf)
+    _currentStatus = InsertionStatus::CHANGELIST_REVERTED;
 }
 
 size_t SAEVRouteChangelist::getRequestId() const {
@@ -67,3 +71,23 @@ bool SAEVRouteChangelist::operator<(const SAEVRouteChangelist &rhs) const {
 SAEVRoute * SAEVRouteChangelist::getRoutePtr() const {
     return _routePtr;
 }
+
+SAEVRouteChangelist::InsertionStatus SAEVRouteChangelist::getStatus() const {
+    return _status;
+}
+
+SAEVRouteChangelist::InsertionStatus SAEVRouteChangelist::getCurrentStatus() const {
+    return _currentStatus;
+}
+
+bool SAEVRouteChangelist::shouldUndoInsertion() const {
+    return _currentStatus > InsertionStatus::FAILURE_DELTA_MAX;
+}
+
+void SAEVRouteChangelist::setStatus(SAEVRouteChangelist::InsertionStatus status) {
+    _status = status;
+}
+
+void SAEVRouteChangelist::setCurrentStatus(SAEVRouteChangelist::InsertionStatus currentStatus) {
+    _currentStatus = currentStatus;
+}
diff --git a/src/routes/vehicle/propagation/SAEVRouteChangelist.h b/src/routes/vehicle/propagation/SAEVRouteChangelist.h
index f15912a..8ea0747 100644
--- a/src/routes/vehicle/propagation/SAEVRouteChangelist.h
+++ b/src/routes/vehicle/propagation/SAEVRouteChangelist.h
@@ -18,12 +18,13 @@ class SAEVRouteChangelist {
 public:
     enum class InsertionStatus{
         SUCCESS,
-        FAILURE_PRECONDITION_TW,
-        FAILURE_PRECONDITION_WEIGHT,//To check if you need to remove a request, check status > FAILURE_PRECONDITION_WEIGHT
         FAILURE_MIN,
         FAILURE_MAX,
         FAILURE_DELTA_MIN,
-        FAILURE_DELTA_MAX
+        FAILURE_DELTA_MAX,
+        FAILURE_PRECONDITION_TW, //To check if you need to remove a request, check status > FAILURE_PRECONDITION_WEIGHT
+        FAILURE_PRECONDITION_WEIGHT,
+        CHANGELIST_REVERTED
     };
 private:
     SAEVRoute * const _routePtr;
@@ -33,6 +34,9 @@ private:
     std::vector<SAEVRouteChange> _changelist{};
     double _score{std::numeric_limits<double>::infinity()}; //Init score to infinity
 
+    InsertionStatus _status; //Status on changelist creation
+    InsertionStatus _currentStatus; //Updated status after applying/reverting changelist
+
 public:
     /**
      * Initializes a change list to memorize every iterative modification made during constraint propagation
@@ -41,8 +45,8 @@ public:
      * @param originPredecessorKP The index of the request our origin will be inserted after
      * @param destinationPredecessorKP The index of the request our destination will be inserted after
      */
-    explicit SAEVRouteChangelist(SAEVRoute * const routePtr, const size_t requestId, SAEVKeyPoint &originPredecessorKP, SAEVKeyPoint &destinationPredecessorKP)
-    : _routePtr(routePtr), _requestId(requestId), _originPredecessorKP(originPredecessorKP), _destinationPredecessorKP(destinationPredecessorKP) {};
+    explicit SAEVRouteChangelist(SAEVRoute * const routePtr, const size_t requestId, SAEVKeyPoint &originPredecessorKP, SAEVKeyPoint &destinationPredecessorKP, InsertionStatus status)
+    : _routePtr(routePtr), _requestId(requestId), _originPredecessorKP(originPredecessorKP), _destinationPredecessorKP(destinationPredecessorKP), _status(status), _currentStatus(status) {};
 
     /**
      * @return A pointer to the route this change list applies/reverts changes to
@@ -59,11 +63,22 @@ public:
 
     [[nodiscard]] const SAEVKeyPoint &getDestinationPredecessorKP() const;
 
+    [[nodiscard]] InsertionStatus getStatus() const;
+    void setStatus(InsertionStatus status);
+
+    [[nodiscard]] InsertionStatus getCurrentStatus() const;
+    void setCurrentStatus(InsertionStatus currentStatus);
+
     /**
      * @return A score value associated with this changelist. A lower score is better
      */
     [[nodiscard]] double getScore() const;
 
+    /**
+     * @return True iff the current state of the route wrt change list requires to remove undo an insertion
+     */
+    [[nodiscard]] bool shouldUndoInsertion() const;
+
     /**
      * Updates this change list's score value if needed (namely, after the whole propagation has been done)
      * @param score A value representing how good the insertion associated with this change list is (lower is better)
@@ -76,14 +91,15 @@ public:
 
     /**
      * Inserts the request associated to this changelist to the given route and iteratively applies every change memorized in this changelist.
+     * Changelist status is updated to reflect the original value associated with the changes
      * Aside from OOB exceptions, no checks are done in this method
      */
-    void applyChanges() const;
+    void applyChanges();
     /**
      * removes the request associated to this changelist from the given route and iteratively reverts every change memorized in this changelist.
      * Aside from OOB exceptions, no checks are done in this method
      */
-    void revertChanges() const;
+    void revertChanges();
 
     /**
      * @param rhs the value *this* will be compared to
-- 
GitLab


From 2b168fedb77dd085ecc8f0fccd57d0d3414759d0 Mon Sep 17 00:00:00 2001
From: Romain BERNARD <romain.bernard@uca.fr>
Date: Thu, 20 Jun 2024 10:20:28 +0200
Subject: [PATCH 114/327] fix typo

---
 src/routes/vehicle/SAEVRoute.cpp | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/src/routes/vehicle/SAEVRoute.cpp b/src/routes/vehicle/SAEVRoute.cpp
index f0068f3..0255411 100644
--- a/src/routes/vehicle/SAEVRoute.cpp
+++ b/src/routes/vehicle/SAEVRoute.cpp
@@ -73,7 +73,7 @@ void SAEVRoute::insertRequest(size_t requestId, SAEVKeyPoint &originRequestPrede
 
 void SAEVRoute::removeRequest(size_t requestId) {
     //Before undoing the insertion, update weights on the route
-    addRequestWeightToRoute(requestId);
+    removeRequestWeightFromRoute(requestId);
 
     SAEVKeyPoint& originKp = getOrigin(requestId);
     SAEVKeyPoint& destinationKp = getDestination(requestId);
-- 
GitLab


From 97c00655d78855ea059903bf88c9031bad6f99ad Mon Sep 17 00:00:00 2001
From: Romain BERNARD <romain.bernard@uca.fr>
Date: Thu, 20 Jun 2024 10:22:31 +0200
Subject: [PATCH 115/327] refactor move request route classes

---
 CMakeLists.txt                                |  8 ++++----
 src/instance/requests/Request.h               |  2 +-
 src/routes/{ => requests}/RequestKeyPoint.cpp |  0
 src/routes/{ => requests}/RequestKeyPoint.h   |  6 +++---
 src/routes/{ => requests}/RequestRoute.cpp    |  0
 src/routes/{ => requests}/RequestRoute.h      |  2 +-
 test/CMakeLists.txt                           | 16 ++++++++--------
 7 files changed, 17 insertions(+), 17 deletions(-)
 rename src/routes/{ => requests}/RequestKeyPoint.cpp (100%)
 rename src/routes/{ => requests}/RequestKeyPoint.h (91%)
 rename src/routes/{ => requests}/RequestRoute.cpp (100%)
 rename src/routes/{ => requests}/RequestRoute.h (96%)

diff --git a/CMakeLists.txt b/CMakeLists.txt
index 60080e1..b279b6e 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -40,16 +40,16 @@ add_executable(GreedyAlgorithm
         src/ShortestPath/Transit/TransitAlgorithmState.h
         src/ShortestPath/Transit/TransitShortestPathContainer.cpp
         src/ShortestPath/Transit/TransitShortestPathContainer.h
-        src/routes/RequestRoute.cpp
-        src/routes/RequestRoute.h
+        src/routes/requests/RequestRoute.cpp
+        src/routes/requests/RequestRoute.h
         src/routes/vehicle/SAEVRoute.cpp
         src/routes/vehicle/SAEVRoute.h
         src/TimeWindow.cpp
         src/TimeWindow.h
         src/routes/KeyPoint.cpp
         src/routes/KeyPoint.h
-        src/routes/RequestKeyPoint.cpp
-        src/routes/RequestKeyPoint.h
+        src/routes/requests/RequestKeyPoint.cpp
+        src/routes/requests/RequestKeyPoint.h
         src/routes/vehicle/SAEVKeyPoint.cpp
         src/routes/vehicle/SAEVKeyPoint.h
         src/instance/SAEVehicle.cpp
diff --git a/src/instance/requests/Request.h b/src/instance/requests/Request.h
index bec3589..df95f2f 100644
--- a/src/instance/requests/Request.h
+++ b/src/instance/requests/Request.h
@@ -7,7 +7,7 @@
 
 
 #include "../../TimeWindow.h"
-#include "../../routes/RequestRoute.h"
+#include "../../routes/requests/RequestRoute.h"
 #include "../graph/Graph.h"
 
 class Request {
diff --git a/src/routes/RequestKeyPoint.cpp b/src/routes/requests/RequestKeyPoint.cpp
similarity index 100%
rename from src/routes/RequestKeyPoint.cpp
rename to src/routes/requests/RequestKeyPoint.cpp
diff --git a/src/routes/RequestKeyPoint.h b/src/routes/requests/RequestKeyPoint.h
similarity index 91%
rename from src/routes/RequestKeyPoint.h
rename to src/routes/requests/RequestKeyPoint.h
index 4794e5b..f96e2b9 100644
--- a/src/routes/RequestKeyPoint.h
+++ b/src/routes/requests/RequestKeyPoint.h
@@ -6,9 +6,9 @@
 #define GREEDYALGORITHM_REQUESTKEYPOINT_H
 
 
-#include "KeyPoint.h"
-#include "../instance/SAEVehicle.h"
-#include "../instance/graph/LineStop.h"
+#include "../KeyPoint.h"
+#include "../../instance/SAEVehicle.h"
+#include "../../instance/graph/LineStop.h"
 
 class RequestKeyPoint : public KeyPoint {
 private:
diff --git a/src/routes/RequestRoute.cpp b/src/routes/requests/RequestRoute.cpp
similarity index 100%
rename from src/routes/RequestRoute.cpp
rename to src/routes/requests/RequestRoute.cpp
diff --git a/src/routes/RequestRoute.h b/src/routes/requests/RequestRoute.h
similarity index 96%
rename from src/routes/RequestRoute.h
rename to src/routes/requests/RequestRoute.h
index a32911c..d9f3bf1 100644
--- a/src/routes/RequestRoute.h
+++ b/src/routes/requests/RequestRoute.h
@@ -41,6 +41,6 @@ public:
     void resetKeyPoint(int routeIndex);
 };
 
-#include "../instance/requests/Request.h"
+#include "../../instance/requests/Request.h"
 
 #endif //GREEDYALGORITHM_REQUESTROUTE_H
diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt
index bb085d9..cc5c263 100644
--- a/test/CMakeLists.txt
+++ b/test/CMakeLists.txt
@@ -62,10 +62,10 @@ add_executable(Constraint_Propag_DEB
         ../src/routes/vehicle/SAEVKeyPoint.h
         ../src/routes/KeyPoint.cpp
         ../src/routes/KeyPoint.h
-        ../src/routes/RequestKeyPoint.cpp
-        ../src/routes/RequestKeyPoint.h
-        ../src/routes/RequestRoute.cpp
-        ../src/routes/RequestRoute.h
+        ../src/routes/requests/RequestKeyPoint.cpp
+        ../src/routes/requests/RequestKeyPoint.h
+        ../src/routes/requests/RequestRoute.cpp
+        ../src/routes/requests/RequestRoute.h
         "../src/utils/Instance Generation/Requests/RequestsGenerator.cpp"
         "../src/utils/Instance Generation/Requests/RequestsGenerator.h"
         "../src/utils/Instance Generation/Requests/RequestGenerationParameters.h"
@@ -96,10 +96,10 @@ add_executable(BestInsertionHeuristic_DEB
         ../src/routes/vehicle/SAEVKeyPoint.h
         ../src/routes/KeyPoint.cpp
         ../src/routes/KeyPoint.h
-        ../src/routes/RequestKeyPoint.cpp
-        ../src/routes/RequestKeyPoint.h
-        ../src/routes/RequestRoute.cpp
-        ../src/routes/RequestRoute.h
+        ../src/routes/requests/RequestKeyPoint.cpp
+        ../src/routes/requests/RequestKeyPoint.h
+        ../src/routes/requests/RequestRoute.cpp
+        ../src/routes/requests/RequestRoute.h
         ../src/routes/vehicle/BestRequestInsertion.h
         ../src/routes/vehicle/BestInsertionQueue.h
 )
-- 
GitLab


From 8b60bd1496f2d3a61d45ce60e74f220fb4e8f974 Mon Sep 17 00:00:00 2001
From: Romain BERNARD <romain.bernard@uca.fr>
Date: Thu, 20 Jun 2024 10:24:57 +0200
Subject: [PATCH 116/327] add practical usage comment to the add/remove weight
 functions

---
 src/routes/vehicle/SAEVRoute.h | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/src/routes/vehicle/SAEVRoute.h b/src/routes/vehicle/SAEVRoute.h
index d879a3f..2c53f70 100644
--- a/src/routes/vehicle/SAEVRoute.h
+++ b/src/routes/vehicle/SAEVRoute.h
@@ -48,11 +48,13 @@ public:
 
     /**
      * Updates weight in-between request's Origin/Destination (both included) to account for the given request's weight
+     * ⚠️ Execute this function *after* adding the request to the route, as it assumes the request is part of the route
      * @param requestId ID of the request that serves as basis for iteration and weight to add
      */
     void addRequestWeightToRoute(size_t requestId);
     /**
      * Resets current weight to 0 on the request Origin/Destination key points and decreases weight on the nodes in-between by the request's weight
+     * ⚠️ Execute this function *before* removing the request from the route, as it assumes the request is still part of the route
      * @param requestId ID of the request that serves as basis for iteration and weight to remove
      */
     void removeRequestWeightFromRoute(size_t requestId);
-- 
GitLab


From 3b34090dc6bab1ac091b9521a23e144bc44365c5 Mon Sep 17 00:00:00 2001
From: Romain BERNARD <romain.bernard@uca.fr>
Date: Thu, 20 Jun 2024 13:46:56 +0200
Subject: [PATCH 117/327] Remove finalize insertion method

---
 src/routes/vehicle/SAEVRoute.cpp | 14 --------------
 src/routes/vehicle/SAEVRoute.h   |  9 ---------
 2 files changed, 23 deletions(-)

diff --git a/src/routes/vehicle/SAEVRoute.cpp b/src/routes/vehicle/SAEVRoute.cpp
index 0255411..08d2579 100644
--- a/src/routes/vehicle/SAEVRoute.cpp
+++ b/src/routes/vehicle/SAEVRoute.cpp
@@ -358,20 +358,6 @@ bool SAEVRoute::checkRouteTimeWindows(size_t vehicleId) {
     return true;
 }
 
-void SAEVRoute::finalizeRequestInsertion(const size_t requestId) {
-    SAEVKeyPoint * currentKeyPoint = &getOrigin(requestId);
-    SAEVKeyPoint const * counterpartKP = currentKeyPoint->getCounterpart();
-    int requestWeight = counterpartKP->getRequest()->getWeight();
-    //Init weight value for Origin KP
-    currentKeyPoint->setCurrentOccupation(currentKeyPoint->getPredecessor()->getCurrentOccupation() + requestWeight);
-    //Iterate over KPs in-between Origin and Destination
-    currentKeyPoint = currentKeyPoint->getSuccessor();
-    while(currentKeyPoint != counterpartKP) {
-        currentKeyPoint->setCurrentOccupation(currentKeyPoint->getCurrentOccupation() + requestWeight);
-        currentKeyPoint = currentKeyPoint->getSuccessor();
-    }
-}
-
 /**
  * Initializes a BestInsertionQueue to guide the best insertion heuristic
  * @param requestId
diff --git a/src/routes/vehicle/SAEVRoute.h b/src/routes/vehicle/SAEVRoute.h
index 2c53f70..64be3c1 100644
--- a/src/routes/vehicle/SAEVRoute.h
+++ b/src/routes/vehicle/SAEVRoute.h
@@ -71,15 +71,6 @@ public:
      */
     SAEVRouteChangelist tryAddRequest(const size_t requestId, SAEVKeyPoint &originRequestPredecessorKP, SAEVKeyPoint &destinationRequestPredecessorKP);
 
-    /**
-     * Call this function whenever a request insertion is considered final (Insertion success + satisfied with result)
-     * Currently only updates Key Point weights, but other post insertion processes will go here
-     * Processe(s) :
-     * 1) Update weights between the request's origin and destination in the vehicle's key points
-     * @param requestId ID of the request that was inserted
-     */
-    void finalizeRequestInsertion(const size_t requestId);
-
     /**
      * Verifies time window constraints on our request's origin/destination's projected neighbour, aka originPredecessor/destinationPredecessor and their successor.
      * There is a special case taken into account if originPredecessor and destinationPredecessor are the same KeyPoint, since then, Origin's successor would be Destination
-- 
GitLab


From 69a9deb6bae8fb4713d4d8c45af23b0d5a64cee4 Mon Sep 17 00:00:00 2001
From: Romain BERNARD <romain.bernard@uca.fr>
Date: Thu, 20 Jun 2024 16:57:17 +0200
Subject: [PATCH 118/327] remove const identifier in BestRequestInsertion to
 use those values in insertion algorithm

---
 src/routes/vehicle/BestRequestInsertion.h | 10 +++++-----
 src/routes/vehicle/SAEVRoute.cpp          | 18 +++++++++---------
 2 files changed, 14 insertions(+), 14 deletions(-)

diff --git a/src/routes/vehicle/BestRequestInsertion.h b/src/routes/vehicle/BestRequestInsertion.h
index 0a19ab7..232421d 100644
--- a/src/routes/vehicle/BestRequestInsertion.h
+++ b/src/routes/vehicle/BestRequestInsertion.h
@@ -13,8 +13,8 @@
 
 class BestRequestInsertion {
 private:
-    const SAEVKeyPoint* _originInsertionKP;
-    const SAEVKeyPoint* _destinationInsertionKP;
+    SAEVKeyPoint* _originInsertionKP;
+    SAEVKeyPoint* _destinationInsertionKP;
     double _score{ std::numeric_limits<double>::max() };
 
 public:
@@ -28,11 +28,11 @@ public:
      * @param destinationInsertionKP Index of insertion for the destination of the request in the route
      * @param score
      */
-    BestRequestInsertion(const SAEVKeyPoint *originInsertionKP, const SAEVKeyPoint *destinationInsertionKP, double score)
+    BestRequestInsertion(SAEVKeyPoint *originInsertionKP, SAEVKeyPoint *destinationInsertionKP, double score)
             : _originInsertionKP(originInsertionKP), _destinationInsertionKP(destinationInsertionKP),
               _score(score) {};
 
-    [[nodiscard]] const SAEVKeyPoint *getOriginInsertionKp() const {
+    [[nodiscard]] SAEVKeyPoint *getOriginInsertionKp() {
         return _originInsertionKP;
     }
 
@@ -40,7 +40,7 @@ public:
         _originInsertionKP = originInsertionKp;
     }
 
-    [[nodiscard]] const SAEVKeyPoint *getDestinationInsertionKp() const {
+    [[nodiscard]] SAEVKeyPoint *getDestinationInsertionKp() {
         return _destinationInsertionKP;
     }
 
diff --git a/src/routes/vehicle/SAEVRoute.cpp b/src/routes/vehicle/SAEVRoute.cpp
index 08d2579..7d15347 100644
--- a/src/routes/vehicle/SAEVRoute.cpp
+++ b/src/routes/vehicle/SAEVRoute.cpp
@@ -369,20 +369,20 @@ BestInsertionQueue SAEVRoute::getBestInsertionsQueue(size_t requestId, size_t ve
 
     //Init variables used during iteration
     double score;
-    SAEVKeyPoint const* originKeyPoint = &getOriginDepot(vehicleId);
-    SAEVKeyPoint const* destinationKeyPoint = originKeyPoint;
+    SAEVKeyPoint * originInsertionKeyPoint = &getOriginDepot(vehicleId);
+    SAEVKeyPoint * destinationInsertionKeyPoint = originInsertionKeyPoint;
 
     //iterate over possible origin/destination pairs for the given vehicle
-    while(originKeyPoint->getSuccessor() != nullptr) {
-        while(destinationKeyPoint->getSuccessor() != nullptr) {
-            score = getDetourScore(requestId, *originKeyPoint, *destinationKeyPoint);
-            bestInsertionQueue.emplace(originKeyPoint, destinationKeyPoint, score);
-            destinationKeyPoint = destinationKeyPoint->getSuccessor();
+    while(originInsertionKeyPoint->getSuccessor() != nullptr) {
+        while(destinationInsertionKeyPoint->getSuccessor() != nullptr) {
+            score = getDetourScore(requestId, *originInsertionKeyPoint, *destinationInsertionKeyPoint);
+            bestInsertionQueue.emplace(originInsertionKeyPoint, destinationInsertionKeyPoint, score);
+            destinationInsertionKeyPoint = destinationInsertionKeyPoint->getSuccessor();
         }
 
         //Iterate over possible origins and reset destination to being the same point as the origin
-        originKeyPoint = originKeyPoint->getSuccessor();
-        destinationKeyPoint = originKeyPoint;
+        originInsertionKeyPoint = originInsertionKeyPoint->getSuccessor();
+        destinationInsertionKeyPoint = originInsertionKeyPoint;
     }
 
     return bestInsertionQueue;
-- 
GitLab


From ba53ca98fe4799c52a594722ac4fb41cb30109db Mon Sep 17 00:00:00 2001
From: Romain BERNARD <romain.bernard@uca.fr>
Date: Thu, 20 Jun 2024 16:58:07 +0200
Subject: [PATCH 119/327] to_string function for easier info logging in tests

---
 src/routes/vehicle/BestRequestInsertion.h | 6 ++++++
 1 file changed, 6 insertions(+)

diff --git a/src/routes/vehicle/BestRequestInsertion.h b/src/routes/vehicle/BestRequestInsertion.h
index 232421d..1af540c 100644
--- a/src/routes/vehicle/BestRequestInsertion.h
+++ b/src/routes/vehicle/BestRequestInsertion.h
@@ -59,6 +59,12 @@ public:
     std::partial_ordering operator<=>(const BestRequestInsertion &rhs) const {
         return _score <=> rhs._score;
     }
+
+    std::string to_string() {
+        return "Insertion points (Origin:" + _originInsertionKP->to_string()
+        + "; Destination:" + _destinationInsertionKP->to_string()
+        + ") score = " + std::to_string(_score);
+    }
 };
 
 
-- 
GitLab


From bf8c843e93242748d363b3bc43ffb878fedc63f1 Mon Sep 17 00:00:00 2001
From: Romain BERNARD <romain.bernard@uca.fr>
Date: Thu, 20 Jun 2024 17:07:03 +0200
Subject: [PATCH 120/327] add best insertions function with neighbour
 feasibility check function (TODO: test perfs wrt no feasibility checks)

---
 src/routes/vehicle/SAEVRoute.cpp | 35 +++++++++++++++++++++++++++++++-
 src/routes/vehicle/SAEVRoute.h   |  1 +
 2 files changed, 35 insertions(+), 1 deletion(-)

diff --git a/src/routes/vehicle/SAEVRoute.cpp b/src/routes/vehicle/SAEVRoute.cpp
index 7d15347..d7f10ad 100644
--- a/src/routes/vehicle/SAEVRoute.cpp
+++ b/src/routes/vehicle/SAEVRoute.cpp
@@ -358,7 +358,7 @@ bool SAEVRoute::checkRouteTimeWindows(size_t vehicleId) {
     return true;
 }
 
-/**
+/** TODO: move to BestInsertionQueue class with a route parameter ?
  * Initializes a BestInsertionQueue to guide the best insertion heuristic
  * @param requestId
  * @param vehicleId
@@ -388,6 +388,39 @@ BestInsertionQueue SAEVRoute::getBestInsertionsQueue(size_t requestId, size_t ve
     return bestInsertionQueue;
 }
 
+/** TODO: move to BestInsertionQueue class with a route parameter ?
+ * Initializes a BestInsertionQueue to guide the best insertion heuristic while checking neighbouring TW checks
+ * @param requestId
+ * @param vehicleId
+ * @return
+ */
+ BestInsertionQueue SAEVRoute::getBestFeasibleInsertionsQueue(size_t requestId, size_t vehicleId) {
+    BestInsertionQueue bestInsertionQueue(requestId, vehicleId, _nbRequest^2);
+
+    //Init variables used during iteration
+    double score;
+    SAEVKeyPoint * originInsertionKeyPoint = &getOriginDepot(vehicleId);
+    SAEVKeyPoint * destinationInsertionKeyPoint = originInsertionKeyPoint;
+
+    //iterate over possible origin/destination pairs for the given vehicle
+    while(originInsertionKeyPoint->getSuccessor() != nullptr) {
+        while(destinationInsertionKeyPoint->getSuccessor() != nullptr) {
+            if(doNeighbouringTWChecks(requestId, getRequestOriginIdx(requestId), getRequestDestinationIdx(requestId),
+                                      originInsertionKeyPoint, destinationInsertionKeyPoint)) {
+                score = getDetourScore(requestId, *originInsertionKeyPoint, *destinationInsertionKeyPoint);
+                bestInsertionQueue.emplace(originInsertionKeyPoint, destinationInsertionKeyPoint, score);
+                destinationInsertionKeyPoint = destinationInsertionKeyPoint->getSuccessor();
+            }
+        }
+
+        //Iterate over possible origins and reset destination to being the same point as the origin
+        originInsertionKeyPoint = originInsertionKeyPoint->getSuccessor();
+        destinationInsertionKeyPoint = originInsertionKeyPoint;
+    }
+
+    return bestInsertionQueue;
+}
+
 void SAEVRoute::addRequestWeightToRoute(size_t requestId) {
     SAEVKeyPoint* currentKP = &getOrigin(requestId);
     int requestWeight = currentKP->getRequest()->getWeight();
diff --git a/src/routes/vehicle/SAEVRoute.h b/src/routes/vehicle/SAEVRoute.h
index 64be3c1..59232e5 100644
--- a/src/routes/vehicle/SAEVRoute.h
+++ b/src/routes/vehicle/SAEVRoute.h
@@ -109,6 +109,7 @@ public:
     double getDetourScore(const size_t requestId, const SAEVKeyPoint &originRequestPredecessorKP, const SAEVKeyPoint &destinationRequestPredecessorKP);
 
     BestInsertionQueue getBestInsertionsQueue(size_t requestId, size_t vehicleId);
+    BestInsertionQueue getBestFeasibleInsertionsQueue(size_t requestId, size_t vehicleId);
 
     SAEVKeyPoint& getOrigin(const size_t requestId) { return _route.at(requestId * 2);}
     SAEVKeyPoint& getDestination(const size_t requestId) { return _route.at(requestId * 2 + 1);}
-- 
GitLab


From 9bc0f8c6d0076b09c23b3a66c62ebfb68532477b Mon Sep 17 00:00:00 2001
From: Romain BERNARD <romain.bernard@uca.fr>
Date: Thu, 20 Jun 2024 17:10:38 +0200
Subject: [PATCH 121/327] add best insertion heuristic functions

---
 CMakeLists.txt                                |  2 +
 .../Heuristics/BestInsertionHeuristic.cpp     | 42 +++++++++++++++++++
 .../DARP/Heuristics/BestInsertionHeuristic.h  | 35 ++++++++++++++++
 3 files changed, 79 insertions(+)
 create mode 100644 src/algorithm/DARP/Heuristics/BestInsertionHeuristic.cpp
 create mode 100644 src/algorithm/DARP/Heuristics/BestInsertionHeuristic.h

diff --git a/CMakeLists.txt b/CMakeLists.txt
index b279b6e..d6e9993 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -113,6 +113,8 @@ add_executable(GraphGeneration
         "src/utils/Instance Generation/Graph/OSRMGraphGenerator.h"
         "src/utils/Instance Generation/Graph/GraphGenerator.h"
         "src/utils/Instance Generation/Graph/PTLineGenerationParameters.h"
+        src/algorithm/DARP/Heuristics/BestInsertionHeuristic.cpp
+        src/algorithm/DARP/Heuristics/BestInsertionHeuristic.h
 )
 
 target_include_directories(GreedyAlgorithm PRIVATE ${PYTHON_INCLUDE_DIRS})
diff --git a/src/algorithm/DARP/Heuristics/BestInsertionHeuristic.cpp b/src/algorithm/DARP/Heuristics/BestInsertionHeuristic.cpp
new file mode 100644
index 0000000..8352a77
--- /dev/null
+++ b/src/algorithm/DARP/Heuristics/BestInsertionHeuristic.cpp
@@ -0,0 +1,42 @@
+//
+// Created by romain on 20/06/24.
+//
+
+#include "BestInsertionHeuristic.h"
+
+#ifdef DEBUG_TRANSIT_PRECOMPUTE
+#include <iostream>
+#define DEBUG_MSG(str) do { std::cout << str << std::endl; } while( false )
+#else
+#define DEBUG_MSG(str) do { } while ( false )
+#endif
+
+bool BestInsertionHeuristic::tryVehicleBestInsertion(size_t requestId, size_t vehicleId, SAEVRoute& route) {
+    BestInsertionQueue bestInsertionsQueue = route.getBestFeasibleInsertionsQueue(requestId, vehicleId); //TODO: check perfs between BestInsertionsQueue vs BestFeasibleInsertionsQueue
+    bool bestInsertionFound = false;
+    BestRequestInsertion currentBestInsertion;
+
+    while(!bestInsertionsQueue.empty() && !bestInsertionFound) {
+        currentBestInsertion = bestInsertionsQueue.topAndPop();
+        SAEVRouteChangelist lastInsertionChangelist = route.tryAddRequest(requestId,
+                                                                          *currentBestInsertion.getOriginInsertionKp(),
+                                                                          *currentBestInsertion.getDestinationInsertionKp());
+        //If insertion worked, signal it, otherwise revert changes
+        if(lastInsertionChangelist.getStatus() == SAEVRouteChangelist::InsertionStatus::SUCCESS) {
+            DEBUG_MSG("Best valid insertion found !\n\t" + currentBestInsertion.to_string());
+            bestInsertionFound = true;
+        } else {
+            lastInsertionChangelist.revertChanges();
+        }
+    }
+    return bestInsertionFound;
+}
+
+size_t BestInsertionHeuristic::doRouteBestInsertion(size_t requestId, SAEVRoute route) {
+    size_t vehicleId = 0;
+    bool insertionSuccess{false};
+    while(vehicleId <= route.getLastActiveVehicleId() + 1 && !insertionSuccess) {
+        insertionSuccess = tryVehicleBestInsertion(requestId, vehicleId, route);
+    }
+    return vehicleId;
+}
diff --git a/src/algorithm/DARP/Heuristics/BestInsertionHeuristic.h b/src/algorithm/DARP/Heuristics/BestInsertionHeuristic.h
new file mode 100644
index 0000000..2dff9d6
--- /dev/null
+++ b/src/algorithm/DARP/Heuristics/BestInsertionHeuristic.h
@@ -0,0 +1,35 @@
+//
+// Created by romain on 20/06/24.
+//
+
+#ifndef GREEDYALGORITHM_BESTINSERTIONHEURISTIC_H
+#define GREEDYALGORITHM_BESTINSERTIONHEURISTIC_H
+
+
+#include <cstdlib>
+#include "../../../routes/vehicle/SAEVRoute.h"
+
+class BestInsertionHeuristic {
+    /**
+     * Automatically inserts the given request in a vehicle, potentially creating a new one if no active vehicle works
+     * @param requestId ID of the request to insert in the route
+     * @param route the route structure in which the request will be inserted
+     * @return ID of the vehicle in which the request has been
+     */
+    static size_t doRouteBestInsertion(size_t requestId, SAEVRoute route);
+    /**
+     * Iteratively tests best insertions wrt scoring function (detour) in the given vehicle and route
+     * @param requestId ID of the request to insert in the vehicle
+     * @param requestId ID of the vehicle in which to insert the vehicle
+     * @param route
+     * @return true iff the request was inserted in the vehicle, false if no best insertion yielded a possible insertion
+     */
+    static bool tryVehicleBestInsertion(size_t requestId, size_t vehicleId, SAEVRoute& route);
+
+    /** TODO Implement those to prevent trying every single best insertion
+    static bool vehicle_K_BestInsertion(size_t requestId, size_t vehicleId, SAEVRoute route);
+    static bool vehicleScoreThresholdBestInsertion(size_t requestId, size_t vehicleId, SAEVRoute& route); */
+};
+
+
+#endif //GREEDYALGORITHM_BESTINSERTIONHEURISTIC_H
-- 
GitLab


From 4a12795de71676643f2b296440d7749aba55d4a9 Mon Sep 17 00:00:00 2001
From: Romain BERNARD <romain.bernard@uca.fr>
Date: Thu, 20 Jun 2024 17:35:52 +0200
Subject: [PATCH 122/327] refactor function name to be clearer

---
 src/algorithm/DARP/Heuristics/BestInsertionHeuristic.cpp | 2 +-
 src/algorithm/DARP/Heuristics/BestInsertionHeuristic.h   | 2 +-
 2 files changed, 2 insertions(+), 2 deletions(-)

diff --git a/src/algorithm/DARP/Heuristics/BestInsertionHeuristic.cpp b/src/algorithm/DARP/Heuristics/BestInsertionHeuristic.cpp
index 8352a77..9293f0d 100644
--- a/src/algorithm/DARP/Heuristics/BestInsertionHeuristic.cpp
+++ b/src/algorithm/DARP/Heuristics/BestInsertionHeuristic.cpp
@@ -32,7 +32,7 @@ bool BestInsertionHeuristic::tryVehicleBestInsertion(size_t requestId, size_t ve
     return bestInsertionFound;
 }
 
-size_t BestInsertionHeuristic::doRouteBestInsertion(size_t requestId, SAEVRoute route) {
+size_t BestInsertionHeuristic::doBestRequestInsertionForRoute(size_t requestId, SAEVRoute route) {
     size_t vehicleId = 0;
     bool insertionSuccess{false};
     while(vehicleId <= route.getLastActiveVehicleId() + 1 && !insertionSuccess) {
diff --git a/src/algorithm/DARP/Heuristics/BestInsertionHeuristic.h b/src/algorithm/DARP/Heuristics/BestInsertionHeuristic.h
index 2dff9d6..04641b0 100644
--- a/src/algorithm/DARP/Heuristics/BestInsertionHeuristic.h
+++ b/src/algorithm/DARP/Heuristics/BestInsertionHeuristic.h
@@ -16,7 +16,7 @@ class BestInsertionHeuristic {
      * @param route the route structure in which the request will be inserted
      * @return ID of the vehicle in which the request has been
      */
-    static size_t doRouteBestInsertion(size_t requestId, SAEVRoute route);
+    static size_t doBestRequestInsertionForRoute(size_t requestId, SAEVRoute route);
     /**
      * Iteratively tests best insertions wrt scoring function (detour) in the given vehicle and route
      * @param requestId ID of the request to insert in the vehicle
-- 
GitLab


From 815eef9f956387a26f8276d7ffa425d41a9cf377 Mon Sep 17 00:00:00 2001
From: Romain BERNARD <romain.bernard@uca.fr>
Date: Thu, 20 Jun 2024 17:40:09 +0200
Subject: [PATCH 123/327] update active vehicle id after insertion TODO: find a
 more elegant way to do this, because it makes the Heuristic(s) responsible
 for updating a member of SAEVRoute I could make it a member of
 BestInsertionHeuristic but then that means we have to instanciate an object
 to use the algorithms which seems inappropriate. Unless maybe if Heuristics
 classes ends up being delegate members of another class to allow
 heuristics/algorithms change via this delegate

---
 src/algorithm/DARP/Heuristics/BestInsertionHeuristic.cpp | 8 ++++++++
 src/routes/vehicle/SAEVRoute.h                           | 4 ++++
 2 files changed, 12 insertions(+)

diff --git a/src/algorithm/DARP/Heuristics/BestInsertionHeuristic.cpp b/src/algorithm/DARP/Heuristics/BestInsertionHeuristic.cpp
index 9293f0d..094abcb 100644
--- a/src/algorithm/DARP/Heuristics/BestInsertionHeuristic.cpp
+++ b/src/algorithm/DARP/Heuristics/BestInsertionHeuristic.cpp
@@ -35,8 +35,16 @@ bool BestInsertionHeuristic::tryVehicleBestInsertion(size_t requestId, size_t ve
 size_t BestInsertionHeuristic::doBestRequestInsertionForRoute(size_t requestId, SAEVRoute route) {
     size_t vehicleId = 0;
     bool insertionSuccess{false};
+    //Iteratively try inserting in every active vehicle and the first inactive vehicle
     while(vehicleId <= route.getLastActiveVehicleId() + 1 && !insertionSuccess) {
         insertionSuccess = tryVehicleBestInsertion(requestId, vehicleId, route);
     }
+
+    //Update last active vehicle ID
+    if(vehicleId > route.getLastActiveVehicleId()) {
+        route.setLastActiveVehicleId(vehicleId);
+        DEBUG_MSG("NEW VEHICLE CREATED, ID :" + std::to_string(vehicleId));
+    }
+
     return vehicleId;
 }
diff --git a/src/routes/vehicle/SAEVRoute.h b/src/routes/vehicle/SAEVRoute.h
index 59232e5..394ed0f 100644
--- a/src/routes/vehicle/SAEVRoute.h
+++ b/src/routes/vehicle/SAEVRoute.h
@@ -18,6 +18,7 @@ private:
     size_t _nbRequest;
     const Graph* _graph;
     const std::vector<Request>* _requestList;
+    size_t _lastActiveVehicleId{0};
 public:
     SAEVRoute() = default;
     /**
@@ -123,6 +124,9 @@ public:
     [[nodiscard]] size_t getOriginDepotIdx(const size_t vehicleId) const { return _nbRequest*2 + vehicleId*2;}
     [[nodiscard]] size_t getDestinationDepotIdx(const size_t vehicleId) const { return _nbRequest*2 + vehicleId*2 + 1;}
 
+    [[nodiscard]] size_t getLastActiveVehicleId() const { return _lastActiveVehicleId; }
+    void setLastActiveVehicleId(size_t lastActiveVehicleId) { _lastActiveVehicleId = lastActiveVehicleId; }
+
     /**
      * Verifies that time windows have been properly propagated for a given vehicle's route
      * @param vehicleId
-- 
GitLab


From a085e1aff7d55355cc5ca268f8e9de37fa394a89 Mon Sep 17 00:00:00 2001
From: Romain BERNARD <romain.bernard@uca.fr>
Date: Fri, 21 Jun 2024 10:54:24 +0200
Subject: [PATCH 124/327] make methods public

---
 src/algorithm/DARP/Heuristics/BestInsertionHeuristic.h | 1 +
 1 file changed, 1 insertion(+)

diff --git a/src/algorithm/DARP/Heuristics/BestInsertionHeuristic.h b/src/algorithm/DARP/Heuristics/BestInsertionHeuristic.h
index 04641b0..657a978 100644
--- a/src/algorithm/DARP/Heuristics/BestInsertionHeuristic.h
+++ b/src/algorithm/DARP/Heuristics/BestInsertionHeuristic.h
@@ -10,6 +10,7 @@
 #include "../../../routes/vehicle/SAEVRoute.h"
 
 class BestInsertionHeuristic {
+public:
     /**
      * Automatically inserts the given request in a vehicle, potentially creating a new one if no active vehicle works
      * @param requestId ID of the request to insert in the route
-- 
GitLab


From 9b42dbf334b6e59dcc3207feceaab77a02155cd2 Mon Sep 17 00:00:00 2001
From: Romain BERNARD <romain.bernard@uca.fr>
Date: Fri, 21 Jun 2024 16:24:38 +0200
Subject: [PATCH 125/327] iterate on vehicles properly

---
 src/algorithm/DARP/Heuristics/BestInsertionHeuristic.cpp | 1 +
 1 file changed, 1 insertion(+)

diff --git a/src/algorithm/DARP/Heuristics/BestInsertionHeuristic.cpp b/src/algorithm/DARP/Heuristics/BestInsertionHeuristic.cpp
index 094abcb..1656b2a 100644
--- a/src/algorithm/DARP/Heuristics/BestInsertionHeuristic.cpp
+++ b/src/algorithm/DARP/Heuristics/BestInsertionHeuristic.cpp
@@ -38,6 +38,7 @@ size_t BestInsertionHeuristic::doBestRequestInsertionForRoute(size_t requestId,
     //Iteratively try inserting in every active vehicle and the first inactive vehicle
     while(vehicleId <= route.getLastActiveVehicleId() + 1 && !insertionSuccess) {
         insertionSuccess = tryVehicleBestInsertion(requestId, vehicleId, route);
+        ++vehicleId;
     }
 
     //Update last active vehicle ID
-- 
GitLab


From 3f57879e91e99a83af41896ff6114498c1d8dae2 Mon Sep 17 00:00:00 2001
From: Romain BERNARD <romain.bernard@uca.fr>
Date: Fri, 21 Jun 2024 16:29:38 +0200
Subject: [PATCH 126/327] properly set status on insertion success

---
 src/routes/vehicle/SAEVRoute.cpp | 1 +
 1 file changed, 1 insertion(+)

diff --git a/src/routes/vehicle/SAEVRoute.cpp b/src/routes/vehicle/SAEVRoute.cpp
index d7f10ad..95d9b8a 100644
--- a/src/routes/vehicle/SAEVRoute.cpp
+++ b/src/routes/vehicle/SAEVRoute.cpp
@@ -278,6 +278,7 @@ SAEVRouteChangelist SAEVRoute::insertRequestWithPropagation(const size_t request
         }
     }
 
+    changelist.setStatus(SAEVRouteChangelist::InsertionStatus::SUCCESS);
     changelist.setScore(getDetourScore(requestId, originRequestPredecessorKP, destinationRequestPredecessorKP));
     return changelist;
 }
-- 
GitLab


From d9945f01c711ad3c3b7617b278176787e8190553 Mon Sep 17 00:00:00 2001
From: Romain BERNARD <romain.bernard@uca.fr>
Date: Fri, 21 Jun 2024 16:31:08 +0200
Subject: [PATCH 127/327] add debug messages

---
 src/algorithm/DARP/Heuristics/BestInsertionHeuristic.cpp | 5 +++--
 1 file changed, 3 insertions(+), 2 deletions(-)

diff --git a/src/algorithm/DARP/Heuristics/BestInsertionHeuristic.cpp b/src/algorithm/DARP/Heuristics/BestInsertionHeuristic.cpp
index 1656b2a..b96e273 100644
--- a/src/algorithm/DARP/Heuristics/BestInsertionHeuristic.cpp
+++ b/src/algorithm/DARP/Heuristics/BestInsertionHeuristic.cpp
@@ -15,7 +15,7 @@ bool BestInsertionHeuristic::tryVehicleBestInsertion(size_t requestId, size_t ve
     BestInsertionQueue bestInsertionsQueue = route.getBestFeasibleInsertionsQueue(requestId, vehicleId); //TODO: check perfs between BestInsertionsQueue vs BestFeasibleInsertionsQueue
     bool bestInsertionFound = false;
     BestRequestInsertion currentBestInsertion;
-
+    DEBUG_MSG("Trying to insert request " + std::to_string(requestId) + " in vehicle " + std::to_string(vehicleId));
     while(!bestInsertionsQueue.empty() && !bestInsertionFound) {
         currentBestInsertion = bestInsertionsQueue.topAndPop();
         SAEVRouteChangelist lastInsertionChangelist = route.tryAddRequest(requestId,
@@ -23,9 +23,10 @@ bool BestInsertionHeuristic::tryVehicleBestInsertion(size_t requestId, size_t ve
                                                                           *currentBestInsertion.getDestinationInsertionKp());
         //If insertion worked, signal it, otherwise revert changes
         if(lastInsertionChangelist.getStatus() == SAEVRouteChangelist::InsertionStatus::SUCCESS) {
-            DEBUG_MSG("Best valid insertion found !\n\t" + currentBestInsertion.to_string());
+            DEBUG_MSG("\tBest valid insertion found !\n\t\t" + currentBestInsertion.to_string());
             bestInsertionFound = true;
         } else {
+            DEBUG_MSG("Failed to insert best insertion " + currentBestInsertion.to_string());
             lastInsertionChangelist.revertChanges();
         }
     }
-- 
GitLab


From 8366e1136f7178d44c83abc7e477e698322761cd Mon Sep 17 00:00:00 2001
From: Romain BERNARD <romain.bernard@uca.fr>
Date: Fri, 21 Jun 2024 16:31:31 +0200
Subject: [PATCH 128/327] add best insertion heuristic tests

---
 test/CMakeLists.txt                      |  2 +
 test/src/BestInsertionHeuristicDebug.cpp | 67 ++++++++++++++++++++----
 2 files changed, 59 insertions(+), 10 deletions(-)

diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt
index cc5c263..59926f7 100644
--- a/test/CMakeLists.txt
+++ b/test/CMakeLists.txt
@@ -102,6 +102,8 @@ add_executable(BestInsertionHeuristic_DEB
         ../src/routes/requests/RequestRoute.h
         ../src/routes/vehicle/BestRequestInsertion.h
         ../src/routes/vehicle/BestInsertionQueue.h
+        ../src/algorithm/DARP/Heuristics/BestInsertionHeuristic.cpp
+        ../src/algorithm/DARP/Heuristics/BestInsertionHeuristic.h
 )
 
 target_link_libraries(Line_UT gtest gtest_main)
diff --git a/test/src/BestInsertionHeuristicDebug.cpp b/test/src/BestInsertionHeuristicDebug.cpp
index 4e20b2d..3d7c600 100644
--- a/test/src/BestInsertionHeuristicDebug.cpp
+++ b/test/src/BestInsertionHeuristicDebug.cpp
@@ -8,6 +8,7 @@
 #include "../../src/ShortestPath/Transit/TransitShortestPathPrecompute.h"
 #include "../../src/instance/Instance.h"
 #include "../../src/routes/vehicle/SAEVRoute.h"
+#include "../../src/algorithm/DARP/Heuristics/BestInsertionHeuristic.h"
 
 TEST(BestInsertionHeuristicDebug, DebugBaseInstance) {
     std::string instancesPath = "../../resources/test/instances/Constraint Propagation/";
@@ -42,7 +43,7 @@ TEST(BestInsertionHeuristicDebug, DebugBaseInstance) {
     req0Changelist.revertChanges();
 }
 
-TEST(BestInsertionHeuristicDebug, DebugInstanceAlain) {
+TEST(BestInsertionQueueDebug, DebugInstanceAlain) {
     std::string instancesPath = "../../resources/test/instances/Constraint Propagation/";
     std::string instanceFolder = "Instance_Alain_140624/";
     std::string graphDatFile = "graph2.dat";
@@ -59,22 +60,68 @@ TEST(BestInsertionHeuristicDebug, DebugInstanceAlain) {
     //Vehicle 1 insertions
     BestInsertionQueue biQueue = routesContainer.getBestInsertionsQueue(0,0);
     routesContainer.tryAddRequest(0,routesContainer.getOriginDepot(0),routesContainer.getOriginDepot(0));
-    biQueue = routesContainer.getBestInsertionsQueue(1,0);
+    biQueue = routesContainer.getBestFeasibleInsertionsQueue(1,0);
     routesContainer.tryAddRequest(1,routesContainer.getOrigin(0),routesContainer.getOrigin(0));
-    biQueue = routesContainer.getBestInsertionsQueue(2,0);
+    biQueue = routesContainer.getBestFeasibleInsertionsQueue(2,0);
     SAEVRouteChangelist cl = routesContainer.tryAddRequest(2,routesContainer.getOrigin(1),routesContainer.getDestination(1));
-    biQueue = routesContainer.getBestInsertionsQueue(3,0);
+    biQueue = routesContainer.getBestFeasibleInsertionsQueue(3,0);
 
     //Vehicle 2 insertions
-    biQueue = routesContainer.getBestInsertionsQueue(5,1);
+    biQueue = routesContainer.getBestFeasibleInsertionsQueue(5,1);
     routesContainer.tryAddRequest(5,routesContainer.getOriginDepot(1),routesContainer.getOriginDepot(1));
-    biQueue = routesContainer.getBestInsertionsQueue(4,1);
+    biQueue = routesContainer.getBestFeasibleInsertionsQueue(4,1);
     routesContainer.tryAddRequest(4,routesContainer.getOriginDepot(1),routesContainer.getDestination(5));
-    biQueue = routesContainer.getBestInsertionsQueue(3,1);
+    biQueue = routesContainer.getBestFeasibleInsertionsQueue(3,1);
     routesContainer.tryAddRequest(3,routesContainer.getOriginDepot(1),routesContainer.getOrigin(4));
-    biQueue = routesContainer.getBestInsertionsQueue(0,1);
-    biQueue = routesContainer.getBestInsertionsQueue(1,1);
-    biQueue = routesContainer.getBestInsertionsQueue(2,1);
+    biQueue = routesContainer.getBestFeasibleInsertionsQueue(0,1);
+    biQueue = routesContainer.getBestFeasibleInsertionsQueue(1,1);
+    biQueue = routesContainer.getBestFeasibleInsertionsQueue(2,1);
+}
+
+TEST(BestInsertionPerVehicleHeuristicDebug, DebugInstanceAlain) {
+    std::string instancesPath = "../../resources/test/instances/Constraint Propagation/";
+    std::string instanceFolder = "Instance_Alain_140624/";
+    std::string graphDatFile = "graph2.dat";
+    std::string requestsDatFile = "requests.dat";
+
+    //Parse graph
+    Graph graphFromSingleFile(instancesPath + instanceFolder + graphDatFile);
+    std::vector<Request> requests = Request::getRequestsFromFile(instancesPath + instanceFolder + requestsDatFile, graphFromSingleFile);
+
+    //Init instance
+    Instance instance(requests,graphFromSingleFile,4);
+    SAEVRoute routesContainer(graphFromSingleFile, requests);
+
+    //Vehicle 0 insertions (0,1,2)
+    BestInsertionHeuristic::tryVehicleBestInsertion(0, 0, routesContainer);
+    BestInsertionHeuristic::tryVehicleBestInsertion(1, 0, routesContainer);
+    BestInsertionHeuristic::tryVehicleBestInsertion(2, 0, routesContainer);
+    //Vehicle 1 insertions (3,4,5)
+    BestInsertionHeuristic::tryVehicleBestInsertion(3, 1, routesContainer);
+    BestInsertionHeuristic::tryVehicleBestInsertion(4, 1, routesContainer);
+    BestInsertionHeuristic::tryVehicleBestInsertion(5, 1, routesContainer);
+}
+
+TEST(BestInsertionHeuristicDebug, DebugInstanceAlain) {
+    std::string instancesPath = "../../resources/test/instances/Constraint Propagation/";
+    std::string instanceFolder = "Instance_Alain_140624/";
+    std::string graphDatFile = "graph2.dat";
+    std::string requestsDatFile = "requests.dat";
+
+    //Parse graph
+    Graph graphFromSingleFile(instancesPath + instanceFolder + graphDatFile);
+    std::vector<Request> requests = Request::getRequestsFromFile(instancesPath + instanceFolder + requestsDatFile, graphFromSingleFile);
+
+    //Init instance
+    Instance instance(requests,graphFromSingleFile,4);
+    SAEVRoute routesContainer(graphFromSingleFile, requests);
+
+    BestInsertionHeuristic::doBestRequestInsertionForRoute(0, routesContainer);
+    BestInsertionHeuristic::doBestRequestInsertionForRoute(1, routesContainer);
+    BestInsertionHeuristic::doBestRequestInsertionForRoute(2, routesContainer);
+    BestInsertionHeuristic::doBestRequestInsertionForRoute(3, routesContainer);
+    BestInsertionHeuristic::doBestRequestInsertionForRoute(4, routesContainer);
+    BestInsertionHeuristic::doBestRequestInsertionForRoute(5, routesContainer);
 }
 
 int main(int argc, char* argv[]) {
-- 
GitLab


From aabba5f7c761f9193b68d19ed4fc4de2affd4d2c Mon Sep 17 00:00:00 2001
From: Romain BERNARD <romain.bernard@uca.fr>
Date: Mon, 24 Jun 2024 10:11:00 +0200
Subject: [PATCH 129/327] fix a silly iteration issue bug

---
 src/routes/vehicle/SAEVRoute.cpp | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/src/routes/vehicle/SAEVRoute.cpp b/src/routes/vehicle/SAEVRoute.cpp
index 95d9b8a..0f194d7 100644
--- a/src/routes/vehicle/SAEVRoute.cpp
+++ b/src/routes/vehicle/SAEVRoute.cpp
@@ -410,8 +410,8 @@ BestInsertionQueue SAEVRoute::getBestInsertionsQueue(size_t requestId, size_t ve
                                       originInsertionKeyPoint, destinationInsertionKeyPoint)) {
                 score = getDetourScore(requestId, *originInsertionKeyPoint, *destinationInsertionKeyPoint);
                 bestInsertionQueue.emplace(originInsertionKeyPoint, destinationInsertionKeyPoint, score);
-                destinationInsertionKeyPoint = destinationInsertionKeyPoint->getSuccessor();
             }
+            destinationInsertionKeyPoint = destinationInsertionKeyPoint->getSuccessor();
         }
 
         //Iterate over possible origins and reset destination to being the same point as the origin
-- 
GitLab


From 0bda626388906bc9b6e952ba0ef7d3ea1ee91115 Mon Sep 17 00:00:00 2001
From: Romain BERNARD <romain.bernard@uca.fr>
Date: Mon, 24 Jun 2024 13:46:10 +0200
Subject: [PATCH 130/327] only increment vehicle id if insertion was a success
 (introduces side effect in while condition)

---
 src/algorithm/DARP/Heuristics/BestInsertionHeuristic.cpp | 5 ++---
 1 file changed, 2 insertions(+), 3 deletions(-)

diff --git a/src/algorithm/DARP/Heuristics/BestInsertionHeuristic.cpp b/src/algorithm/DARP/Heuristics/BestInsertionHeuristic.cpp
index b96e273..7bcdf59 100644
--- a/src/algorithm/DARP/Heuristics/BestInsertionHeuristic.cpp
+++ b/src/algorithm/DARP/Heuristics/BestInsertionHeuristic.cpp
@@ -37,10 +37,9 @@ size_t BestInsertionHeuristic::doBestRequestInsertionForRoute(size_t requestId,
     size_t vehicleId = 0;
     bool insertionSuccess{false};
     //Iteratively try inserting in every active vehicle and the first inactive vehicle
-    while(vehicleId <= route.getLastActiveVehicleId() + 1 && !insertionSuccess) {
+    do {
         insertionSuccess = tryVehicleBestInsertion(requestId, vehicleId, route);
-        ++vehicleId;
-    }
+    } while(!insertionSuccess && ++vehicleId <= route.getLastActiveVehicleId() + 1);
 
     //Update last active vehicle ID
     if(vehicleId > route.getLastActiveVehicleId()) {
-- 
GitLab


From 36c7cf045f526e836adccec097444aecd0f79beb Mon Sep 17 00:00:00 2001
From: Romain BERNARD <romain.bernard@uca.fr>
Date: Mon, 24 Jun 2024 14:30:13 +0200
Subject: [PATCH 131/327] refactors for clarity (and fix heuristic), O/D node
 index were unnecessary in arguments as we have the KPs in

---
 src/routes/vehicle/SAEVRoute.cpp         | 70 +++++++++++++-----------
 src/routes/vehicle/SAEVRoute.h           | 16 ++++--
 test/src/BestInsertionHeuristicDebug.cpp | 12 ++--
 test/src/ConstraintPropagationDebug.cpp  | 12 ++--
 4 files changed, 63 insertions(+), 47 deletions(-)

diff --git a/src/routes/vehicle/SAEVRoute.cpp b/src/routes/vehicle/SAEVRoute.cpp
index 0f194d7..cbc1065 100644
--- a/src/routes/vehicle/SAEVRoute.cpp
+++ b/src/routes/vehicle/SAEVRoute.cpp
@@ -23,8 +23,8 @@ SAEVRoute::SAEVRoute(const Graph& graph, const std::vector<Request>& requestList
         getOrigin(i) = SAEVKeyPoint(graph, requestList.at(i), true); //origin
         getDestination(i) = SAEVKeyPoint(graph, requestList.at(i), false); //destination
         //Link Origins and Destinations
-        getOrigin(i).setCounterpart(&getDestination(i));
-        getDestination(i).setCounterpart(&getOrigin(i));
+        getRequestOrigin(i).setCounterpart(&getRequestDestination(i));
+        getRequestDestination(i).setCounterpart(&getRequestOrigin(i));
 
         //Create depot O/D KP (Upper Bound = nb requests)
         getOriginDepot(i) = SAEVKeyPoint(graph.getDepotNodeIdx()); //start
@@ -38,8 +38,8 @@ SAEVRoute::SAEVRoute(const Graph& graph, const std::vector<Request>& requestList
 }
 
 void SAEVRoute::insertRequest(size_t requestId, SAEVKeyPoint &originRequestPredecessorKP, SAEVKeyPoint &destinationRequestPredecessorKP) {
-    SAEVKeyPoint& originKp = getOrigin(requestId);
-    SAEVKeyPoint& destinationKp = getDestination(requestId);
+    SAEVKeyPoint& originKp = getRequestOrigin(requestId);
+    SAEVKeyPoint& destinationKp = getRequestDestination(requestId);
 
     SAEVKeyPoint *originSuccKp = originRequestPredecessorKP.getSuccessor();
     SAEVKeyPoint *destinationSuccKp = destinationRequestPredecessorKP.getSuccessor();
@@ -75,18 +75,25 @@ void SAEVRoute::removeRequest(size_t requestId) {
     //Before undoing the insertion, update weights on the route
     removeRequestWeightFromRoute(requestId);
 
-    SAEVKeyPoint& originKp = getOrigin(requestId);
-    SAEVKeyPoint& destinationKp = getDestination(requestId);
+    SAEVKeyPoint& originKp = getRequestOrigin(requestId);
+    SAEVKeyPoint& destinationKp = getRequestDestination(requestId);
 
     //get predecessor and successor for request
     SAEVKeyPoint* originPredecessor = originKp.getPredecessor();
-    SAEVKeyPoint* originSuccessor = destinationKp.getSuccessor();
-    SAEVKeyPoint* destinationPredecessor = originKp.getPredecessor();
+    SAEVKeyPoint* originSuccessor = originKp.getSuccessor();
+    SAEVKeyPoint* destinationPredecessor = destinationKp.getPredecessor();
     SAEVKeyPoint* destinationSuccessor = destinationKp.getSuccessor();
 
-    //Link pred and successor from origin and destination
-    originPredecessor->setSuccessor(originSuccessor);
-    destinationPredecessor->setSuccessor(destinationSuccessor);
+    //Link pred and successor from origin and destination (cases differ if O/D are next to each other
+    if(originSuccessor == &destinationKp) {
+        originPredecessor->setSuccessor(destinationSuccessor);
+        destinationSuccessor->setPredecessor(originPredecessor);
+    } else {
+        originPredecessor->setSuccessor(originSuccessor);
+        originSuccessor->setPredecessor(originPredecessor);
+        destinationPredecessor->setSuccessor(destinationSuccessor);
+        destinationSuccessor->setSuccessor(destinationPredecessor);
+    }
 
     //Revert origin/destination key points to their default state
     originKp.setPredecessor(nullptr);
@@ -115,7 +122,7 @@ SAEVRoute::tryAddRequest(const size_t requestId, SAEVKeyPoint &originRequestPred
     } while (currentKP != destinationSuccessor && currentKP != nullptr);
 
     //Do basic checks on neighbouring nodes from our Origin/Destination insertion points
-    bool isValid = doNeighbouringTWChecks(requestId, request->getOriginNodeIndex(), request->getDestinationNodeIndex(), &originRequestPredecessorKP, &destinationRequestPredecessorKP);
+    bool isValid = doNeighbouringTWChecks(requestId, &originRequestPredecessorKP, &destinationRequestPredecessorKP);
 
     if(isValid) {
         return insertRequestWithPropagation(requestId, originRequestPredecessorKP, destinationRequestPredecessorKP);
@@ -126,12 +133,13 @@ SAEVRoute::tryAddRequest(const size_t requestId, SAEVKeyPoint &originRequestPred
 }
 
 bool
-SAEVRoute::doNeighbouringTWChecks(const size_t requestId, const size_t originNodeIndex, const size_t destinationNodeIndex,
-                                  const SAEVKeyPoint *originPredecessor, const SAEVKeyPoint *destinationPredecessor) {
+SAEVRoute::doNeighbouringTWChecks(const size_t requestId, const SAEVKeyPoint *originPredecessor, const SAEVKeyPoint *destinationPredecessor) {
 
-    const SAEVKeyPoint& originKP = getOrigin(requestId);
-    const SAEVKeyPoint& destinationKP = getDestination(requestId);
+    const SAEVKeyPoint& originKP = getRequestOrigin(requestId);
+    const SAEVKeyPoint& destinationKP = getRequestDestination(requestId);
     const SAEVKeyPoint* originSuccessor = originPredecessor->getSuccessor();
+    const size_t originNodeIndex = originKP.getNodeIndex();
+    const size_t destinationNodeIndex = destinationKP.getNodeIndex();
 
     if(originPredecessor != destinationPredecessor)
     {
@@ -181,8 +189,8 @@ SAEVRouteChangelist SAEVRoute::insertRequestWithPropagation(const size_t request
 
     //Initialize bound propagation signal queue (each item signals a modification done on one of a KeyPoint
     std::queue<std::pair<Bound, SAEVKeyPoint *>> boundPropagationQueue{};
-    SAEVKeyPoint * originKP = &getOrigin(requestId);
-    SAEVKeyPoint * destinationKP = &getDestination(requestId);
+    SAEVKeyPoint * originKP = &getRequestOrigin(requestId);
+    SAEVKeyPoint * destinationKP = &getRequestDestination(requestId);
     boundPropagationQueue.emplace(Min, originKP->getPredecessor());
     boundPropagationQueue.emplace(Max, originKP->getSuccessor());
     boundPropagationQueue.emplace(Min, destinationKP->getPredecessor());
@@ -204,7 +212,7 @@ SAEVRouteChangelist SAEVRoute::insertRequestWithPropagation(const size_t request
         auto const& [bound, keyPoint] = boundPropagationQueue.front();
         boundPropagationQueue.pop();
         counterpartKP = keyPoint->getCounterpart();
-        DEBUG_MSG("KP=" + keyPoint->to_string() + "\n");
+//        DEBUG_MSG("KP=" + keyPoint->to_string() + "\n");
         if(bound == Min) {
             successorKP = keyPoint->getSuccessor();
             if(successorKP != nullptr) {
@@ -217,7 +225,7 @@ SAEVRouteChangelist SAEVRoute::insertRequestWithPropagation(const size_t request
                         changelist.setStatus(SAEVRouteChangelist::InsertionStatus::FAILURE_MIN);
                         return changelist;
                     }
-                    DEBUG_MSG("\tMIN Successeur KP=" + successorKP->to_string() + "\n\tModif Min=" + std::to_string(oldValue) + "->" + std::to_string(newValue));
+//                    DEBUG_MSG("\tMIN Successeur KP=" + successorKP->to_string() + "\n\tModif Min=" + std::to_string(oldValue) + "->" + std::to_string(newValue));
                     changelist.emplace_back(*successorKP, Min, newValue - oldValue);
                     successorKP->setMinTw(newValue);
                     boundPropagationQueue.emplace(Min, successorKP);
@@ -234,7 +242,7 @@ SAEVRouteChangelist SAEVRoute::insertRequestWithPropagation(const size_t request
                     changelist.setStatus(SAEVRouteChangelist::InsertionStatus::FAILURE_DELTA_MIN);
                     return changelist;
                 }
-                DEBUG_MSG("\tMIN Counterpart KP=" + counterpartKP->to_string() + "\n\tModif Min=" + std::to_string(oldValue) + "->" + std::to_string(newValue));
+//                DEBUG_MSG("\tMIN Counterpart KP=" + counterpartKP->to_string() + "\n\tModif Min=" + std::to_string(oldValue) + "->" + std::to_string(newValue));
                 changelist.emplace_back(*counterpartKP, Min, newValue - oldValue);
                 counterpartKP->setMinTw(newValue);
                 boundPropagationQueue.emplace(Min, counterpartKP);
@@ -253,7 +261,7 @@ SAEVRouteChangelist SAEVRoute::insertRequestWithPropagation(const size_t request
                         changelist.setStatus(SAEVRouteChangelist::InsertionStatus::FAILURE_MAX);
                         return changelist;
                     }
-                    DEBUG_MSG("\tMAX Predecessor KP=" + predecessorKP->to_string() + "\n\tModif Max=" + std::to_string(oldValue) + "->" + std::to_string(newValue));
+//                    DEBUG_MSG("\tMAX Predecessor KP=" + predecessorKP->to_string() + "\n\tModif Max=" + std::to_string(oldValue) + "->" + std::to_string(newValue));
                     changelist.emplace_back(*predecessorKP, Max, newValue - oldValue);
                     predecessorKP->setMaxTw(newValue);
                     boundPropagationQueue.emplace(Max, predecessorKP);
@@ -273,11 +281,12 @@ SAEVRouteChangelist SAEVRoute::insertRequestWithPropagation(const size_t request
                 changelist.emplace_back(*counterpartKP, Max, oldValue - newValue);
                 counterpartKP->setMaxTw(newValue);
                 boundPropagationQueue.emplace(Max, counterpartKP);
-                DEBUG_MSG("\tMAX Destination KP=" + counterpartKP->to_string() + "\n\tModif Max=" + std::to_string(oldValue) + "->" + std::to_string(newValue));
+//                DEBUG_MSG("\tMAX Destination KP=" + counterpartKP->to_string() + "\n\tModif Max=" + std::to_string(oldValue) + "->" + std::to_string(newValue));
             }
         }
     }
 
+    DEBUG_MSG("INSERTION SUCCESS");
     changelist.setStatus(SAEVRouteChangelist::InsertionStatus::SUCCESS);
     changelist.setScore(getDetourScore(requestId, originRequestPredecessorKP, destinationRequestPredecessorKP));
     return changelist;
@@ -286,8 +295,8 @@ SAEVRouteChangelist SAEVRoute::insertRequestWithPropagation(const size_t request
 double SAEVRoute::getDetourScore(const size_t requestId, const SAEVKeyPoint &originRequestPredecessorKP,
                                  const SAEVKeyPoint &destinationRequestPredecessorKP) {
     double score;
-    const SAEVKeyPoint& originKP = getOrigin(requestId);
-    const SAEVKeyPoint& destinationKP = getDestination(requestId);
+    const SAEVKeyPoint& originKP = getRequestOrigin(requestId);
+    const SAEVKeyPoint& destinationKP = getRequestDestination(requestId);
     const SAEVKeyPoint* originSuccKP = originRequestPredecessorKP.getSuccessor();
     const SAEVKeyPoint* destinationSuccKP = destinationRequestPredecessorKP.getSuccessor();
 
@@ -406,8 +415,7 @@ BestInsertionQueue SAEVRoute::getBestInsertionsQueue(size_t requestId, size_t ve
     //iterate over possible origin/destination pairs for the given vehicle
     while(originInsertionKeyPoint->getSuccessor() != nullptr) {
         while(destinationInsertionKeyPoint->getSuccessor() != nullptr) {
-            if(doNeighbouringTWChecks(requestId, getRequestOriginIdx(requestId), getRequestDestinationIdx(requestId),
-                                      originInsertionKeyPoint, destinationInsertionKeyPoint)) {
+            if(doNeighbouringTWChecks(requestId,originInsertionKeyPoint, destinationInsertionKeyPoint)) {
                 score = getDetourScore(requestId, *originInsertionKeyPoint, *destinationInsertionKeyPoint);
                 bestInsertionQueue.emplace(originInsertionKeyPoint, destinationInsertionKeyPoint, score);
             }
@@ -423,24 +431,24 @@ BestInsertionQueue SAEVRoute::getBestInsertionsQueue(size_t requestId, size_t ve
 }
 
 void SAEVRoute::addRequestWeightToRoute(size_t requestId) {
-    SAEVKeyPoint* currentKP = &getOrigin(requestId);
+    SAEVKeyPoint* currentKP = &getRequestOrigin(requestId);
     int requestWeight = currentKP->getRequest()->getWeight();
     currentKP->setCurrentOccupation(currentKP->getPredecessor()->getCurrentOccupation() + requestWeight); //O.Weight = Prec(O).Weight + R.Weight (request enters the vehicle=)
     do {
         currentKP = currentKP->getSuccessor();
         currentKP->setCurrentOccupation(currentKP->getCurrentOccupation() + requestWeight);
-    } while (currentKP != &getDestination(requestId));
+    } while (currentKP != &getRequestDestination(requestId));
     currentKP->setCurrentOccupation(currentKP->getPredecessor()->getCurrentOccupation() - requestWeight); //D.Weight = Prec(D).Weight - R.Weight (request leaves the vehicle)
 }
 
 void SAEVRoute::removeRequestWeightFromRoute(size_t requestId) {
-    SAEVKeyPoint* currentKP = &getOrigin(requestId);
+    SAEVKeyPoint* currentKP = &getRequestOrigin(requestId);
     int requestWeight = currentKP->getRequest()->getWeight();
     currentKP->setCurrentOccupation(0); //reset request weight on origin KP
     do {
         currentKP = currentKP->getSuccessor();
         currentKP->setCurrentOccupation(currentKP->getCurrentOccupation() - requestWeight);
-    } while (currentKP != &getDestination(requestId));
+    } while (currentKP != &getRequestDestination(requestId));
     currentKP->setCurrentOccupation(0); //reset request weight on destination KP
 }
 
diff --git a/src/routes/vehicle/SAEVRoute.h b/src/routes/vehicle/SAEVRoute.h
index 394ed0f..df44ddc 100644
--- a/src/routes/vehicle/SAEVRoute.h
+++ b/src/routes/vehicle/SAEVRoute.h
@@ -84,8 +84,8 @@ public:
      * @param destinationPredecessor The destination's expected predecessor, aka the point after which we wish to insert our destination
      * @return true iff all neighbouring time window conditions are valid at our insertion points, false otherwise
      */
-    bool doNeighbouringTWChecks(const size_t requestId, const size_t originNodeIndex, const size_t destinationNodeIndex,
-                                const SAEVKeyPoint *originPredecessor, const SAEVKeyPoint *destinationPredecessor);
+    bool doNeighbouringTWChecks(const size_t requestId, const SAEVKeyPoint *originPredecessor,
+                                const SAEVKeyPoint *destinationPredecessor);
 
     /**
      * Method called after having validated conditions not requiring request insertion. \n
@@ -118,11 +118,15 @@ public:
     SAEVKeyPoint& getOriginDepot(const size_t vehicleId) { return _route.at(_nbRequest*2 + vehicleId*2);}
     SAEVKeyPoint& getDestinationDepot(const size_t vehicleId) { return _route.at(_nbRequest*2 + vehicleId*2 + 1);}
 
-    [[nodiscard]] size_t getRequestOriginIdx(const size_t requestId) const { return requestId * 2;}
-    [[nodiscard]] size_t getRequestDestinationIdx(const size_t requestId) const { return requestId * 2 + 1;}
+    [[nodiscard]] size_t getRequestOriginRouteIdx(const size_t requestId) const { return requestId * 2;}
+    [[nodiscard]] size_t getRequestDestinationRouteIdx(const size_t requestId) const { return requestId * 2 + 1;}
+    [[nodiscard]] size_t getRequestOriginNodeIdx(const size_t requestId) const { return _route[getRequestOriginRouteIdx(requestId)].getNodeIndex();}
+    [[nodiscard]] size_t getRequestDestinationNodeIdx(const size_t requestId) const { return _route[getRequestDestinationRouteIdx(requestId)].getNodeIndex();}
 
-    [[nodiscard]] size_t getOriginDepotIdx(const size_t vehicleId) const { return _nbRequest*2 + vehicleId*2;}
-    [[nodiscard]] size_t getDestinationDepotIdx(const size_t vehicleId) const { return _nbRequest*2 + vehicleId*2 + 1;}
+    [[nodiscard]] size_t getOriginDepotRouteIdx(const size_t vehicleId) const { return _nbRequest*2 + vehicleId*2;}
+    [[nodiscard]] size_t getDestinationDepotRouteIdx(const size_t vehicleId) const { return _nbRequest*2 + vehicleId*2 + 1;}
+    [[nodiscard]] size_t getOriginDepotNodeIdx(const size_t vehicleId) const { return _route[_nbRequest*2 + vehicleId*2].getNodeIndex();}
+    [[nodiscard]] size_t getDestinationDepotNodeIdx(const size_t vehicleId) const { return _route[_nbRequest*2 + vehicleId*2].getNodeIndex();}
 
     [[nodiscard]] size_t getLastActiveVehicleId() const { return _lastActiveVehicleId; }
     void setLastActiveVehicleId(size_t lastActiveVehicleId) { _lastActiveVehicleId = lastActiveVehicleId; }
diff --git a/test/src/BestInsertionHeuristicDebug.cpp b/test/src/BestInsertionHeuristicDebug.cpp
index 3d7c600..1649fb5 100644
--- a/test/src/BestInsertionHeuristicDebug.cpp
+++ b/test/src/BestInsertionHeuristicDebug.cpp
@@ -31,7 +31,8 @@ TEST(BestInsertionHeuristicDebug, DebugBaseInstance) {
     std::cout << routesContainer.to_string(vehicleId) << std::endl;
     assert(routesContainer.checkRouteTimeWindows(vehicleId));
     std::cout << "------------------------------------------------------------------" << std::endl;
-    SAEVRouteChangelist req1Changelist = routesContainer.tryAddRequest(1, routesContainer.getOriginDepot(vehicleId), routesContainer.getDestination(0));
+    SAEVRouteChangelist req1Changelist = routesContainer.tryAddRequest(1, routesContainer.getOriginDepot(vehicleId),
+                                                                       routesContainer.getRequestDestination(0));
     std::cout << routesContainer.to_string(vehicleId) << std::endl << std::endl;
     assert(!routesContainer.checkRouteTimeWindows(vehicleId));
     std::cout << "------------------------------------------------------------------" << std::endl;
@@ -61,18 +62,19 @@ TEST(BestInsertionQueueDebug, DebugInstanceAlain) {
     BestInsertionQueue biQueue = routesContainer.getBestInsertionsQueue(0,0);
     routesContainer.tryAddRequest(0,routesContainer.getOriginDepot(0),routesContainer.getOriginDepot(0));
     biQueue = routesContainer.getBestFeasibleInsertionsQueue(1,0);
-    routesContainer.tryAddRequest(1,routesContainer.getOrigin(0),routesContainer.getOrigin(0));
+    routesContainer.tryAddRequest(1, routesContainer.getRequestOrigin(0), routesContainer.getRequestOrigin(0));
     biQueue = routesContainer.getBestFeasibleInsertionsQueue(2,0);
-    SAEVRouteChangelist cl = routesContainer.tryAddRequest(2,routesContainer.getOrigin(1),routesContainer.getDestination(1));
+    SAEVRouteChangelist cl = routesContainer.tryAddRequest(2, routesContainer.getRequestOrigin(1),
+                                                           routesContainer.getRequestDestination(1));
     biQueue = routesContainer.getBestFeasibleInsertionsQueue(3,0);
 
     //Vehicle 2 insertions
     biQueue = routesContainer.getBestFeasibleInsertionsQueue(5,1);
     routesContainer.tryAddRequest(5,routesContainer.getOriginDepot(1),routesContainer.getOriginDepot(1));
     biQueue = routesContainer.getBestFeasibleInsertionsQueue(4,1);
-    routesContainer.tryAddRequest(4,routesContainer.getOriginDepot(1),routesContainer.getDestination(5));
+    routesContainer.tryAddRequest(4,routesContainer.getOriginDepot(1), routesContainer.getRequestDestination(5));
     biQueue = routesContainer.getBestFeasibleInsertionsQueue(3,1);
-    routesContainer.tryAddRequest(3,routesContainer.getOriginDepot(1),routesContainer.getOrigin(4));
+    routesContainer.tryAddRequest(3,routesContainer.getOriginDepot(1), routesContainer.getRequestOrigin(4));
     biQueue = routesContainer.getBestFeasibleInsertionsQueue(0,1);
     biQueue = routesContainer.getBestFeasibleInsertionsQueue(1,1);
     biQueue = routesContainer.getBestFeasibleInsertionsQueue(2,1);
diff --git a/test/src/ConstraintPropagationDebug.cpp b/test/src/ConstraintPropagationDebug.cpp
index dd68aad..5dd841d 100644
--- a/test/src/ConstraintPropagationDebug.cpp
+++ b/test/src/ConstraintPropagationDebug.cpp
@@ -31,7 +31,8 @@ TEST(ConstraintPropagationDebug, DebugBaseInstance) {
     std::cout << routesContainer.to_string(vehicleId) << std::endl;
     assert(routesContainer.checkRouteTimeWindows(vehicleId));
     std::cout << "------------------------------------------------------------------" << std::endl;
-    SAEVRouteChangelist req1Changelist = routesContainer.tryAddRequest(1, routesContainer.getOriginDepot(vehicleId), routesContainer.getDestination(0));
+    SAEVRouteChangelist req1Changelist = routesContainer.tryAddRequest(1, routesContainer.getOriginDepot(vehicleId),
+                                                                       routesContainer.getRequestDestination(0));
     std::cout << routesContainer.to_string(vehicleId) << std::endl << std::endl;
     assert(!routesContainer.checkRouteTimeWindows(vehicleId));
     std::cout << "------------------------------------------------------------------" << std::endl;
@@ -80,13 +81,14 @@ TEST(ConstraintPropagationDebug, DebugInstanceAlain) {
 
     //Vehicle 1 insertions
     routesContainer.tryAddRequest(0,routesContainer.getOriginDepot(0),routesContainer.getOriginDepot(0));
-    routesContainer.tryAddRequest(1,routesContainer.getOrigin(0),routesContainer.getOrigin(0));
-    SAEVRouteChangelist cl = routesContainer.tryAddRequest(2,routesContainer.getOrigin(1),routesContainer.getDestination(1));
+    routesContainer.tryAddRequest(1, routesContainer.getRequestOrigin(0), routesContainer.getRequestOrigin(0));
+    SAEVRouteChangelist cl = routesContainer.tryAddRequest(2, routesContainer.getRequestOrigin(1),
+                                                           routesContainer.getRequestDestination(1));
 
     //Vehicle 2 insertions
     routesContainer.tryAddRequest(5,routesContainer.getOriginDepot(1),routesContainer.getOriginDepot(1));
-    routesContainer.tryAddRequest(4,routesContainer.getOriginDepot(1),routesContainer.getDestination(5));
-    routesContainer.tryAddRequest(3,routesContainer.getOriginDepot(1),routesContainer.getOrigin(4));
+    routesContainer.tryAddRequest(4,routesContainer.getOriginDepot(1), routesContainer.getRequestDestination(5));
+    routesContainer.tryAddRequest(3,routesContainer.getOriginDepot(1), routesContainer.getRequestOrigin(4));
 }
 
 }
-- 
GitLab


From 7997a696b953fb14644aec6f31804770ab585132 Mon Sep 17 00:00:00 2001
From: Romain BERNARD <romain.bernard@uca.fr>
Date: Mon, 24 Jun 2024 17:37:33 +0200
Subject: [PATCH 132/327] use appropriate debug message macro names

---
 src/algorithm/DARP/Heuristics/BestInsertionHeuristic.cpp | 2 +-
 src/routes/vehicle/SAEVRoute.cpp                         | 3 +--
 2 files changed, 2 insertions(+), 3 deletions(-)

diff --git a/src/algorithm/DARP/Heuristics/BestInsertionHeuristic.cpp b/src/algorithm/DARP/Heuristics/BestInsertionHeuristic.cpp
index 7bcdf59..e846571 100644
--- a/src/algorithm/DARP/Heuristics/BestInsertionHeuristic.cpp
+++ b/src/algorithm/DARP/Heuristics/BestInsertionHeuristic.cpp
@@ -4,7 +4,7 @@
 
 #include "BestInsertionHeuristic.h"
 
-#ifdef DEBUG_TRANSIT_PRECOMPUTE
+#ifdef DEBUG_BEST_INSERTION_HEURISTIC
 #include <iostream>
 #define DEBUG_MSG(str) do { std::cout << str << std::endl; } while( false )
 #else
diff --git a/src/routes/vehicle/SAEVRoute.cpp b/src/routes/vehicle/SAEVRoute.cpp
index cbc1065..03f267e 100644
--- a/src/routes/vehicle/SAEVRoute.cpp
+++ b/src/routes/vehicle/SAEVRoute.cpp
@@ -7,7 +7,7 @@
 #include "SAEVRoute.h"
 #include "BestInsertionQueue.h"
 
-#ifdef DEBUG_TRANSIT_PRECOMPUTE
+#ifdef DEBUG_CONSTRAINT_PROPAGATION
 #include <iostream>
 #define DEBUG_MSG(str) do { std::cout << str << std::endl; } while( false )
 #else
@@ -286,7 +286,6 @@ SAEVRouteChangelist SAEVRoute::insertRequestWithPropagation(const size_t request
         }
     }
 
-    DEBUG_MSG("INSERTION SUCCESS");
     changelist.setStatus(SAEVRouteChangelist::InsertionStatus::SUCCESS);
     changelist.setScore(getDetourScore(requestId, originRequestPredecessorKP, destinationRequestPredecessorKP));
     return changelist;
-- 
GitLab


From f68cb03ca18bbdce5516d89c7eaa3adc0f1f4065 Mon Sep 17 00:00:00 2001
From: Romain BERNARD <romain.bernard@uca.fr>
Date: Mon, 24 Jun 2024 17:38:45 +0200
Subject: [PATCH 133/327] use a reference for the routes to be properly updated
 in the method

---
 src/algorithm/DARP/Heuristics/BestInsertionHeuristic.cpp | 2 +-
 src/algorithm/DARP/Heuristics/BestInsertionHeuristic.h   | 2 +-
 2 files changed, 2 insertions(+), 2 deletions(-)

diff --git a/src/algorithm/DARP/Heuristics/BestInsertionHeuristic.cpp b/src/algorithm/DARP/Heuristics/BestInsertionHeuristic.cpp
index e846571..dedbf5f 100644
--- a/src/algorithm/DARP/Heuristics/BestInsertionHeuristic.cpp
+++ b/src/algorithm/DARP/Heuristics/BestInsertionHeuristic.cpp
@@ -33,7 +33,7 @@ bool BestInsertionHeuristic::tryVehicleBestInsertion(size_t requestId, size_t ve
     return bestInsertionFound;
 }
 
-size_t BestInsertionHeuristic::doBestRequestInsertionForRoute(size_t requestId, SAEVRoute route) {
+size_t BestInsertionHeuristic::doBestRequestInsertionForRoute(size_t requestId, SAEVRoute& route) {
     size_t vehicleId = 0;
     bool insertionSuccess{false};
     //Iteratively try inserting in every active vehicle and the first inactive vehicle
diff --git a/src/algorithm/DARP/Heuristics/BestInsertionHeuristic.h b/src/algorithm/DARP/Heuristics/BestInsertionHeuristic.h
index 657a978..ce5606e 100644
--- a/src/algorithm/DARP/Heuristics/BestInsertionHeuristic.h
+++ b/src/algorithm/DARP/Heuristics/BestInsertionHeuristic.h
@@ -17,7 +17,7 @@ public:
      * @param route the route structure in which the request will be inserted
      * @return ID of the vehicle in which the request has been
      */
-    static size_t doBestRequestInsertionForRoute(size_t requestId, SAEVRoute route);
+    static size_t doBestRequestInsertionForRoute(size_t requestId, SAEVRoute& route);
     /**
      * Iteratively tests best insertions wrt scoring function (detour) in the given vehicle and route
      * @param requestId ID of the request to insert in the vehicle
-- 
GitLab


From 407be6f63116791eddb799ea53edd0333a3a4ed2 Mon Sep 17 00:00:00 2001
From: Romain BERNARD <romain.bernard@uca.fr>
Date: Mon, 24 Jun 2024 17:39:45 +0200
Subject: [PATCH 134/327] replace vehicle weight macro with a constexpr

---
 CMakeLists.txt            |  1 +
 src/instance/SAEVehicle.h |  6 ++----
 src/utils/Constants.h     | 15 +++++++++++++++
 test/CMakeLists.txt       |  2 ++
 4 files changed, 20 insertions(+), 4 deletions(-)
 create mode 100644 src/utils/Constants.h

diff --git a/CMakeLists.txt b/CMakeLists.txt
index d6e9993..0423a97 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -64,6 +64,7 @@ add_executable(GreedyAlgorithm
         "src/utils/Instance Generation/Graph/OSRMGraphGenerator.h"
         src/routes/vehicle/BestRequestInsertion.h
         src/routes/vehicle/BestInsertionQueue.h
+        src/utils/Constants.h
 )
 
 add_executable(RequestGenerator
diff --git a/src/instance/SAEVehicle.h b/src/instance/SAEVehicle.h
index 2efee9e..c7e5ceb 100644
--- a/src/instance/SAEVehicle.h
+++ b/src/instance/SAEVehicle.h
@@ -5,13 +5,11 @@
 #ifndef GREEDYALGORITHM_SAEVEHICLE_H
 #define GREEDYALGORITHM_SAEVEHICLE_H
 
-#define VEHICLE_CAPACITY 6
-
-
+#include "../utils/Constants.h"
 
 class SAEVehicle {
 private:
-    static const int _capacity{VEHICLE_CAPACITY};
+    static const int _capacity{Constants::VEHICLE_CAPACITY};
 
 public:
     SAEVehicle() = default;
diff --git a/src/utils/Constants.h b/src/utils/Constants.h
new file mode 100644
index 0000000..47f3b51
--- /dev/null
+++ b/src/utils/Constants.h
@@ -0,0 +1,15 @@
+//
+// Created by romain on 24/06/24.
+//
+
+#ifndef GREEDYALGORITHM_CONSTANTS_H
+#define GREEDYALGORITHM_CONSTANTS_H
+
+
+class Constants {
+public:
+    static constexpr int VEHICLE_CAPACITY = 4;
+};
+
+
+#endif //GREEDYALGORITHM_CONSTANTS_H
diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt
index 59926f7..5d97ecd 100644
--- a/test/CMakeLists.txt
+++ b/test/CMakeLists.txt
@@ -70,6 +70,7 @@ add_executable(Constraint_Propag_DEB
         "../src/utils/Instance Generation/Requests/RequestsGenerator.h"
         "../src/utils/Instance Generation/Requests/RequestGenerationParameters.h"
         "../src/utils/Instance Generation/Graph/OSRMGraphGenerator.h"
+        ../src/utils/Constants.h
 )
 
 add_executable(BestInsertionHeuristic_DEB
@@ -104,6 +105,7 @@ add_executable(BestInsertionHeuristic_DEB
         ../src/routes/vehicle/BestInsertionQueue.h
         ../src/algorithm/DARP/Heuristics/BestInsertionHeuristic.cpp
         ../src/algorithm/DARP/Heuristics/BestInsertionHeuristic.h
+        ../src/utils/Constants.h
 )
 
 target_link_libraries(Line_UT gtest gtest_main)
-- 
GitLab


From 4b4308f828ca40640db4737c1b99bdf2685c9ad0 Mon Sep 17 00:00:00 2001
From: Romain BERNARD <romain.bernard@uca.fr>
Date: Mon, 24 Jun 2024 17:40:32 +0200
Subject: [PATCH 135/327] new debug/test instances

---
 .../DebugWeight/graph.dat                     | 30 +++++++++++++++
 .../DebugWeight/requests.dat                  |  9 +++++
 .../Instance_Alain_140624_2/graph2.dat        | 30 +++++++++++++++
 .../Instance_Alain_140624_2/requests.dat      |  9 +++++
 test/src/BestInsertionHeuristicDebug.cpp      | 38 +++++++++++++++++--
 5 files changed, 112 insertions(+), 4 deletions(-)
 create mode 100644 resources/test/instances/BestInsertionHeuristic/DebugWeight/graph.dat
 create mode 100644 resources/test/instances/BestInsertionHeuristic/DebugWeight/requests.dat
 create mode 100644 resources/test/instances/Constraint Propagation/Instance_Alain_140624_2/graph2.dat
 create mode 100644 resources/test/instances/Constraint Propagation/Instance_Alain_140624_2/requests.dat

diff --git a/resources/test/instances/BestInsertionHeuristic/DebugWeight/graph.dat b/resources/test/instances/BestInsertionHeuristic/DebugWeight/graph.dat
new file mode 100644
index 0000000..9f90059
--- /dev/null
+++ b/resources/test/instances/BestInsertionHeuristic/DebugWeight/graph.dat
@@ -0,0 +1,30 @@
+#Params (seed)
+123456789
+#Nodes format : status (work, leisure, residential),x,y
+,0,0
+,1,1
+,1,2
+,2,2
+,2,3
+,3,3
+,3,4
+,4,4
+,4,5
+,5,5
+,5,6
+,6,6
+,6,7
+#Matrix
+0,4,60,60,60,60,60,1,60,5,60,10,60
+60,0,15,3,60,60,60,60,60,60,60,60,60
+60,60,0,60,60,60,7,60,60,60,60,60,60
+60,60,60,0,5,5,60,60,60,60,60,60,60
+60,60,6,60,0,5,60,60,60,60,60,60,60
+60,60,60,60,2,0,16,60,60,60,60,60,60
+2,60,60,60,60,60,0,16,60,60,60,60,60
+60,60,60,60,60,60,60,0,10,3,60,60,60
+60,60,60,60,60,60,60,60,0,60,60,5,60
+60,60,60,60,60,60,60,60,6,0,18,10,60
+3,60,60,60,60,60,60,60,60,60,0,60,60
+60,60,60,60,60,60,60,60,60,60,60,0,4
+60,60,60,60,60,60,60,60,60,60,2,60,0
diff --git a/resources/test/instances/BestInsertionHeuristic/DebugWeight/requests.dat b/resources/test/instances/BestInsertionHeuristic/DebugWeight/requests.dat
new file mode 100644
index 0000000..b3170a4
--- /dev/null
+++ b/resources/test/instances/BestInsertionHeuristic/DebugWeight/requests.dat
@@ -0,0 +1,9 @@
+#Global Params (delta ratio)
+1
+#Requests (origin_idx,destination_idx,min_tw_start,max_tw_start,min_tw_end,max_tw_end,delta baseline,capacity)
+1,2,1,5,,,30,4
+1,2,1,5,,,30,3
+1,2,1,5,,,30,1
+1,2,1,5,,,30,2
+1,2,1,5,,,30,3
+1,2,1,5,,,30,2
diff --git a/resources/test/instances/Constraint Propagation/Instance_Alain_140624_2/graph2.dat b/resources/test/instances/Constraint Propagation/Instance_Alain_140624_2/graph2.dat
new file mode 100644
index 0000000..b5de44a
--- /dev/null
+++ b/resources/test/instances/Constraint Propagation/Instance_Alain_140624_2/graph2.dat	
@@ -0,0 +1,30 @@
+#Params (seed)
+123456789
+#Nodes format : status (work, leisure, residential),x,y
+,0,0
+,1,1
+,1,2
+,2,2
+,2,3
+,3,3
+,3,4
+,4,4
+,4,5
+,5,5
+,5,6
+,6,6
+,6,7
+#Matrix
+0,2,60,60,60,60,60,1,60,5,60,10,60
+60,0,15,6,60,60,60,60,60,60,60,60,60
+3,60,0,60,60,60,7,60,60,60,60,60,60
+60,60,60,0,9,7,60,60,60,60,60,60,60
+60,60,5,60,0,5,3,60,60,60,60,60,60
+60,60,60,60,4,0,5,60,60,60,60,60,60
+2,60,6,60,60,60,0,16,60,60,60,60,60
+60,60,60,60,60,60,60,0,10,3,60,60,60
+60,60,60,60,60,60,60,60,0,60,60,5,60
+60,60,60,60,60,60,60,60,6,0,18,10,60
+3,60,60,60,60,60,60,60,60,60,0,60,60
+60,60,60,60,60,60,60,60,60,60,60,0,4
+60,60,60,60,60,60,60,60,60,60,2,60,0
diff --git a/resources/test/instances/Constraint Propagation/Instance_Alain_140624_2/requests.dat b/resources/test/instances/Constraint Propagation/Instance_Alain_140624_2/requests.dat
new file mode 100644
index 0000000..65b3a20
--- /dev/null
+++ b/resources/test/instances/Constraint Propagation/Instance_Alain_140624_2/requests.dat	
@@ -0,0 +1,9 @@
+#Global Params (delta ratio)
+1
+#Requests (origin_idx,destination_idx,min_tw_start,max_tw_start,min_tw_end,max_tw_end,delta baseline,capacity)
+1,2,1,5,,,30,1
+3,4,10,12,,,15,1
+5,6,14,20,,,10,1
+7,8,0,4,,,13,1
+9,10,2,7,,,22,1
+11,12,14,16,,,6,1
\ No newline at end of file
diff --git a/test/src/BestInsertionHeuristicDebug.cpp b/test/src/BestInsertionHeuristicDebug.cpp
index 1649fb5..53832d0 100644
--- a/test/src/BestInsertionHeuristicDebug.cpp
+++ b/test/src/BestInsertionHeuristicDebug.cpp
@@ -83,7 +83,7 @@ TEST(BestInsertionQueueDebug, DebugInstanceAlain) {
 TEST(BestInsertionPerVehicleHeuristicDebug, DebugInstanceAlain) {
     std::string instancesPath = "../../resources/test/instances/Constraint Propagation/";
     std::string instanceFolder = "Instance_Alain_140624/";
-    std::string graphDatFile = "graph2.dat";
+    std::string graphDatFile = "graph.dat";
     std::string requestsDatFile = "requests.dat";
 
     //Parse graph
@@ -104,10 +104,36 @@ TEST(BestInsertionPerVehicleHeuristicDebug, DebugInstanceAlain) {
     BestInsertionHeuristic::tryVehicleBestInsertion(5, 1, routesContainer);
 }
 
-TEST(BestInsertionHeuristicDebug, DebugInstanceAlain) {
+TEST(BestInsertionHeuristicDebug, DebugInstanceAlain2) {
     std::string instancesPath = "../../resources/test/instances/Constraint Propagation/";
-    std::string instanceFolder = "Instance_Alain_140624/";
-    std::string graphDatFile = "graph2.dat";
+    std::string instanceFolder = "Instance_Alain_140624_2/";
+    std::string graphDatFile = "graph.dat";
+    std::string requestsDatFile = "requests.dat";
+
+    //Parse graph
+    Graph graphFromSingleFile(instancesPath + instanceFolder + graphDatFile);
+    std::vector<Request> requests = Request::getRequestsFromFile(instancesPath + instanceFolder + requestsDatFile, graphFromSingleFile);
+
+    //Init instance
+    Instance instance(requests,graphFromSingleFile,4);
+    SAEVRoute routesContainer(graphFromSingleFile, requests);
+
+    auto t0 = std::chrono::steady_clock::now();
+    BestInsertionHeuristic::doBestRequestInsertionForRoute(0, routesContainer);
+    BestInsertionHeuristic::doBestRequestInsertionForRoute(1, routesContainer);
+    BestInsertionHeuristic::doBestRequestInsertionForRoute(2, routesContainer);
+    BestInsertionHeuristic::doBestRequestInsertionForRoute(3, routesContainer);
+    BestInsertionHeuristic::doBestRequestInsertionForRoute(4, routesContainer);
+    BestInsertionHeuristic::doBestRequestInsertionForRoute(5, routesContainer);
+    auto t1 = std::chrono::steady_clock::now();
+    auto d = t1 - t0;
+    std::cout << d.count() << "\n";
+}
+
+TEST(BestInsertionHeuristicDebug, DebugInstanceAlain) {
+    std::string instancesPath = "../../resources/test/instances/BestInsertionHeuristic/";
+    std::string instanceFolder = "DebugWeight/";
+    std::string graphDatFile = "graph.dat";
     std::string requestsDatFile = "requests.dat";
 
     //Parse graph
@@ -118,12 +144,16 @@ TEST(BestInsertionHeuristicDebug, DebugInstanceAlain) {
     Instance instance(requests,graphFromSingleFile,4);
     SAEVRoute routesContainer(graphFromSingleFile, requests);
 
+    auto t0 = std::chrono::steady_clock::now();
     BestInsertionHeuristic::doBestRequestInsertionForRoute(0, routesContainer);
     BestInsertionHeuristic::doBestRequestInsertionForRoute(1, routesContainer);
     BestInsertionHeuristic::doBestRequestInsertionForRoute(2, routesContainer);
     BestInsertionHeuristic::doBestRequestInsertionForRoute(3, routesContainer);
     BestInsertionHeuristic::doBestRequestInsertionForRoute(4, routesContainer);
     BestInsertionHeuristic::doBestRequestInsertionForRoute(5, routesContainer);
+    auto t1 = std::chrono::steady_clock::now();
+    auto d = t1 - t0;
+    std::cout << d.count() << "\n";
 }
 
 int main(int argc, char* argv[]) {
-- 
GitLab


From d7929c0b388f6472d2d768eef26c2508197709f0 Mon Sep 17 00:00:00 2001
From: Romain BERNARD <romain.bernard@uca.fr>
Date: Mon, 1 Jul 2024 10:09:15 +0200
Subject: [PATCH 136/327] rename instances to fix tests

---
 .../Instance_Alain_140624_2/{graph2.dat => graph.dat}           | 0
 test/src/BestInsertionHeuristicDebug.cpp                        | 2 +-
 test/src/ConstraintPropagationDebug.cpp                         | 2 +-
 3 files changed, 2 insertions(+), 2 deletions(-)
 rename resources/test/instances/Constraint Propagation/Instance_Alain_140624_2/{graph2.dat => graph.dat} (100%)

diff --git a/resources/test/instances/Constraint Propagation/Instance_Alain_140624_2/graph2.dat b/resources/test/instances/Constraint Propagation/Instance_Alain_140624_2/graph.dat
similarity index 100%
rename from resources/test/instances/Constraint Propagation/Instance_Alain_140624_2/graph2.dat
rename to resources/test/instances/Constraint Propagation/Instance_Alain_140624_2/graph.dat
diff --git a/test/src/BestInsertionHeuristicDebug.cpp b/test/src/BestInsertionHeuristicDebug.cpp
index 53832d0..45d2a0a 100644
--- a/test/src/BestInsertionHeuristicDebug.cpp
+++ b/test/src/BestInsertionHeuristicDebug.cpp
@@ -47,7 +47,7 @@ TEST(BestInsertionHeuristicDebug, DebugBaseInstance) {
 TEST(BestInsertionQueueDebug, DebugInstanceAlain) {
     std::string instancesPath = "../../resources/test/instances/Constraint Propagation/";
     std::string instanceFolder = "Instance_Alain_140624/";
-    std::string graphDatFile = "graph2.dat";
+    std::string graphDatFile = "graph.dat";
     std::string requestsDatFile = "requests.dat";
 
     //Parse graph
diff --git a/test/src/ConstraintPropagationDebug.cpp b/test/src/ConstraintPropagationDebug.cpp
index 5dd841d..cdc0ff7 100644
--- a/test/src/ConstraintPropagationDebug.cpp
+++ b/test/src/ConstraintPropagationDebug.cpp
@@ -68,7 +68,7 @@ TEST(ConstraintPropagationDebug, DebugRequestGeneration) {
 TEST(ConstraintPropagationDebug, DebugInstanceAlain) {
     std::string instancesPath = "../../resources/test/instances/Constraint Propagation/";
     std::string instanceFolder = "Instance_Alain_140624/";
-    std::string graphDatFile = "graph2.dat";
+    std::string graphDatFile = "graph.dat";
     std::string requestsDatFile = "requests.dat";
 
     //Parse graph
-- 
GitLab


From e911fa989f3ddc05a5750478a478f643de977a1d Mon Sep 17 00:00:00 2001
From: Romain BERNARD <romain.bernard@uca.fr>
Date: Mon, 1 Jul 2024 10:10:31 +0200
Subject: [PATCH 137/327] add tryAdd method that can't create vehicles for the
 nex algorithm

---
 .../DARP/Heuristics/BestInsertionHeuristic.cpp | 18 +++++++++++++++++-
 .../DARP/Heuristics/BestInsertionHeuristic.h   | 11 +++++++++++
 2 files changed, 28 insertions(+), 1 deletion(-)

diff --git a/src/algorithm/DARP/Heuristics/BestInsertionHeuristic.cpp b/src/algorithm/DARP/Heuristics/BestInsertionHeuristic.cpp
index dedbf5f..3f2cbc7 100644
--- a/src/algorithm/DARP/Heuristics/BestInsertionHeuristic.cpp
+++ b/src/algorithm/DARP/Heuristics/BestInsertionHeuristic.cpp
@@ -15,9 +15,11 @@ bool BestInsertionHeuristic::tryVehicleBestInsertion(size_t requestId, size_t ve
     BestInsertionQueue bestInsertionsQueue = route.getBestFeasibleInsertionsQueue(requestId, vehicleId); //TODO: check perfs between BestInsertionsQueue vs BestFeasibleInsertionsQueue
     bool bestInsertionFound = false;
     BestRequestInsertion currentBestInsertion;
-    DEBUG_MSG("Trying to insert request " + std::to_string(requestId) + " in vehicle " + std::to_string(vehicleId));
+
+    DEBUG_MSG("Trying to insert request " + std::to_string(requestId) + " in vehicle " + std::to_string(vehicleId) + " queue size : " + std::to_string(bestInsertionsQueue.size()));
     while(!bestInsertionsQueue.empty() && !bestInsertionFound) {
         currentBestInsertion = bestInsertionsQueue.topAndPop();
+        DEBUG_MSG("Trying insertion " + currentBestInsertion.to_string() + ", remaining : " + std::to_string(bestInsertionsQueue.size()));
         SAEVRouteChangelist lastInsertionChangelist = route.tryAddRequest(requestId,
                                                                           *currentBestInsertion.getOriginInsertionKp(),
                                                                           *currentBestInsertion.getDestinationInsertionKp());
@@ -49,3 +51,17 @@ size_t BestInsertionHeuristic::doBestRequestInsertionForRoute(size_t requestId,
 
     return vehicleId;
 }
+
+size_t BestInsertionHeuristic::tryBestRequestInsertionInActiveVehicle(size_t requestId, SAEVRoute &route) {
+    size_t vehicleId = 0;
+    bool insertionSuccess{false};
+    //Iteratively try inserting in every active vehicle and the first inactive vehicle
+    while(!insertionSuccess && ++vehicleId <= route.getLastActiveVehicleId() + 1) {
+        insertionSuccess = tryVehicleBestInsertion(requestId, vehicleId, route);
+    }
+
+    if(insertionSuccess)
+        return vehicleId;
+    else
+        return route.getLastActiveVehicleId() + 1;
+}
diff --git a/src/algorithm/DARP/Heuristics/BestInsertionHeuristic.h b/src/algorithm/DARP/Heuristics/BestInsertionHeuristic.h
index ce5606e..258f3bf 100644
--- a/src/algorithm/DARP/Heuristics/BestInsertionHeuristic.h
+++ b/src/algorithm/DARP/Heuristics/BestInsertionHeuristic.h
@@ -18,6 +18,16 @@ public:
      * @return ID of the vehicle in which the request has been
      */
     static size_t doBestRequestInsertionForRoute(size_t requestId, SAEVRoute& route);
+    /**
+     * Iteratively attempts insertions in the currently active vehicles in two steps :
+     * 1) creates a global best insertion list for all active vehicles
+     * 2) tries every insertions from best to worst
+     * 3) return the ID of the vehicle in which the request was inserted if an active vehicle was viable, return the most favourable inactive vehicle's ID otherwise
+     * @param requestId ID of the request to insert in the route
+     * @param route the route structure in which the request will be inserted
+     * @return The ID of the active vehicle in which our request was inserted, or the ID of the most favourable inactive vehicle
+     */
+    static size_t tryBestRequestInsertionInActiveVehicle(size_t requestId, SAEVRoute& route);
     /**
      * Iteratively tests best insertions wrt scoring function (detour) in the given vehicle and route
      * @param requestId ID of the request to insert in the vehicle
@@ -27,6 +37,7 @@ public:
      */
     static bool tryVehicleBestInsertion(size_t requestId, size_t vehicleId, SAEVRoute& route);
 
+
     /** TODO Implement those to prevent trying every single best insertion
     static bool vehicle_K_BestInsertion(size_t requestId, size_t vehicleId, SAEVRoute route);
     static bool vehicleScoreThresholdBestInsertion(size_t requestId, size_t vehicleId, SAEVRoute& route); */
-- 
GitLab


From aaf8e73badbe4b03afb1148d3cbdad1b7fb240f3 Mon Sep 17 00:00:00 2001
From: Romain BERNARD <romain.bernard@uca.fr>
Date: Wed, 10 Jul 2024 14:42:57 +0200
Subject: [PATCH 138/327] use size_t/uint where appropriate

---
 src/instance/graph/Graph.h          | 28 ++++++++++-----------
 src/instance/requests/Request.cpp   | 32 ++++++++++++------------
 src/instance/requests/Request.h     | 38 ++++++++++++++---------------
 src/routes/vehicle/SAEVKeyPoint.cpp |  8 +++---
 src/routes/vehicle/SAEVKeyPoint.h   | 12 ++++-----
 5 files changed, 58 insertions(+), 60 deletions(-)

diff --git a/src/instance/graph/Graph.h b/src/instance/graph/Graph.h
index 389b8e5..2843207 100644
--- a/src/instance/graph/Graph.h
+++ b/src/instance/graph/Graph.h
@@ -40,20 +40,20 @@ public:
         return nodesVector;
     }
 
-    [[nodiscard]] const Node &getNode(int nodeIndex) const {
-        return nodesVector.at(nodeIndex);
+    [[nodiscard]] const Node &getNode(size_t nodeIndex) const {
+        return nodesVector[nodeIndex];
     }
 
     [[nodiscard]] size_t getNbNodes() const {
         return nodesVector.size();
     }
 
-    [[nodiscard]] std::vector<LineStop> getPTLinesSet(int nodeIndex) const {
-        return nodesVector.at(nodeIndex).getPTLinesSet();
+    [[nodiscard]] std::vector<LineStop> getPTLinesSet(size_t nodeIndex) const {
+        return nodesVector[nodeIndex].getPTLinesSet();
     }
 
-    [[nodiscard]] size_t getNbPTLines(int nodeIndex) const {
-        return nodesVector.at(nodeIndex).getPTLinesSet().size();
+    [[nodiscard]] size_t getNbPTLines(size_t nodeIndex) const {
+        return nodesVector[nodeIndex].getPTLinesSet().size();
     }
 
     [[nodiscard]] int getDepotNodeIdx() const;
@@ -66,17 +66,17 @@ public:
         return edgesVector;
     }
 
-    [[nodiscard]] size_t getNbIncomingEdges(int nodeIndex) const {
-        return nodesVector.at(nodeIndex).getIncomingEdges().size();
+    [[nodiscard]] size_t getNbIncomingEdges(size_t nodeIndex) const {
+        return nodesVector[nodeIndex].getIncomingEdges().size();
     }
 
-    [[nodiscard]] size_t getNbOutgoingEdges(int nodeIndex) const {
-        return nodesVector.at(nodeIndex).getOutgoingEdges().size();
+    [[nodiscard]] size_t getNbOutgoingEdges(size_t nodeIndex) const {
+        return nodesVector[nodeIndex].getOutgoingEdges().size();
     }
 
 
-    [[nodiscard]] size_t getNbEdges(int nodeIndex) const {
-        return nodesVector.at(nodeIndex).getIncomingEdges().size() + nodesVector.at(nodeIndex).getOutgoingEdges().size();
+    [[nodiscard]] size_t getNbEdges(size_t nodeIndex) const {
+        return nodesVector[nodeIndex].getIncomingEdges().size() + nodesVector[nodeIndex].getOutgoingEdges().size();
     }
 
     /**
@@ -148,9 +148,9 @@ public:
      * @param edgeEndNodeIndex Index of the node serving as an exit point for this edge
      * @param length The length of this edge (in minutes)
      */
-    void createAndAddEdge(int edgeStartNodeIndex, int edgeEndNodeIndex, double length);
+    void createAndAddEdge(size_t edgeStartNodeIndex, size_t edgeEndNodeIndex, double length);
 
-    [[nodiscard]] int getShortestSAEVPath(int x, int y) const { return shortestSAEVPaths.at(x).at(y); }
+    [[nodiscard]] int getShortestSAEVPath(size_t x, size_t y) const { return shortestSAEVPaths[x][y]; }
 
     void parseDistanceMatrix(std::ifstream &infile, DATRow currentRow);
 };
diff --git a/src/instance/requests/Request.cpp b/src/instance/requests/Request.cpp
index 6de343d..02aaa80 100644
--- a/src/instance/requests/Request.cpp
+++ b/src/instance/requests/Request.cpp
@@ -6,19 +6,17 @@
 #include "Request.h"
 #include "../../services/DatFile/DATRow.h"
 
-Request::Request(const int departureNodeIndex, const int arrivalNodeIndex, const TimeWindow &arrivalTw,
-                 const int deltaTime, const int weight) : _originNodeIndex(departureNodeIndex),
-                                                          _destinationNodeIndex(arrivalNodeIndex), _arrivalTW(arrivalTw),
-                                                          _deltaTime(deltaTime), _weight(weight) {
-    _currentDeltaTime = deltaTime;
+Request::Request(const size_t departureNodeIndex, const size_t arrivalNodeIndex, const TimeWindow &arrivalTw,
+                 const uint deltaTime, const uint weight) : _originNodeIndex(departureNodeIndex),
+                                                            _destinationNodeIndex(arrivalNodeIndex), _arrivalTW(arrivalTw),
+                                                            _deltaTime(deltaTime), _currentDeltaTime(deltaTime), _weight(weight) {
     _departureTW = _arrivalTW - deltaTime;
 }
 
-Request::Request(const int departureNodeIndex, const int arrivalNodeIndex, const TimeWindow &arrivalTw,
-                 const int deltaTime, const int weight, const Graph& graph) :
+Request::Request(const size_t departureNodeIndex, const size_t arrivalNodeIndex, const TimeWindow &arrivalTw,
+                 const uint deltaTime, const uint weight, const Graph& graph) :
         _originNodeIndex(departureNodeIndex), _destinationNodeIndex(arrivalNodeIndex),
-        _arrivalTW(arrivalTw), _deltaTime(deltaTime), _weight(weight) {
-    _currentDeltaTime = deltaTime;
+        _arrivalTW(arrivalTw), _deltaTime(deltaTime), _currentDeltaTime(deltaTime), _weight(weight) {
     _departureTW.min = _arrivalTW.min - deltaTime;
     _departureTW.max = _arrivalTW.max - graph.getShortestSAEVPath(departureNodeIndex, arrivalNodeIndex);
 }
@@ -85,11 +83,11 @@ std::vector<Request> Request::getRequestsFromFile(const std::string& datFilePath
     return requests;
 }
 
-const int Request::getOriginNodeIndex() const {
+size_t Request::getOriginNodeIndex() const {
     return _originNodeIndex;
 }
 
-const int Request::getDestinationNodeIndex() const {
+size_t Request::getDestinationNodeIndex() const {
     return _destinationNodeIndex;
 }
 
@@ -97,11 +95,11 @@ const TimeWindow &Request::getArrivalTw() const {
     return _arrivalTW;
 }
 
-const int Request::getDeltaTime() const {
+int Request::getDeltaTime() const {
     return _deltaTime;
 }
 
-const int Request::getWeight() const {
+int Request::getWeight() const {
     return _weight;
 }
 
@@ -125,21 +123,21 @@ const TimeWindow &Request::getDepartureTw() const {
     return _departureTW;
 }
 
-const int &Request::getMinDepartureTw() const {
+uint Request::getMinDepartureTw() const {
     return _departureTW.min;
 }
 
 
-const int &Request::getMaxDepartureTw() const {
+uint Request::getMaxDepartureTw() const {
     return _departureTW.max;
 }
 
-const int &Request::getMinArrivalTw() const {
+uint Request::getMinArrivalTw() const {
     return _arrivalTW.min;
 }
 
 
-const int &Request::getMaxArrivalTw() const {
+uint Request::getMaxArrivalTw() const {
     return _arrivalTW.max;
 }
 
diff --git a/src/instance/requests/Request.h b/src/instance/requests/Request.h
index df95f2f..d24cf79 100644
--- a/src/instance/requests/Request.h
+++ b/src/instance/requests/Request.h
@@ -13,43 +13,43 @@
 class Request {
 private:
     //Request base members (const and initialized on _request creation)
-    int _originNodeIndex; //Starting point of the user _request //TODO (?) change this to a Node pointer eventually
-    int _destinationNodeIndex; //
+    size_t _originNodeIndex; //Starting point of the user _request //TODO (?) change this to a Node pointer eventually
+    size_t _destinationNodeIndex; //
     TimeWindow _arrivalTW; //[min,max] time window for arrival to the destination node
-    int _deltaTime; //Base delta time, aka the maximum total duration of the path to serve this _request
-    int _weight; //How much space the requests takes in the vehicle (defaults to 1)
+    uint _deltaTime; //Base delta time, aka the maximum total duration of the path to serve this _request
+    uint _weight; //How much space the requests takes in the vehicle (defaults to 1)
 
     //Request helpful members (used for constraint propagation and remember the current state of the _request)
-    int _currentDeltaTime; //deltaTime - currentRouteDuration
-    int _requestServiceStart;
-    int _requestServiceEnd;
+    uint _currentDeltaTime; //deltaTime - currentRouteDuration
+    uint _requestServiceStart;
+    uint _requestServiceEnd;
     RequestRoute _currentRoute{this};
     TimeWindow _departureTW; //For now, a virtual TW on departures, used for constraint propagation
 public:
-    Request(const int departureNodeIndex, const int arrivalNodeIndex,
-            const TimeWindow &arrivalTw, const int deltaTime, const int weight);
-    Request(const int departureNodeIndex, const int arrivalNodeIndex, const TimeWindow &arrivalTw,
-            const int deltaTime, const int weight, const Graph& graph);
+    Request(const size_t departureNodeIndex, const size_t arrivalNodeIndex,
+            const TimeWindow &arrivalTw, const uint deltaTime, const uint weight);
+    Request(const size_t departureNodeIndex, const size_t arrivalNodeIndex, const TimeWindow &arrivalTw,
+            const uint deltaTime, const uint weight, const Graph& graph);
     Request(const DATRow& currentRow, const Graph& graph);
     Request(const DATRow& currentRow, double deltaRatio, const Graph& graph);
 
     static std::vector<Request> getRequestsFromFile(const std::string& datFilePath, const Graph& graph);
 
     //Getters
-    [[nodiscard]] const int getOriginNodeIndex() const;
-    [[nodiscard]] const int getDestinationNodeIndex() const;
+    [[nodiscard]] size_t getOriginNodeIndex() const;
+    [[nodiscard]] size_t getDestinationNodeIndex() const;
     [[nodiscard]] const TimeWindow &getArrivalTw() const;
-    [[nodiscard]] const int getDeltaTime() const;
-    [[nodiscard]] const int getWeight() const;
+    [[nodiscard]] int getDeltaTime() const;
+    [[nodiscard]] int getWeight() const;
     [[nodiscard]] int getCurrentDeltaTime() const;
     [[nodiscard]] int getRequestServiceStart() const;
     [[nodiscard]] int getRequestServiceEnd() const;
     [[nodiscard]] const RequestRoute &getCurrentRoute() const;
     [[nodiscard]] const TimeWindow &getDepartureTw() const;
-    [[nodiscard]] const int &getMinDepartureTw() const;
-    [[nodiscard]] const int &getMaxDepartureTw() const;
-    [[nodiscard]] const int &getMinArrivalTw() const;
-    [[nodiscard]] const int &getMaxArrivalTw() const;
+    [[nodiscard]] uint getMinDepartureTw() const;
+    [[nodiscard]] uint getMaxDepartureTw() const;
+    [[nodiscard]] uint getMinArrivalTw() const;
+    [[nodiscard]] uint getMaxArrivalTw() const;
 
     //Setters
     void setCurrentDeltaTime(int currentDeltaTime);
diff --git a/src/routes/vehicle/SAEVKeyPoint.cpp b/src/routes/vehicle/SAEVKeyPoint.cpp
index 15511b8..9f7527f 100644
--- a/src/routes/vehicle/SAEVKeyPoint.cpp
+++ b/src/routes/vehicle/SAEVKeyPoint.cpp
@@ -32,19 +32,19 @@ void SAEVKeyPoint::setCurrentOccupation(int currentCapacity) {
     _currentOccupation = currentCapacity;
 }
 
-int SAEVKeyPoint::getMinTw() const {
+uint SAEVKeyPoint::getMinTw() const {
     return _minTW;
 }
 
-void SAEVKeyPoint::setMinTw(int minTw) {
+void SAEVKeyPoint::setMinTw(uint minTw) {
     _minTW = minTw;
 }
 
-int SAEVKeyPoint::getMaxTw() const {
+uint SAEVKeyPoint::getMaxTw() const {
     return _maxTW;
 }
 
-void SAEVKeyPoint::setMaxTw(int maxTw) {
+void SAEVKeyPoint::setMaxTw(uint maxTw) {
     _maxTW = maxTw;
 }
 
diff --git a/src/routes/vehicle/SAEVKeyPoint.h b/src/routes/vehicle/SAEVKeyPoint.h
index bacdbaa..8725687 100644
--- a/src/routes/vehicle/SAEVKeyPoint.h
+++ b/src/routes/vehicle/SAEVKeyPoint.h
@@ -18,8 +18,8 @@ private:
     SAEVKeyPoint* _successor{nullptr};
     SAEVKeyPoint* _counterpart{nullptr};
     int _currentOccupation{0};
-    int _minTW{0};
-    int _maxTW{INT16_MAX};
+    uint _minTW{0};
+    uint _maxTW{INT16_MAX};
     SAEVehicle const * _vehiclePointer{};
     Request const * _requestPointer{};
 public:
@@ -48,11 +48,11 @@ public:
     [[nodiscard]] int getCurrentOccupation() const;
     void setCurrentOccupation(int currentCapacity);
 
-    [[nodiscard]] int getMinTw() const;
-    void setMinTw(int minTw);
+    [[nodiscard]] uint getMinTw() const;
+    void setMinTw(uint minTw);
 
-    [[nodiscard]] int getMaxTw() const;
-    void setMaxTw(int maxTw);
+    [[nodiscard]] uint getMaxTw() const;
+    void setMaxTw(uint maxTw);
 
     [[nodiscard]] bool isOrigin() const;
     [[nodiscard]] bool isDestination() const;
-- 
GitLab


From 3ad7e88595c7c30702728dad4a9ff432f6dfaf11 Mon Sep 17 00:00:00 2001
From: Romain BERNARD <romain.bernard@uca.fr>
Date: Wed, 10 Jul 2024 15:55:39 +0200
Subject: [PATCH 139/327] Replace .at calls with [] access for performance
 (debug modes can still include vector bounds check on [] operators)

---
 src/ShortestPath/ShortestPath.h               |  2 +-
 .../Transit/TransitAlgorithmState.h           |  4 +--
 .../Transit/TransitShortestPathContainer.cpp  |  8 ++---
 .../Transit/TransitStateContainer.h           | 32 +++++++++----------
 src/instance/graph/Graph.cpp                  | 10 +++---
 src/instance/graph/Line.cpp                   |  2 +-
 src/instance/graph/Line.h                     | 10 +++---
 src/routes/vehicle/SAEVRoute.cpp              | 14 ++++----
 src/routes/vehicle/SAEVRoute.h                |  8 ++---
 test/src/LineUnitTests.cpp                    |  2 +-
 10 files changed, 46 insertions(+), 46 deletions(-)

diff --git a/src/ShortestPath/ShortestPath.h b/src/ShortestPath/ShortestPath.h
index 8ad3290..0199832 100644
--- a/src/ShortestPath/ShortestPath.h
+++ b/src/ShortestPath/ShortestPath.h
@@ -21,7 +21,7 @@ public:
     }
 
     void replaceKeyPoint(int keyPointIndex, KeyPoint& value) {
-        _keyPoints.at(keyPointIndex) = value;
+        _keyPoints[keyPointIndex] = value;
     }
 
     /**
diff --git a/src/ShortestPath/Transit/TransitAlgorithmState.h b/src/ShortestPath/Transit/TransitAlgorithmState.h
index d069858..133d003 100644
--- a/src/ShortestPath/Transit/TransitAlgorithmState.h
+++ b/src/ShortestPath/Transit/TransitAlgorithmState.h
@@ -207,11 +207,11 @@ public:
             res += ", Connections: ";
             if(_connections.size() > 1) {
                 for(int i = 0; i < _connections.size() - 1; ++i) {
-                    res += _connections.at(i).getLineRef().getLineId() + " -> ";
+                    res += _connections[i].getLineRef().getLineId() + " -> ";
                 }
             }
 
-            res += _connections.at(_connections.size() - 1).getLineRef().getLineId();
+            res += _connections[_connections.size() - 1].getLineRef().getLineId();
 
         }
 
diff --git a/src/ShortestPath/Transit/TransitShortestPathContainer.cpp b/src/ShortestPath/Transit/TransitShortestPathContainer.cpp
index bee8ce4..1bac7e5 100644
--- a/src/ShortestPath/Transit/TransitShortestPathContainer.cpp
+++ b/src/ShortestPath/Transit/TransitShortestPathContainer.cpp
@@ -7,7 +7,7 @@
 
 void TransitShortestPathContainer::addShortestPathCollection(int startNodeIndex,
                                                              const std::pair<int, std::vector<TransitShortestPath>>& shortestPathList) {
-    container.at(startNodeIndex).emplace_back(shortestPathList);
+    container[startNodeIndex].emplace_back(shortestPathList);
 }
 
 void TransitShortestPathContainer::addShortestPathCollection(int startNodeIndex, int startingInstant, int graphSize,
@@ -21,12 +21,12 @@ void TransitShortestPathContainer::addShortestPathCollection(int startNodeIndex,
     }
 
     //Add the (startingInstant, pathVector) pair at the appropriate node index
-    container.at(startNodeIndex).emplace_back(startingInstant, shortestPathList);
+    container[startNodeIndex].emplace_back(startingInstant, shortestPathList);
 }
 
 std::vector<std::pair<int, std::vector<TransitShortestPath>>>::iterator
 TransitShortestPathContainer::getShortestPathsFromTime(int startNodeIndex, int earliestStartInstant) {
-    const auto& iterator = std::lower_bound(container.at(startNodeIndex).begin(), container.at(startNodeIndex).end(),
+    const auto& iterator = std::lower_bound(container[startNodeIndex].begin(), container[startNodeIndex].end(),
                                             std::pair<int, std::vector<TransitShortestPath>>(earliestStartInstant, {}));
 
     return iterator;
@@ -35,5 +35,5 @@ TransitShortestPathContainer::getShortestPathsFromTime(int startNodeIndex, int e
 std::pair<int, TransitShortestPath>
 TransitShortestPathContainer::getShortestPathToYFromTime(int startNodeIndex, int earliestStartInstant, int goalNode) {
     const auto& shortestPathsIterator = getShortestPathsFromTime(startNodeIndex, earliestStartInstant);
-    return std::pair(shortestPathsIterator->first, shortestPathsIterator->second.at(goalNode));
+    return std::pair(shortestPathsIterator->first, shortestPathsIterator->second[goalNode]);
 }
diff --git a/src/ShortestPath/Transit/TransitStateContainer.h b/src/ShortestPath/Transit/TransitStateContainer.h
index fbb3ea4..b568d03 100644
--- a/src/ShortestPath/Transit/TransitStateContainer.h
+++ b/src/ShortestPath/Transit/TransitStateContainer.h
@@ -25,8 +25,8 @@ public:
     {
         solutionVector.resize(size);
         for(size_t i = 0; i < size; ++i) {
-            solutionVector.at(i).emplace_back();
-            solutionVector.at(i).emplace_back();
+            solutionVector[i].emplace_back();
+            solutionVector[i].emplace_back();
         }
     }
     explicit TransitStateContainer(size_t size)
@@ -34,8 +34,8 @@ public:
         //Reserve space for all nodes and add empty solutions to reserve memory
         solutionVector.resize(size);
         for(size_t i = 0; i < size; ++i) {
-            solutionVector.at(i).emplace_back();
-            solutionVector.at(i).emplace_back();
+            solutionVector[i].emplace_back();
+            solutionVector[i].emplace_back();
         }
     }
     /**
@@ -44,14 +44,14 @@ public:
      * @return The first solution of potentially two saved in this array
      */
     [[nodiscard]] const TransitAlgorithmState& getBestSolution(int nodeIndex) const{
-        if(solutionVector.at(1) < solutionVector.at(0))
-            return solutionVector.at(nodeIndex).at(1);
+        if(solutionVector[1] < solutionVector[0])
+            return solutionVector[nodeIndex][1];
         else
-            return solutionVector.at(nodeIndex).at(0);
+            return solutionVector[nodeIndex][0];
     }
 
-    TransitAlgorithmState& getBestSolution(int nodeIndex, int nbConnections){ return solutionVector.at(nodeIndex).at(nbConnections == 0 ? 0 : nbConnections - 1);}
-    std::vector<TransitAlgorithmState>& getSolutions(int nodeIndex){ return solutionVector.at(nodeIndex);}
+    TransitAlgorithmState& getBestSolution(int nodeIndex, int nbConnections){ return solutionVector[nodeIndex][nbConnections == 0 ? 0 : nbConnections - 1];}
+    std::vector<TransitAlgorithmState>& getSolutions(int nodeIndex){ return solutionVector[nodeIndex];}
     std::vector<std::vector<TransitAlgorithmState>>& getSolutionsVector(){ return solutionVector;}
 
     bool strictlyDominates(const TransitAlgorithmState& state){
@@ -72,10 +72,10 @@ public:
     void replaceBestSolutionIfNecessary(int nodeIndex, const TransitAlgorithmState& newState)
     {
         if(newState.getNbConnections() > 0) {
-            TransitAlgorithmState& currentBest = solutionVector.at(nodeIndex).at(newState.getNbConnections() - 1);
+            TransitAlgorithmState const& currentBest = solutionVector[nodeIndex][newState.getNbConnections() - 1];
             if(currentBest.getInstant() > newState.getInstant()) {
                 DEBUG_MSG("Candidate state " + newState.toString() + " is the new fastest solution");
-                solutionVector.at(nodeIndex).at(newState.getNbConnections() - 1) = newState;
+                solutionVector[nodeIndex][newState.getNbConnections() - 1] = newState;
             }
         }
     }
@@ -87,10 +87,10 @@ public:
      * @return
      */
     TransitAlgorithmState getBestSolution(int nodeIndex) {
-        TransitAlgorithmState currentBestSol = solutionVector.at(nodeIndex).at(0);
-        for(size_t i = 1; i < solutionVector.at(nodeIndex).size(); ++i) {
-            if(solutionVector.at(nodeIndex).at(i).getInstant() < currentBestSol.getInstant()) {
-                currentBestSol = solutionVector.at(nodeIndex).at(i);
+        TransitAlgorithmState currentBestSol = solutionVector[nodeIndex][0];
+        for(size_t i = 1; i < solutionVector[nodeIndex].size(); ++i) {
+            if(solutionVector[nodeIndex][i].getInstant() < currentBestSol.getInstant()) {
+                currentBestSol = solutionVector[nodeIndex][i];
             }
         }
 
@@ -100,7 +100,7 @@ public:
     void pushEmptyState(int nodeIndex)
     {
         TransitAlgorithmState newState = TransitAlgorithmState(nodeIndex);
-        solutionVector.at(nodeIndex).emplace_back(newState);
+        solutionVector[nodeIndex].emplace_back(newState);
     }
 };
 
diff --git a/src/instance/graph/Graph.cpp b/src/instance/graph/Graph.cpp
index 36e2858..17b2159 100644
--- a/src/instance/graph/Graph.cpp
+++ b/src/instance/graph/Graph.cpp
@@ -20,7 +20,7 @@ std::vector<Line> Graph::addLine(Line& line) {
     //Add line stops to nodes
     for(int i = 0; i < line.size(); ++i)
     {
-        nodesVector.at(line.getNode(i)).addBusLine(line, i);
+        nodesVector[line.getNode(i)].addBusLine(line, i);
     }
     //Add transit line to transit lines vector
     transitLines.push_back(line);
@@ -210,7 +210,7 @@ bool Graph::checkLineToNodeLinks() {
         for(auto const& lineStop : node.getPTLinesSet())
         {
             nodeIndexFromLine = lineStop.getLineRef().getNode(lineStop.getStopIndex());
-            nodeFromGraph = &this->nodesVector.at(nodeIndexFromLine);
+            nodeFromGraph = &this->nodesVector[nodeIndexFromLine];
             checkResult &= *nodeFromGraph == node;
         }
     }
@@ -299,13 +299,13 @@ void Graph::parseLineRandomizedSchedule(const DATRow& row, std::mt19937 rng,
 
 }
 
-void Graph::createAndAddEdge(int edgeStartNodeIndex, int edgeEndNodeIndex, double length) {
+void Graph::createAndAddEdge(size_t edgeStartNodeIndex, size_t edgeEndNodeIndex, double length) {
     edgesVector.emplace_back(edgeStartNodeIndex, edgeEndNodeIndex, length);
 
-    Node entryNode = nodesVector.at(edgeStartNodeIndex);
+    Node entryNode = nodesVector[edgeStartNodeIndex];
     entryNode.getOutgoingEdges().emplace_back(edgesVector.size() - 1);
 
-    Node exitNode = nodesVector.at(edgeEndNodeIndex);
+    Node exitNode = nodesVector[edgeEndNodeIndex];
     exitNode.getIncomingEdges().emplace_back(edgesVector.size() - 1);
 }
 
diff --git a/src/instance/graph/Line.cpp b/src/instance/graph/Line.cpp
index a07e307..aebd398 100644
--- a/src/instance/graph/Line.cpp
+++ b/src/instance/graph/Line.cpp
@@ -13,7 +13,7 @@ bool Line::checkSchedules() const{
     checkResult &= _nodes.size() == _timetables.size(); //check we have as many schedules as nodes in our line
 
     int precedingTimeStep = 0;
-    int expectedScheduleSize = !_timetables.empty() ? _timetables.at(0).size() : 0;
+    int expectedScheduleSize = !_timetables.empty() ? _timetables[0].size() : 0;
     for(auto& schedule : _timetables)
     {
         precedingTimeStep = 0; //reinit first timestep to 0
diff --git a/src/instance/graph/Line.h b/src/instance/graph/Line.h
index 3f94c1e..da7fcfb 100644
--- a/src/instance/graph/Line.h
+++ b/src/instance/graph/Line.h
@@ -22,11 +22,11 @@ public:
     [[nodiscard]] const std::string &getLineId() const;
     void setLineId(const std::string &lineId);
     [[nodiscard]] std::vector<int> getNodes() const { return _nodes;};
-    [[nodiscard]] int getNode(size_t index) const { return _nodes.at(index);};
+    [[nodiscard]] int getNode(size_t index) const { return _nodes[index];};
     void addNode(const int node){this->_nodes.emplace_back(node);};
     [[nodiscard]] bool isEmpty() const{return this->_nodes.empty() || _timetables.empty();}
 
-    [[nodiscard]] std::vector<int> getTimetable(size_t pos) const{ return _timetables.at(pos);};
+    [[nodiscard]] std::vector<int> getTimetable(size_t pos) const{ return _timetables[pos];};
     [[nodiscard]] std::vector<std::vector<int>> getTimetables() const{ return _timetables;};
     void addTimetable(const std::vector<int>& timetable) { _timetables.push_back(timetable);};
     void setTimetable(size_t pos, const std::vector<int>& timetable) { _timetables.insert(_timetables.begin() + pos, timetable);};
@@ -38,7 +38,7 @@ public:
      * @return a vector index corresponding to the next valid passage at the given station and after or at the given instant
      */
     [[nodiscard]] size_t findNextScheduledPassage(size_t stationIdx, uint instant) const {
-        return SearchAlgorithms<int>::findNextSortedValue(_timetables.at(stationIdx), instant);
+        return SearchAlgorithms<int>::findNextSortedValue(_timetables[stationIdx], instant);
     }
     /**
      * Returns the instant for the given station at a given schedule position, O(1)
@@ -46,10 +46,10 @@ public:
      * @param scheduleIdx The expected index of our passage
      * @return The instant associated with the given station at the given schedule position
      */
-    [[nodiscard]] int getInstant(size_t stationIdx, size_t scheduleIdx) const { return _timetables.at(stationIdx).at(scheduleIdx); }
+    [[nodiscard]] int getInstant(size_t stationIdx, size_t scheduleIdx) const { return _timetables[stationIdx][scheduleIdx]; }
 
     [[nodiscard]] size_t size() const {return _nodes.size();}
-    [[nodiscard]] size_t scheduleSize() const {return _timetables.empty() ? 0 : _timetables.at(0).size();}
+    [[nodiscard]] size_t scheduleSize() const {return _timetables.empty() ? 0 : _timetables[0].size();}
 
     [[nodiscard]] bool check() const;
     [[nodiscard]] bool checkSchedules() const;
diff --git a/src/routes/vehicle/SAEVRoute.cpp b/src/routes/vehicle/SAEVRoute.cpp
index 03f267e..9ccdc79 100644
--- a/src/routes/vehicle/SAEVRoute.cpp
+++ b/src/routes/vehicle/SAEVRoute.cpp
@@ -20,8 +20,8 @@ SAEVRoute::SAEVRoute(const Graph& graph, const std::vector<Request>& requestList
     //Init Request O/D and Depot start/end key points
     for(size_t i = 0; i < _nbRequest; ++i) {
         //Create key O/D points
-        getOrigin(i) = SAEVKeyPoint(graph, requestList.at(i), true); //origin
-        getDestination(i) = SAEVKeyPoint(graph, requestList.at(i), false); //destination
+        getRequestOrigin(i) = SAEVKeyPoint(graph, requestList[i], true); //origin
+        getRequestDestination(i) = SAEVKeyPoint(graph, requestList[i], false); //destination
         //Link Origins and Destinations
         getRequestOrigin(i).setCounterpart(&getRequestDestination(i));
         getRequestDestination(i).setCounterpart(&getRequestOrigin(i));
@@ -100,15 +100,15 @@ void SAEVRoute::removeRequest(size_t requestId) {
     originKp.setSuccessor(nullptr);
     destinationKp.setPredecessor(nullptr);
     destinationKp.setSuccessor(nullptr);
-    originKp.setMinTw(_requestList->at(requestId).getMinDepartureTw());
-    originKp.setMaxTw(_requestList->at(requestId).getMaxDepartureTw());
-    destinationKp.setMinTw(_requestList->at(requestId).getMinArrivalTw());
-    destinationKp.setMaxTw(_requestList->at(requestId).getMaxArrivalTw());
+    originKp.setMinTw((*_requestList)[requestId].getMinDepartureTw());
+    originKp.setMaxTw((*_requestList)[requestId].getMaxDepartureTw());
+    destinationKp.setMinTw((*_requestList)[requestId].getMinArrivalTw());
+    destinationKp.setMaxTw((*_requestList)[requestId].getMaxArrivalTw());
 }
 
 SAEVRouteChangelist
 SAEVRoute::tryAddRequest(const size_t requestId, SAEVKeyPoint &originRequestPredecessorKP, SAEVKeyPoint &destinationRequestPredecessorKP) {
-    const Request* request = &_requestList->at(requestId);
+    const Request* request = &(*_requestList)[requestId];
     SAEVKeyPoint const* destinationSuccessor = destinationRequestPredecessorKP.getSuccessor();
 
     //Check vehicle capacity
diff --git a/src/routes/vehicle/SAEVRoute.h b/src/routes/vehicle/SAEVRoute.h
index df44ddc..89803fd 100644
--- a/src/routes/vehicle/SAEVRoute.h
+++ b/src/routes/vehicle/SAEVRoute.h
@@ -112,11 +112,11 @@ public:
     BestInsertionQueue getBestInsertionsQueue(size_t requestId, size_t vehicleId);
     BestInsertionQueue getBestFeasibleInsertionsQueue(size_t requestId, size_t vehicleId);
 
-    SAEVKeyPoint& getOrigin(const size_t requestId) { return _route.at(requestId * 2);}
-    SAEVKeyPoint& getDestination(const size_t requestId) { return _route.at(requestId * 2 + 1);}
+    SAEVKeyPoint& getRequestOrigin(const size_t requestId) { return _route[requestId * 2];}
+    SAEVKeyPoint& getRequestDestination(const size_t requestId) { return _route[requestId * 2 + 1];}
 
-    SAEVKeyPoint& getOriginDepot(const size_t vehicleId) { return _route.at(_nbRequest*2 + vehicleId*2);}
-    SAEVKeyPoint& getDestinationDepot(const size_t vehicleId) { return _route.at(_nbRequest*2 + vehicleId*2 + 1);}
+    SAEVKeyPoint& getOriginDepot(const size_t vehicleId) { return _route[_nbRequest*2 + vehicleId*2];}
+    SAEVKeyPoint& getDestinationDepot(const size_t vehicleId) { return _route[_nbRequest*2 + vehicleId*2 + 1];}
 
     [[nodiscard]] size_t getRequestOriginRouteIdx(const size_t requestId) const { return requestId * 2;}
     [[nodiscard]] size_t getRequestDestinationRouteIdx(const size_t requestId) const { return requestId * 2 + 1;}
diff --git a/test/src/LineUnitTests.cpp b/test/src/LineUnitTests.cpp
index bc8b3c4..04f90f0 100644
--- a/test/src/LineUnitTests.cpp
+++ b/test/src/LineUnitTests.cpp
@@ -18,7 +18,7 @@ TEST(LineTests, LineGenerationScheduleOrder) {
     for(const auto& line : graphFromSingleFile.getPTLines()) {
         for(const auto& schedule : line.getTimetables()) {
             for(size_t i = 0; i < line.scheduleSize(); ++i) {
-                ASSERT_GT(schedule.at(i), schedule.at(i + 1)); //assert schedule value order
+                ASSERT_GT(schedule[i], schedule[i + 1]); //assert schedule value order
             }
         }
         ASSERT_TRUE(line.checkSchedules()); //assert line schedule check function is coherent with our preceding assertion
-- 
GitLab


From 60c4f6714f95956f6ad63a11c77cbca54fec0424 Mon Sep 17 00:00:00 2001
From: Romain BERNARD <romain.bernard@uca.fr>
Date: Fri, 12 Jul 2024 18:00:12 +0200
Subject: [PATCH 140/327] Refactor best insertions heuristic API to return a
 changelist usable by higher level heuristics

---
 .../Heuristics/BestInsertionHeuristic.cpp     | 32 ++++++------
 .../DARP/Heuristics/BestInsertionHeuristic.h  | 11 +++-
 src/routes/vehicle/BestInsertionQueue.h       |  9 ++++
 src/routes/vehicle/SAEVRoute.cpp              | 52 +++++++++----------
 src/routes/vehicle/SAEVRoute.h                |  8 +--
 .../propagation/SAEVRouteChangelist.cpp       | 18 +++++--
 .../vehicle/propagation/SAEVRouteChangelist.h | 28 +++++++---
 test/src/BestInsertionHeuristicDebug.cpp      | 20 +++----
 8 files changed, 110 insertions(+), 68 deletions(-)

diff --git a/src/algorithm/DARP/Heuristics/BestInsertionHeuristic.cpp b/src/algorithm/DARP/Heuristics/BestInsertionHeuristic.cpp
index 3f2cbc7..3ed37a6 100644
--- a/src/algorithm/DARP/Heuristics/BestInsertionHeuristic.cpp
+++ b/src/algorithm/DARP/Heuristics/BestInsertionHeuristic.cpp
@@ -11,18 +11,22 @@
 #define DEBUG_MSG(str) do { } while ( false )
 #endif
 
-bool BestInsertionHeuristic::tryVehicleBestInsertion(size_t requestId, size_t vehicleId, SAEVRoute& route) {
-    BestInsertionQueue bestInsertionsQueue = route.getBestFeasibleInsertionsQueue(requestId, vehicleId); //TODO: check perfs between BestInsertionsQueue vs BestFeasibleInsertionsQueue
+SAEVRouteChangelist BestInsertionHeuristic::tryVehicleBestInsertion(size_t requestId, size_t vehicleId, SAEVRoute& route) {
+    BestInsertionQueue bestInsertionsQueue = route.getBestFeasibleInsertionsQueue(requestId, vehicleId);
+    return tryVehicleBestInsertion(bestInsertionsQueue, route);
+}
+
+SAEVRouteChangelist BestInsertionHeuristic::tryVehicleBestInsertion(BestInsertionQueue& bestInsertionsQueue, SAEVRoute& route) {
     bool bestInsertionFound = false;
     BestRequestInsertion currentBestInsertion;
+    size_t requestId = bestInsertionsQueue.getRequestId();
+    SAEVRouteChangelist lastInsertionChangelist(&route, requestId);
 
     DEBUG_MSG("Trying to insert request " + std::to_string(requestId) + " in vehicle " + std::to_string(vehicleId) + " queue size : " + std::to_string(bestInsertionsQueue.size()));
     while(!bestInsertionsQueue.empty() && !bestInsertionFound) {
         currentBestInsertion = bestInsertionsQueue.topAndPop();
         DEBUG_MSG("Trying insertion " + currentBestInsertion.to_string() + ", remaining : " + std::to_string(bestInsertionsQueue.size()));
-        SAEVRouteChangelist lastInsertionChangelist = route.tryAddRequest(requestId,
-                                                                          *currentBestInsertion.getOriginInsertionKp(),
-                                                                          *currentBestInsertion.getDestinationInsertionKp());
+        lastInsertionChangelist = route.tryAddRequest(requestId,currentBestInsertion.getOriginInsertionKp(),currentBestInsertion.getDestinationInsertionKp());
         //If insertion worked, signal it, otherwise revert changes
         if(lastInsertionChangelist.getStatus() == SAEVRouteChangelist::InsertionStatus::SUCCESS) {
             DEBUG_MSG("\tBest valid insertion found !\n\t\t" + currentBestInsertion.to_string());
@@ -32,7 +36,8 @@ bool BestInsertionHeuristic::tryVehicleBestInsertion(size_t requestId, size_t ve
             lastInsertionChangelist.revertChanges();
         }
     }
-    return bestInsertionFound;
+    //FIXME : use a pointer and return it via dereferencing ? Create a dummy constructor ? (I think I'll go with the latter)
+    return lastInsertionChangelist;
 }
 
 size_t BestInsertionHeuristic::doBestRequestInsertionForRoute(size_t requestId, SAEVRoute& route) {
@@ -40,7 +45,7 @@ size_t BestInsertionHeuristic::doBestRequestInsertionForRoute(size_t requestId,
     bool insertionSuccess{false};
     //Iteratively try inserting in every active vehicle and the first inactive vehicle
     do {
-        insertionSuccess = tryVehicleBestInsertion(requestId, vehicleId, route);
+        insertionSuccess = tryVehicleBestInsertion(requestId, vehicleId, route).success();
     } while(!insertionSuccess && ++vehicleId <= route.getLastActiveVehicleId() + 1);
 
     //Update last active vehicle ID
@@ -52,16 +57,13 @@ size_t BestInsertionHeuristic::doBestRequestInsertionForRoute(size_t requestId,
     return vehicleId;
 }
 
-size_t BestInsertionHeuristic::tryBestRequestInsertionInActiveVehicle(size_t requestId, SAEVRoute &route) {
+SAEVRouteChangelist BestInsertionHeuristic::tryBestRequestInsertionInActiveVehicle(size_t requestId, SAEVRoute &route) {
     size_t vehicleId = 0;
-    bool insertionSuccess{false};
+    BestInsertionQueue bestInsertions{requestId};
     //Iteratively try inserting in every active vehicle and the first inactive vehicle
-    while(!insertionSuccess && ++vehicleId <= route.getLastActiveVehicleId() + 1) {
-        insertionSuccess = tryVehicleBestInsertion(requestId, vehicleId, route);
+    while(++vehicleId <= route.getLastActiveVehicleId() + 1) {
+        route.getBestFeasibleInsertionsQueue(bestInsertions, requestId, vehicleId);
     }
 
-    if(insertionSuccess)
-        return vehicleId;
-    else
-        return route.getLastActiveVehicleId() + 1;
+    return tryVehicleBestInsertion(requestId, vehicleId, route);
 }
diff --git a/src/algorithm/DARP/Heuristics/BestInsertionHeuristic.h b/src/algorithm/DARP/Heuristics/BestInsertionHeuristic.h
index 258f3bf..95001b7 100644
--- a/src/algorithm/DARP/Heuristics/BestInsertionHeuristic.h
+++ b/src/algorithm/DARP/Heuristics/BestInsertionHeuristic.h
@@ -27,7 +27,7 @@ public:
      * @param route the route structure in which the request will be inserted
      * @return The ID of the active vehicle in which our request was inserted, or the ID of the most favourable inactive vehicle
      */
-    static size_t tryBestRequestInsertionInActiveVehicle(size_t requestId, SAEVRoute& route);
+    static SAEVRouteChangelist tryBestRequestInsertionInActiveVehicle(size_t requestId, SAEVRoute& route);
     /**
      * Iteratively tests best insertions wrt scoring function (detour) in the given vehicle and route
      * @param requestId ID of the request to insert in the vehicle
@@ -35,7 +35,14 @@ public:
      * @param route
      * @return true iff the request was inserted in the vehicle, false if no best insertion yielded a possible insertion
      */
-    static bool tryVehicleBestInsertion(size_t requestId, size_t vehicleId, SAEVRoute& route);
+    static SAEVRouteChangelist tryVehicleBestInsertion(size_t requestId, size_t vehicleId, SAEVRoute& route);
+    /**
+     * Tries the best insertions
+     * @param bestInsertionsQueue
+     * @param route
+     * @return
+     */
+    static SAEVRouteChangelist tryVehicleBestInsertion(BestInsertionQueue& bestInsertionsQueue, SAEVRoute& route);
 
 
     /** TODO Implement those to prevent trying every single best insertion
diff --git a/src/routes/vehicle/BestInsertionQueue.h b/src/routes/vehicle/BestInsertionQueue.h
index 7a6071b..25b077f 100644
--- a/src/routes/vehicle/BestInsertionQueue.h
+++ b/src/routes/vehicle/BestInsertionQueue.h
@@ -15,12 +15,21 @@ private:
     size_t _vehicleId{std::numeric_limits<size_t>::max()};
 
 public:
+    explicit BestInsertionQueue(size_t requestId) : _requestId(requestId) {}
     BestInsertionQueue(size_t requestId, size_t vehicleId) : _requestId(requestId), _vehicleId(vehicleId) {}
 
     BestInsertionQueue(size_t requestId, size_t vehicleId, size_t nbRequests) : BestInsertionQueue(requestId, vehicleId) {
         c.reserve(nbRequests^2);
     }
 
+    [[nodiscard]] size_t getVehicleId() const {
+        return _vehicleId;
+    }
+
+    [[nodiscard]] size_t getRequestId() const {
+        return _requestId;
+    }
+
     /**
      * Returns and removes the top value from the priority queue
      * @return The top value in the priority queue
diff --git a/src/routes/vehicle/SAEVRoute.cpp b/src/routes/vehicle/SAEVRoute.cpp
index 9ccdc79..fc42ed2 100644
--- a/src/routes/vehicle/SAEVRoute.cpp
+++ b/src/routes/vehicle/SAEVRoute.cpp
@@ -37,34 +37,34 @@ SAEVRoute::SAEVRoute(const Graph& graph, const std::vector<Request>& requestList
     }
 }
 
-void SAEVRoute::insertRequest(size_t requestId, SAEVKeyPoint &originRequestPredecessorKP, SAEVKeyPoint &destinationRequestPredecessorKP) {
+void SAEVRoute::insertRequest(size_t requestId, SAEVKeyPoint * originRequestPredecessorKP, SAEVKeyPoint * destinationRequestPredecessorKP) {
     SAEVKeyPoint& originKp = getRequestOrigin(requestId);
     SAEVKeyPoint& destinationKp = getRequestDestination(requestId);
 
-    SAEVKeyPoint *originSuccKp = originRequestPredecessorKP.getSuccessor();
-    SAEVKeyPoint *destinationSuccKp = destinationRequestPredecessorKP.getSuccessor();
+    SAEVKeyPoint *originSuccKp = originRequestPredecessorKP->getSuccessor();
+    SAEVKeyPoint *destinationSuccKp = destinationRequestPredecessorKP->getSuccessor();
 
     if(originRequestPredecessorKP != destinationRequestPredecessorKP) {
         //Set values for O/D KPs
-        originKp.setPredecessor(&originRequestPredecessorKP);
+        originKp.setPredecessor(originRequestPredecessorKP);
         originKp.setSuccessor(originSuccKp);
-        destinationKp.setPredecessor(&destinationRequestPredecessorKP);
+        destinationKp.setPredecessor(destinationRequestPredecessorKP);
         destinationKp.setSuccessor(destinationSuccKp);
 
         //Set values for predecessors/successors
-        originRequestPredecessorKP.setSuccessor(&originKp);
+        originRequestPredecessorKP->setSuccessor(&originKp);
         originSuccKp->setPredecessor(&originKp);
-        destinationRequestPredecessorKP.setSuccessor(&destinationKp);
+        destinationRequestPredecessorKP->setSuccessor(&destinationKp);
         destinationSuccKp->setPredecessor(&destinationKp);
     } else {
         //Set values for O/D KPs
-        originKp.setPredecessor(&originRequestPredecessorKP);
+        originKp.setPredecessor(originRequestPredecessorKP);
         originKp.setSuccessor(&destinationKp);
         destinationKp.setPredecessor(&originKp);
         destinationKp.setSuccessor(destinationSuccKp);
 
         //Set values for predecessors/successors
-        originRequestPredecessorKP.setSuccessor(&originKp);
+        originRequestPredecessorKP->setSuccessor(&originKp);
         originSuccKp->setPredecessor(&destinationKp);
     }
     //Once insertion is done, update weights on the route
@@ -107,12 +107,12 @@ void SAEVRoute::removeRequest(size_t requestId) {
 }
 
 SAEVRouteChangelist
-SAEVRoute::tryAddRequest(const size_t requestId, SAEVKeyPoint &originRequestPredecessorKP, SAEVKeyPoint &destinationRequestPredecessorKP) {
+SAEVRoute::tryAddRequest(const size_t requestId, SAEVKeyPoint * originRequestPredecessorKP, SAEVKeyPoint * destinationRequestPredecessorKP) {
     const Request* request = &(*_requestList)[requestId];
-    SAEVKeyPoint const* destinationSuccessor = destinationRequestPredecessorKP.getSuccessor();
+    SAEVKeyPoint const* destinationSuccessor = destinationRequestPredecessorKP->getSuccessor();
 
     //Check vehicle capacity
-    SAEVKeyPoint const* currentKP = &originRequestPredecessorKP;
+    SAEVKeyPoint const* currentKP = originRequestPredecessorKP;
     do {
         if(currentKP->getCurrentOccupation() + request->getWeight() > SAEVehicle::getCapacity()) {
             DEBUG_MSG("WEIGHT VIOLATION : request weight = " + std::to_string(request->getWeight()) + " incompatible KP = " + currentKP->to_string());
@@ -122,7 +122,7 @@ SAEVRoute::tryAddRequest(const size_t requestId, SAEVKeyPoint &originRequestPred
     } while (currentKP != destinationSuccessor && currentKP != nullptr);
 
     //Do basic checks on neighbouring nodes from our Origin/Destination insertion points
-    bool isValid = doNeighbouringTWChecks(requestId, &originRequestPredecessorKP, &destinationRequestPredecessorKP);
+    bool isValid = doNeighbouringTWChecks(requestId, originRequestPredecessorKP, destinationRequestPredecessorKP);
 
     if(isValid) {
         return insertRequestWithPropagation(requestId, originRequestPredecessorKP, destinationRequestPredecessorKP);
@@ -180,8 +180,8 @@ SAEVRoute::doNeighbouringTWChecks(const size_t requestId, const SAEVKeyPoint *or
     return true;
 }
 
-SAEVRouteChangelist SAEVRoute::insertRequestWithPropagation(const size_t requestId, SAEVKeyPoint &originRequestPredecessorKP,
-                                                            SAEVKeyPoint &destinationRequestPredecessorKP) {
+SAEVRouteChangelist SAEVRoute::insertRequestWithPropagation(const size_t requestId, SAEVKeyPoint * originRequestPredecessorKP,
+                                                            SAEVKeyPoint * destinationRequestPredecessorKP) {
     //Init changelist
     SAEVRouteChangelist changelist{this, requestId, originRequestPredecessorKP, destinationRequestPredecessorKP, SAEVRouteChangelist::InsertionStatus::FAILURE_MIN};
     //Properly insert the request to facilitate constraint propagation
@@ -291,31 +291,31 @@ SAEVRouteChangelist SAEVRoute::insertRequestWithPropagation(const size_t request
     return changelist;
 }
 
-double SAEVRoute::getDetourScore(const size_t requestId, const SAEVKeyPoint &originRequestPredecessorKP,
-                                 const SAEVKeyPoint &destinationRequestPredecessorKP) {
+double SAEVRoute::getDetourScore(const size_t requestId, const SAEVKeyPoint * originRequestPredecessorKP,
+                                 const SAEVKeyPoint * destinationRequestPredecessorKP) {
     double score;
     const SAEVKeyPoint& originKP = getRequestOrigin(requestId);
     const SAEVKeyPoint& destinationKP = getRequestDestination(requestId);
-    const SAEVKeyPoint* originSuccKP = originRequestPredecessorKP.getSuccessor();
-    const SAEVKeyPoint* destinationSuccKP = destinationRequestPredecessorKP.getSuccessor();
+    const SAEVKeyPoint* originSuccKP = originRequestPredecessorKP->getSuccessor();
+    const SAEVKeyPoint* destinationSuccKP = destinationRequestPredecessorKP->getSuccessor();
 
     if(originRequestPredecessorKP != destinationRequestPredecessorKP) {
-        const SAEVKeyPoint* destinationPredKP = &destinationRequestPredecessorKP;
+        const SAEVKeyPoint* destinationPredKP = destinationRequestPredecessorKP;
 
         //Origin Detour
-        score = _graph->getShortestSAEVPath(originRequestPredecessorKP.getNodeIndex(), originKP.getNodeIndex()) //T(Pred(O), D)
+        score = _graph->getShortestSAEVPath(originRequestPredecessorKP->getNodeIndex(), originKP.getNodeIndex()) //T(Pred(O), D)
                 + _graph->getShortestSAEVPath(originKP.getNodeIndex(), originSuccKP->getNodeIndex()) //T(O, Succ(D))
-                - _graph->getShortestSAEVPath(originRequestPredecessorKP.getNodeIndex(), originSuccKP->getNodeIndex()); //T(Pred(O), Succ(O))
+                - _graph->getShortestSAEVPath(originRequestPredecessorKP->getNodeIndex(), originSuccKP->getNodeIndex()); //T(Pred(O), Succ(O))
 
         //Destination Detour
         score += _graph->getShortestSAEVPath(destinationPredKP->getNodeIndex(), destinationKP.getNodeIndex()) //T(Pred(D), D))
                 + _graph->getShortestSAEVPath(destinationKP.getNodeIndex(), destinationSuccKP->getNodeIndex()) //T(D, Succ(D)))
                 - _graph->getShortestSAEVPath(destinationPredKP->getNodeIndex(), destinationSuccKP->getNodeIndex()); //T(Pred(D), Succ(D)))
     } else {
-        score = _graph->getShortestSAEVPath(originRequestPredecessorKP.getNodeIndex(), originKP.getNodeIndex()) //T(Pred(O), O)
+        score = _graph->getShortestSAEVPath(originRequestPredecessorKP->getNodeIndex(), originKP.getNodeIndex()) //T(Pred(O), O)
                 + _graph->getShortestSAEVPath(originKP.getNodeIndex(), destinationKP.getNodeIndex()) //T(O, D)
                 + _graph->getShortestSAEVPath(destinationKP.getNodeIndex(), destinationSuccKP->getNodeIndex()) //T(D, Succ(D))
-                - _graph->getShortestSAEVPath(originRequestPredecessorKP.getNodeIndex(), destinationSuccKP->getNodeIndex()); //T(Pred(O), Succ(D))
+                - _graph->getShortestSAEVPath(originRequestPredecessorKP->getNodeIndex(), destinationSuccKP->getNodeIndex()); //T(Pred(O), Succ(D))
     }
     return score;
 }
@@ -384,7 +384,7 @@ BestInsertionQueue SAEVRoute::getBestInsertionsQueue(size_t requestId, size_t ve
     //iterate over possible origin/destination pairs for the given vehicle
     while(originInsertionKeyPoint->getSuccessor() != nullptr) {
         while(destinationInsertionKeyPoint->getSuccessor() != nullptr) {
-            score = getDetourScore(requestId, *originInsertionKeyPoint, *destinationInsertionKeyPoint);
+            score = getDetourScore(requestId, originInsertionKeyPoint, destinationInsertionKeyPoint);
             bestInsertionQueue.emplace(originInsertionKeyPoint, destinationInsertionKeyPoint, score);
             destinationInsertionKeyPoint = destinationInsertionKeyPoint->getSuccessor();
         }
@@ -415,7 +415,7 @@ BestInsertionQueue SAEVRoute::getBestInsertionsQueue(size_t requestId, size_t ve
     while(originInsertionKeyPoint->getSuccessor() != nullptr) {
         while(destinationInsertionKeyPoint->getSuccessor() != nullptr) {
             if(doNeighbouringTWChecks(requestId,originInsertionKeyPoint, destinationInsertionKeyPoint)) {
-                score = getDetourScore(requestId, *originInsertionKeyPoint, *destinationInsertionKeyPoint);
+                score = getDetourScore(requestId, originInsertionKeyPoint, destinationInsertionKeyPoint);
                 bestInsertionQueue.emplace(originInsertionKeyPoint, destinationInsertionKeyPoint, score);
             }
             destinationInsertionKeyPoint = destinationInsertionKeyPoint->getSuccessor();
diff --git a/src/routes/vehicle/SAEVRoute.h b/src/routes/vehicle/SAEVRoute.h
index 89803fd..23cf745 100644
--- a/src/routes/vehicle/SAEVRoute.h
+++ b/src/routes/vehicle/SAEVRoute.h
@@ -39,7 +39,7 @@ public:
      * @param originRequestPredecessorKP Identifier/index in the route key point vector for the request origin or destination that will precede the origin of the request we want to insert
      * @param destinationRequestPredecessorKP Identifier/index in the route key point vector for the request origin or destination that will precede the destination of the request we want to insert
      */
-    void insertRequest(size_t requestId, SAEVKeyPoint &originRequestPredecessorKP, SAEVKeyPoint &destinationRequestPredecessorKP);
+    void insertRequest(size_t requestId, SAEVKeyPoint * originRequestPredecessorKP, SAEVKeyPoint * destinationRequestPredecessorKP);
 
     /**
      * Raw request removal method. Public for debug purposes, but should effectively never be called by an outside member
@@ -70,7 +70,7 @@ public:
      * @param destinationRequestPredecessorKP Identifier/index in the route key point vector for the request origin or destination that will precede our request's destination in the route
      * @return A change list with every min/max bound change made during the tryAdd procedure and a score estimating insertion quality (lower is better)
      */
-    SAEVRouteChangelist tryAddRequest(const size_t requestId, SAEVKeyPoint &originRequestPredecessorKP, SAEVKeyPoint &destinationRequestPredecessorKP);
+    SAEVRouteChangelist tryAddRequest(const size_t requestId, SAEVKeyPoint * originRequestPredecessorKP, SAEVKeyPoint * destinationRequestPredecessorKP);
 
     /**
      * Verifies time window constraints on our request's origin/destination's projected neighbour, aka originPredecessor/destinationPredecessor and their successor.
@@ -97,7 +97,7 @@ public:
      * @param destinationRequestPredecessorKP Identifier/index in the route key point vector for the request origin or destination that will precede our request's destination in the route
      * @return A change list with every min/max bound change made during the insert procedure and a score estimating insertion quality (lower is better)
      */
-    SAEVRouteChangelist insertRequestWithPropagation(const size_t requestId, SAEVKeyPoint &originRequestPredecessorKP, SAEVKeyPoint &destinationRequestPredecessorKP);
+    SAEVRouteChangelist insertRequestWithPropagation(const size_t requestId, SAEVKeyPoint * originRequestPredecessorKP, SAEVKeyPoint * destinationRequestPredecessorKP);
 
     /**
      * Returns a score value equivalent to the detour implied by insertion of a request after the two given key point indexes.
@@ -107,7 +107,7 @@ public:
      * @param destinationRequestPredecessorKP Identifier/index in the route key point vector for the request origin or destination that will precede our request's destination in the route
      * @return
      */
-    double getDetourScore(const size_t requestId, const SAEVKeyPoint &originRequestPredecessorKP, const SAEVKeyPoint &destinationRequestPredecessorKP);
+    double getDetourScore(const size_t requestId, const SAEVKeyPoint * originRequestPredecessorKP, const SAEVKeyPoint * destinationRequestPredecessorKP);
 
     BestInsertionQueue getBestInsertionsQueue(size_t requestId, size_t vehicleId);
     BestInsertionQueue getBestFeasibleInsertionsQueue(size_t requestId, size_t vehicleId);
diff --git a/src/routes/vehicle/propagation/SAEVRouteChangelist.cpp b/src/routes/vehicle/propagation/SAEVRouteChangelist.cpp
index 3e05775..1e47d54 100644
--- a/src/routes/vehicle/propagation/SAEVRouteChangelist.cpp
+++ b/src/routes/vehicle/propagation/SAEVRouteChangelist.cpp
@@ -44,11 +44,11 @@ size_t SAEVRouteChangelist::getRequestId() const {
     return _requestId;
 }
 
-const SAEVKeyPoint &SAEVRouteChangelist::getOriginPredecessorKP() const {
+const SAEVKeyPoint * SAEVRouteChangelist::getOriginPredecessorKP() const {
     return _originPredecessorKP;
 }
 
-const SAEVKeyPoint &SAEVRouteChangelist::getDestinationPredecessorKP() const {
+const SAEVKeyPoint * SAEVRouteChangelist::getDestinationPredecessorKP() const {
     return _destinationPredecessorKP;
 }
 
@@ -81,7 +81,7 @@ SAEVRouteChangelist::InsertionStatus SAEVRouteChangelist::getCurrentStatus() con
 }
 
 bool SAEVRouteChangelist::shouldUndoInsertion() const {
-    return _currentStatus > InsertionStatus::FAILURE_DELTA_MAX;
+    return _currentStatus < InsertionStatus::FAILURE_PRECONDITION_TW;
 }
 
 void SAEVRouteChangelist::setStatus(SAEVRouteChangelist::InsertionStatus status) {
@@ -91,3 +91,15 @@ void SAEVRouteChangelist::setStatus(SAEVRouteChangelist::InsertionStatus status)
 void SAEVRouteChangelist::setCurrentStatus(SAEVRouteChangelist::InsertionStatus currentStatus) {
     _currentStatus = currentStatus;
 }
+
+size_t SAEVRouteChangelist::getVehicleId() const {
+    return _vehicleId;
+}
+
+void SAEVRouteChangelist::setVehicleId(size_t vehicleId) {
+    _vehicleId = vehicleId;
+}
+
+bool SAEVRouteChangelist::success() {
+    return _status == InsertionStatus::SUCCESS;
+}
diff --git a/src/routes/vehicle/propagation/SAEVRouteChangelist.h b/src/routes/vehicle/propagation/SAEVRouteChangelist.h
index 8ea0747..b9eae10 100644
--- a/src/routes/vehicle/propagation/SAEVRouteChangelist.h
+++ b/src/routes/vehicle/propagation/SAEVRouteChangelist.h
@@ -27,17 +27,24 @@ public:
         CHANGELIST_REVERTED
     };
 private:
-    SAEVRoute * const _routePtr;
-    const size_t _requestId;
-    SAEVKeyPoint& _originPredecessorKP;
-    SAEVKeyPoint& _destinationPredecessorKP;
+    //Change target info
+    SAEVRoute * _routePtr{};
+    size_t _requestId{};
+    size_t _vehicleId{};
+    SAEVKeyPoint* _originPredecessorKP{};
+    SAEVKeyPoint* _destinationPredecessorKP{};
+
+    //Changelist specific info (aka, if this ever becomes a template class, *this* is what will go in the generic interface)
     std::vector<SAEVRouteChange> _changelist{};
     double _score{std::numeric_limits<double>::infinity()}; //Init score to infinity
 
-    InsertionStatus _status; //Status on changelist creation
+    InsertionStatus _status{InsertionStatus::CHANGELIST_REVERTED}; //Status on changelist creation
     InsertionStatus _currentStatus; //Updated status after applying/reverting changelist
 
 public:
+
+    SAEVRouteChangelist(SAEVRoute * routePtr, size_t requestId) : _routePtr(routePtr), _requestId(requestId) {}
+
     /**
      * Initializes a change list to memorize every iterative modification made during constraint propagation
      * @param routePtr a pointer to the route the constraint propagation was applied on. revert/apply operations will be done on this route
@@ -45,9 +52,10 @@ public:
      * @param originPredecessorKP The index of the request our origin will be inserted after
      * @param destinationPredecessorKP The index of the request our destination will be inserted after
      */
-    explicit SAEVRouteChangelist(SAEVRoute * const routePtr, const size_t requestId, SAEVKeyPoint &originPredecessorKP, SAEVKeyPoint &destinationPredecessorKP, InsertionStatus status)
+    explicit SAEVRouteChangelist(SAEVRoute * const routePtr, const size_t requestId, SAEVKeyPoint* originPredecessorKP, SAEVKeyPoint* destinationPredecessorKP, InsertionStatus status)
     : _routePtr(routePtr), _requestId(requestId), _originPredecessorKP(originPredecessorKP), _destinationPredecessorKP(destinationPredecessorKP), _status(status), _currentStatus(status) {};
 
+
     /**
      * @return A pointer to the route this change list applies/reverts changes to
      */
@@ -59,12 +67,16 @@ public:
      */
     [[nodiscard]] size_t getRequestId() const;
 
-    [[nodiscard]] const SAEVKeyPoint &getOriginPredecessorKP() const;
+    [[nodiscard]] size_t getVehicleId() const;
+    void setVehicleId(size_t vehicleId);
+
+    [[nodiscard]] const SAEVKeyPoint * getOriginPredecessorKP() const;
 
-    [[nodiscard]] const SAEVKeyPoint &getDestinationPredecessorKP() const;
+    [[nodiscard]] const SAEVKeyPoint * getDestinationPredecessorKP() const;
 
     [[nodiscard]] InsertionStatus getStatus() const;
     void setStatus(InsertionStatus status);
+    [[nodiscard]] bool success();
 
     [[nodiscard]] InsertionStatus getCurrentStatus() const;
     void setCurrentStatus(InsertionStatus currentStatus);
diff --git a/test/src/BestInsertionHeuristicDebug.cpp b/test/src/BestInsertionHeuristicDebug.cpp
index 45d2a0a..e06145d 100644
--- a/test/src/BestInsertionHeuristicDebug.cpp
+++ b/test/src/BestInsertionHeuristicDebug.cpp
@@ -27,12 +27,12 @@ TEST(BestInsertionHeuristicDebug, DebugBaseInstance) {
     std::cout << "------------------Fin parsing instance et route-------------------" << std::endl << std::endl;
     int vehicleId = 1;
     assert(routesContainer.checkRouteTimeWindows(vehicleId));
-    SAEVRouteChangelist req0Changelist = routesContainer.tryAddRequest(0, routesContainer.getOriginDepot(vehicleId), routesContainer.getOriginDepot(1));
+    SAEVRouteChangelist req0Changelist = routesContainer.tryAddRequest(0, &routesContainer.getOriginDepot(vehicleId), &routesContainer.getOriginDepot(1));
     std::cout << routesContainer.to_string(vehicleId) << std::endl;
     assert(routesContainer.checkRouteTimeWindows(vehicleId));
     std::cout << "------------------------------------------------------------------" << std::endl;
-    SAEVRouteChangelist req1Changelist = routesContainer.tryAddRequest(1, routesContainer.getOriginDepot(vehicleId),
-                                                                       routesContainer.getRequestDestination(0));
+    SAEVRouteChangelist req1Changelist = routesContainer.tryAddRequest(1, &routesContainer.getOriginDepot(vehicleId),
+                                                                       &routesContainer.getRequestDestination(0));
     std::cout << routesContainer.to_string(vehicleId) << std::endl << std::endl;
     assert(!routesContainer.checkRouteTimeWindows(vehicleId));
     std::cout << "------------------------------------------------------------------" << std::endl;
@@ -60,21 +60,21 @@ TEST(BestInsertionQueueDebug, DebugInstanceAlain) {
 
     //Vehicle 1 insertions
     BestInsertionQueue biQueue = routesContainer.getBestInsertionsQueue(0,0);
-    routesContainer.tryAddRequest(0,routesContainer.getOriginDepot(0),routesContainer.getOriginDepot(0));
+    routesContainer.tryAddRequest(0,&routesContainer.getOriginDepot(0),&routesContainer.getOriginDepot(0));
     biQueue = routesContainer.getBestFeasibleInsertionsQueue(1,0);
-    routesContainer.tryAddRequest(1, routesContainer.getRequestOrigin(0), routesContainer.getRequestOrigin(0));
+    routesContainer.tryAddRequest(1, &routesContainer.getRequestOrigin(0), &routesContainer.getRequestOrigin(0));
     biQueue = routesContainer.getBestFeasibleInsertionsQueue(2,0);
-    SAEVRouteChangelist cl = routesContainer.tryAddRequest(2, routesContainer.getRequestOrigin(1),
-                                                           routesContainer.getRequestDestination(1));
+    SAEVRouteChangelist cl = routesContainer.tryAddRequest(2, &routesContainer.getRequestOrigin(1),
+                                                           &routesContainer.getRequestDestination(1));
     biQueue = routesContainer.getBestFeasibleInsertionsQueue(3,0);
 
     //Vehicle 2 insertions
     biQueue = routesContainer.getBestFeasibleInsertionsQueue(5,1);
-    routesContainer.tryAddRequest(5,routesContainer.getOriginDepot(1),routesContainer.getOriginDepot(1));
+    routesContainer.tryAddRequest(5,&routesContainer.getOriginDepot(1),&routesContainer.getOriginDepot(1));
     biQueue = routesContainer.getBestFeasibleInsertionsQueue(4,1);
-    routesContainer.tryAddRequest(4,routesContainer.getOriginDepot(1), routesContainer.getRequestDestination(5));
+    routesContainer.tryAddRequest(4,&routesContainer.getOriginDepot(1), &routesContainer.getRequestDestination(5));
     biQueue = routesContainer.getBestFeasibleInsertionsQueue(3,1);
-    routesContainer.tryAddRequest(3,routesContainer.getOriginDepot(1), routesContainer.getRequestOrigin(4));
+    routesContainer.tryAddRequest(3,&routesContainer.getOriginDepot(1), &routesContainer.getRequestOrigin(4));
     biQueue = routesContainer.getBestFeasibleInsertionsQueue(0,1);
     biQueue = routesContainer.getBestFeasibleInsertionsQueue(1,1);
     biQueue = routesContainer.getBestFeasibleInsertionsQueue(2,1);
-- 
GitLab


From 0675808eae6730a0a38c3ce70ac5163a79594373 Mon Sep 17 00:00:00 2001
From: Romain BERNARD <romain.bernard@uca.fr>
Date: Fri, 12 Jul 2024 18:00:58 +0200
Subject: [PATCH 141/327] use std range

---
 src/ShortestPath/Transit/TransitShortestPathContainer.cpp | 3 ++-
 src/utils/SearchAlgorithms.h                              | 5 +++--
 2 files changed, 5 insertions(+), 3 deletions(-)

diff --git a/src/ShortestPath/Transit/TransitShortestPathContainer.cpp b/src/ShortestPath/Transit/TransitShortestPathContainer.cpp
index 1bac7e5..71e74eb 100644
--- a/src/ShortestPath/Transit/TransitShortestPathContainer.cpp
+++ b/src/ShortestPath/Transit/TransitShortestPathContainer.cpp
@@ -2,6 +2,7 @@
 // Created by romain on 13/03/24.
 //
 
+#include <algorithm>
 #include "TransitShortestPathContainer.h"
 #include "TransitStateContainer.h"
 
@@ -26,7 +27,7 @@ void TransitShortestPathContainer::addShortestPathCollection(int startNodeIndex,
 
 std::vector<std::pair<int, std::vector<TransitShortestPath>>>::iterator
 TransitShortestPathContainer::getShortestPathsFromTime(int startNodeIndex, int earliestStartInstant) {
-    const auto& iterator = std::lower_bound(container[startNodeIndex].begin(), container[startNodeIndex].end(),
+    const auto& iterator = std::ranges::lower_bound(container[startNodeIndex],
                                             std::pair<int, std::vector<TransitShortestPath>>(earliestStartInstant, {}));
 
     return iterator;
diff --git a/src/utils/SearchAlgorithms.h b/src/utils/SearchAlgorithms.h
index 90214d2..cd987ee 100644
--- a/src/utils/SearchAlgorithms.h
+++ b/src/utils/SearchAlgorithms.h
@@ -7,6 +7,7 @@
 
 
 #include <vector>
+#include <algorithm>
 
 template <typename Comparable>
 class SearchAlgorithms {
@@ -18,7 +19,7 @@ public:
      * @return the size of the vector if all vector values are lower than our search, the index of the first larger or equal value otherwise
      */
     static size_t findNextSortedValue(std::vector<Comparable> sortedVector, Comparable value) {
-        auto iterator = std::lower_bound(sortedVector.begin(), sortedVector.end(), value);
+        auto iterator = std::ranges::lower_bound(sortedVector, value);
         return std::distance(sortedVector.begin(), iterator);
     }
 
@@ -29,7 +30,7 @@ public:
      * @return -1 if the exact value hasn't been found or the index of the value if it's been found
      */
     static size_t vectorBinarySearch(std::vector<Comparable> sortedVector, Comparable value) {
-        auto iterator = std::lower_bound(sortedVector.begin(), sortedVector.end(), value);
+        auto iterator = std::ranges::lower_bound(sortedVector, value);
         if (iterator == sortedVector.end() || *iterator != value) {
             return -1;
         } else {
-- 
GitLab


From 77ac4fb6da2eea09c10a6313f7b8bfb0aad8beed Mon Sep 17 00:00:00 2001
From: Romain BERNARD <romain.bernard@uca.fr>
Date: Fri, 12 Jul 2024 18:02:11 +0200
Subject: [PATCH 142/327] Add best insertions pass through to mutualize best
 insertions in multiple vehicles

---
 src/routes/vehicle/SAEVRoute.cpp | 22 +++++++++++++++-------
 src/routes/vehicle/SAEVRoute.h   |  1 +
 2 files changed, 16 insertions(+), 7 deletions(-)

diff --git a/src/routes/vehicle/SAEVRoute.cpp b/src/routes/vehicle/SAEVRoute.cpp
index fc42ed2..bfb340f 100644
--- a/src/routes/vehicle/SAEVRoute.cpp
+++ b/src/routes/vehicle/SAEVRoute.cpp
@@ -397,15 +397,25 @@ BestInsertionQueue SAEVRoute::getBestInsertionsQueue(size_t requestId, size_t ve
     return bestInsertionQueue;
 }
 
-/** TODO: move to BestInsertionQueue class with a route parameter ?
+/**
  * Initializes a BestInsertionQueue to guide the best insertion heuristic while checking neighbouring TW checks
- * @param requestId
- * @param vehicleId
- * @return
+ * @param requestId The ID of the request for which we search best insertions
+ * @param vehicleId The ID of the vehicle in which we look for new best insertions
+ * @return The created BestInsertionQueue filled with the best insertions for the given request and vehicle IDs
  */
- BestInsertionQueue SAEVRoute::getBestFeasibleInsertionsQueue(size_t requestId, size_t vehicleId) {
+BestInsertionQueue SAEVRoute::getBestFeasibleInsertionsQueue(size_t requestId, size_t vehicleId) {
     BestInsertionQueue bestInsertionQueue(requestId, vehicleId, _nbRequest^2);
+    getBestFeasibleInsertionsQueue(bestInsertionQueue, requestId, vehicleId);
+    return bestInsertionQueue;
+}
 
+/**
+ * Search for new best insertions to add into the given best insertion queue for a given request and vehicle
+ * @param bestInsertionQueue The queue we wish to add the new feasible best insertions to
+ * @param requestId The ID of the request for which we search best insertions
+ * @param vehicleId The ID of the vehicle in which we look for new best insertions
+ */
+void SAEVRoute::getBestFeasibleInsertionsQueue(BestInsertionQueue& bestInsertionQueue, size_t requestId, size_t vehicleId) {
     //Init variables used during iteration
     double score;
     SAEVKeyPoint * originInsertionKeyPoint = &getOriginDepot(vehicleId);
@@ -425,8 +435,6 @@ BestInsertionQueue SAEVRoute::getBestInsertionsQueue(size_t requestId, size_t ve
         originInsertionKeyPoint = originInsertionKeyPoint->getSuccessor();
         destinationInsertionKeyPoint = originInsertionKeyPoint;
     }
-
-    return bestInsertionQueue;
 }
 
 void SAEVRoute::addRequestWeightToRoute(size_t requestId) {
diff --git a/src/routes/vehicle/SAEVRoute.h b/src/routes/vehicle/SAEVRoute.h
index 23cf745..8dce807 100644
--- a/src/routes/vehicle/SAEVRoute.h
+++ b/src/routes/vehicle/SAEVRoute.h
@@ -111,6 +111,7 @@ public:
 
     BestInsertionQueue getBestInsertionsQueue(size_t requestId, size_t vehicleId);
     BestInsertionQueue getBestFeasibleInsertionsQueue(size_t requestId, size_t vehicleId);
+    void getBestFeasibleInsertionsQueue(BestInsertionQueue& bestInsertionQueue, size_t requestId, size_t vehicleId);
 
     SAEVKeyPoint& getRequestOrigin(const size_t requestId) { return _route[requestId * 2];}
     SAEVKeyPoint& getRequestDestination(const size_t requestId) { return _route[requestId * 2 + 1];}
-- 
GitLab


From 76a1169c300367d943453c6dc8b5e7d88eac7bfb Mon Sep 17 00:00:00 2001
From: Romain BERNARD <romain.bernard@uca.fr>
Date: Mon, 15 Jul 2024 12:17:09 +0200
Subject: [PATCH 143/327] enrich shortestpath api for easy access to start/end
 keypoints

---
 src/ShortestPath/ShortestPath.h               |  8 ++++
 .../Transit/TransitShortestPath.h             | 37 +++++++++----------
 src/instance/graph/LineStop.h                 |  5 +++
 3 files changed, 31 insertions(+), 19 deletions(-)

diff --git a/src/ShortestPath/ShortestPath.h b/src/ShortestPath/ShortestPath.h
index 0199832..f73bb23 100644
--- a/src/ShortestPath/ShortestPath.h
+++ b/src/ShortestPath/ShortestPath.h
@@ -20,6 +20,14 @@ public:
         return _keyPoints;
     }
 
+    virtual const KeyPoint* getDeparture() const {
+        return _keyPoints.cbegin().base();
+    }
+
+    virtual const KeyPoint* getArrival() const {
+        return (_keyPoints.cend() - 1).base();
+    }
+
     void replaceKeyPoint(int keyPointIndex, KeyPoint& value) {
         _keyPoints[keyPointIndex] = value;
     }
diff --git a/src/ShortestPath/Transit/TransitShortestPath.h b/src/ShortestPath/Transit/TransitShortestPath.h
index c2014d1..ccbf88b 100644
--- a/src/ShortestPath/Transit/TransitShortestPath.h
+++ b/src/ShortestPath/Transit/TransitShortestPath.h
@@ -11,11 +11,11 @@
 
 class TransitShortestPath : public ShortestPath<LineStop> {
 private:
-    int _arrivalTime;
+    int _arrivalTime{-1};
 public:
+    TransitShortestPath() = default;
 
-    explicit TransitShortestPath(const TransitAlgorithmState& state) {
-        _arrivalTime = state.getInstant();
+    explicit TransitShortestPath(const TransitAlgorithmState& state) : _arrivalTime(state.getInstant()) {
         std::move(state.getConnections().begin(), state.getConnections().end() - 1,_keyPoints.begin());
     }
 
@@ -39,24 +39,23 @@ public:
                (this->getArrivalTime() == rhs.getArrivalTime() && this->getKeyPoints().size() > rhs.getKeyPoints().size());
     }
 
-    [[nodiscard]] int getArrivalTime() const { return _arrivalTime; }
+    [[nodiscard]] const LineStop* getDeparture() const override {
+        return _keyPoints.cbegin().base();
+    }
 
+    [[nodiscard]] const LineStop* getArrival() const override {
+        return (_keyPoints.cend() - 1).base();
+    }
 
-//    FIXME: check if I can properly remove this or if shortest path comparisons may be useful
-//    [[nodiscard]] bool strictlyDominates(const TransitAlgorithmState& rhs) const {
-//        return this->getKeyPoints().size() <= rhs.getConnections().size()
-//               && this->getDuration() <= rhs.getInstant();
-//    }
-//
-//    bool operator<(const TransitAlgorithmState& rhs) const {
-//        return this->getDuration() < rhs.getInstant() ||
-//               (this->getDuration() == rhs.getInstant() && this->getKeyPoints().size() < rhs.getConnections().size());
-//    }
-//
-//    bool operator>(const TransitAlgorithmState& rhs) const {
-//        return this->getDuration() > rhs.getInstant() ||
-//               (this->getDuration() == rhs.getInstant() && this->getKeyPoints().size() > rhs.getConnections().size());
-//    }
+    [[nodiscard]] size_t getDepartureNode() const {
+        return getDeparture()->getNodeIndex();
+    }
+
+    [[nodiscard]] size_t getArrivalNode() const {
+        return getArrival()->getNodeIndex();
+    }
+
+    [[nodiscard]] int getArrivalTime() const { return _arrivalTime; }
 };
 
 
diff --git a/src/instance/graph/LineStop.h b/src/instance/graph/LineStop.h
index 9d15019..5414a08 100644
--- a/src/instance/graph/LineStop.h
+++ b/src/instance/graph/LineStop.h
@@ -25,6 +25,11 @@ public:
     [[nodiscard]] int getInstant(int stationIdx, int scheduleIdx) const { return _lineRef.getInstant(stationIdx, scheduleIdx); }
     [[nodiscard]] int findNextScheduledPassage(int stationIdx, int instant) const { return _lineRef.findNextScheduledPassage(stationIdx, instant); }
 
+    [[nodiscard]] size_t getNodeIndex() const
+    {
+        return _lineRef.getNode(_stopIndex);
+    }
+
     /**
      * @return -1 if there are no valid successors to this LineStop's node. Returns the node index in the graph if there is a valid successor
      */
-- 
GitLab


From c9ac69f4b50de42d4cd51aa9abf25f55cefb8bcb Mon Sep 17 00:00:00 2001
From: Romain BERNARD <romain.bernard@uca.fr>
Date: Mon, 15 Jul 2024 12:18:17 +0200
Subject: [PATCH 144/327] refactor TransitShortestPathContainer API and bugfix

---
 .../Transit/TransitShortestPathContainer.cpp    | 17 +++++++++++------
 .../Transit/TransitShortestPathContainer.h      |  5 ++---
 test/src/TransitPreprocessDebug.cpp             |  8 ++++----
 3 files changed, 17 insertions(+), 13 deletions(-)

diff --git a/src/ShortestPath/Transit/TransitShortestPathContainer.cpp b/src/ShortestPath/Transit/TransitShortestPathContainer.cpp
index 71e74eb..10dfb98 100644
--- a/src/ShortestPath/Transit/TransitShortestPathContainer.cpp
+++ b/src/ShortestPath/Transit/TransitShortestPathContainer.cpp
@@ -25,16 +25,21 @@ void TransitShortestPathContainer::addShortestPathCollection(int startNodeIndex,
     container[startNodeIndex].emplace_back(startingInstant, shortestPathList);
 }
 
-std::vector<std::pair<int, std::vector<TransitShortestPath>>>::iterator
-TransitShortestPathContainer::getShortestPathsFromTime(int startNodeIndex, int earliestStartInstant) {
+std::pair<int, std::vector<TransitShortestPath>> *
+TransitShortestPathContainer::getShortestPathsFrom(int startNodeIndex, int earliestStartInstant) {
     const auto& iterator = std::ranges::lower_bound(container[startNodeIndex],
                                             std::pair<int, std::vector<TransitShortestPath>>(earliestStartInstant, {}));
 
-    return iterator;
+    return iterator.base();
 }
 
-std::pair<int, TransitShortestPath>
+TransitShortestPath
 TransitShortestPathContainer::getShortestPathToYFromTime(int startNodeIndex, int earliestStartInstant, int goalNode) {
-    const auto& shortestPathsIterator = getShortestPathsFromTime(startNodeIndex, earliestStartInstant);
-    return std::pair(shortestPathsIterator->first, shortestPathsIterator->second[goalNode]);
+    auto [startNode, shortestPathsVector] = *getShortestPathsFrom(startNodeIndex, earliestStartInstant);
+    for(const auto& shortestPath : shortestPathsVector) {
+        if(shortestPath.getArrivalNode() == goalNode) {
+            return shortestPath;
+        }
+    }
+    return  TransitShortestPath{};
 }
diff --git a/src/ShortestPath/Transit/TransitShortestPathContainer.h b/src/ShortestPath/Transit/TransitShortestPathContainer.h
index 55166e4..14e26db 100644
--- a/src/ShortestPath/Transit/TransitShortestPathContainer.h
+++ b/src/ShortestPath/Transit/TransitShortestPathContainer.h
@@ -19,9 +19,8 @@ public:
     explicit TransitShortestPathContainer(size_t size) { container.resize(size); }
     void addShortestPathCollection(int startNodeIndex, const std::pair<int, std::vector<TransitShortestPath>>& shortestPathList);
     void addShortestPathCollection(int startNodeIndex, int startingInstant, int graphSize, const TransitStateContainer& algorithmResultStates);
-    std::vector<std::pair<int, std::vector<TransitShortestPath>>>::iterator getShortestPathsFromTime(int startNodeIndex, int earliestStartInstant);
-    std::pair<int, TransitShortestPath> getShortestPathToYFromTime(int startNodeIndex, int earliestStartInstant, int goalNode);
-
+    std::pair<int, std::vector<TransitShortestPath>> * getShortestPathsFrom(int startNodeIndex, int earliestStartInstant);
+    TransitShortestPath getShortestPathToYFromTime(int startNodeIndex, int earliestStartInstant, int goalNode);
 };
 
 
diff --git a/test/src/TransitPreprocessDebug.cpp b/test/src/TransitPreprocessDebug.cpp
index 66d32f3..e263e9d 100644
--- a/test/src/TransitPreprocessDebug.cpp
+++ b/test/src/TransitPreprocessDebug.cpp
@@ -20,7 +20,7 @@ TEST(Transit_Preprocess_DEB, DebugFunction) {
             for (auto& startingTime: ptLine.getTimetable(i)) {
                 contiguousContainer.addShortestPathCollection(i, startingTime, graphFromSingleFile.getNbNodes(),
                         TransitShortestPathPrecompute::executeAlgorithm(graphFromSingleFile, ptLine.getNode(i),startingTime));
-                contiguousContainer.getShortestPathsFromTime(i, startingTime - 1);
+                contiguousContainer.getShortestPathsFrom(i, startingTime - 1);
             }
         }
     }
@@ -32,7 +32,7 @@ TEST(Transit_Preprocess_DEB, DebugFunction) {
             for (auto& startingTime: ptLine.getTimetable(i)) {
                 crossingContainer.addShortestPathCollection(i, startingTime, crossingLinesGraph.getNbNodes(),
                         TransitShortestPathPrecompute::executeAlgorithm(crossingLinesGraph, ptLine.getNode(i),startingTime));
-                crossingContainer.getShortestPathsFromTime(i, startingTime - 1);
+                crossingContainer.getShortestPathsFrom(i, startingTime - 1);
             }
         }
     }
@@ -44,7 +44,7 @@ TEST(Transit_Preprocess_DEB, DebugFunction) {
             for (auto& startingTime: ptLine.getTimetable(i)) {
                 cycleContainer.addShortestPathCollection(i, startingTime, cyclingLineGraph.getNbNodes(),
                         TransitShortestPathPrecompute::executeAlgorithm(cyclingLineGraph, ptLine.getNode(i),startingTime));
-                cycleContainer.getShortestPathsFromTime(i, startingTime - 1);
+                cycleContainer.getShortestPathsFrom(i, startingTime - 1);
             }
         }
     }
@@ -57,7 +57,7 @@ TEST(Transit_Preprocess_DEB, DebugFunction) {
             for (auto& startingTime: ptLine.getTimetable(i)) {
                 multiCycleContainer.addShortestPathCollection(i, startingTime, multipleCyclingLinesGraph.getNbNodes(),
                         TransitShortestPathPrecompute::executeAlgorithm(multipleCyclingLinesGraph, ptLine.getNode(i),startingTime));
-                multiCycleContainer.getShortestPathsFromTime(i, startingTime - 1);
+                multiCycleContainer.getShortestPathsFrom(i, startingTime - 1);
             }
         }
     }
-- 
GitLab


From ff9791667c41a97111cd933bd4f4b44b72e55c8d Mon Sep 17 00:00:00 2001
From: Romain BERNARD <romain.bernard@uca.fr>
Date: Mon, 15 Jul 2024 15:09:42 +0200
Subject: [PATCH 145/327] fix tests

---
 test/src/ConstraintPropagationDebug.cpp | 20 ++++++++++----------
 1 file changed, 10 insertions(+), 10 deletions(-)

diff --git a/test/src/ConstraintPropagationDebug.cpp b/test/src/ConstraintPropagationDebug.cpp
index cdc0ff7..9ee6338 100644
--- a/test/src/ConstraintPropagationDebug.cpp
+++ b/test/src/ConstraintPropagationDebug.cpp
@@ -27,12 +27,12 @@ TEST(ConstraintPropagationDebug, DebugBaseInstance) {
     std::cout << "------------------Fin parsing instance et route-------------------" << std::endl << std::endl;
     int vehicleId = 1;
     assert(routesContainer.checkRouteTimeWindows(vehicleId));
-    SAEVRouteChangelist req0Changelist = routesContainer.tryAddRequest(0, routesContainer.getOriginDepot(vehicleId), routesContainer.getOriginDepot(1));
+    SAEVRouteChangelist req0Changelist = routesContainer.tryAddRequest(0, &routesContainer.getOriginDepot(vehicleId), &routesContainer.getOriginDepot(1));
     std::cout << routesContainer.to_string(vehicleId) << std::endl;
     assert(routesContainer.checkRouteTimeWindows(vehicleId));
     std::cout << "------------------------------------------------------------------" << std::endl;
-    SAEVRouteChangelist req1Changelist = routesContainer.tryAddRequest(1, routesContainer.getOriginDepot(vehicleId),
-                                                                       routesContainer.getRequestDestination(0));
+    SAEVRouteChangelist req1Changelist = routesContainer.tryAddRequest(1, &routesContainer.getOriginDepot(vehicleId),
+                                                                       &routesContainer.getRequestDestination(0));
     std::cout << routesContainer.to_string(vehicleId) << std::endl << std::endl;
     assert(!routesContainer.checkRouteTimeWindows(vehicleId));
     std::cout << "------------------------------------------------------------------" << std::endl;
@@ -80,15 +80,15 @@ TEST(ConstraintPropagationDebug, DebugInstanceAlain) {
     SAEVRoute routesContainer(graphFromSingleFile, requests);
 
     //Vehicle 1 insertions
-    routesContainer.tryAddRequest(0,routesContainer.getOriginDepot(0),routesContainer.getOriginDepot(0));
-    routesContainer.tryAddRequest(1, routesContainer.getRequestOrigin(0), routesContainer.getRequestOrigin(0));
-    SAEVRouteChangelist cl = routesContainer.tryAddRequest(2, routesContainer.getRequestOrigin(1),
-                                                           routesContainer.getRequestDestination(1));
+    routesContainer.tryAddRequest(0,&routesContainer.getOriginDepot(0),&routesContainer.getOriginDepot(0));
+    routesContainer.tryAddRequest(1, &routesContainer.getRequestOrigin(0), &routesContainer.getRequestOrigin(0));
+    SAEVRouteChangelist cl = routesContainer.tryAddRequest(2, &routesContainer.getRequestOrigin(1),
+                                                           &routesContainer.getRequestDestination(1));
 
     //Vehicle 2 insertions
-    routesContainer.tryAddRequest(5,routesContainer.getOriginDepot(1),routesContainer.getOriginDepot(1));
-    routesContainer.tryAddRequest(4,routesContainer.getOriginDepot(1), routesContainer.getRequestDestination(5));
-    routesContainer.tryAddRequest(3,routesContainer.getOriginDepot(1), routesContainer.getRequestOrigin(4));
+    routesContainer.tryAddRequest(5,&routesContainer.getOriginDepot(1),&routesContainer.getOriginDepot(1));
+    routesContainer.tryAddRequest(4,&routesContainer.getOriginDepot(1), &routesContainer.getRequestDestination(5));
+    routesContainer.tryAddRequest(3,&routesContainer.getOriginDepot(1), &routesContainer.getRequestOrigin(4));
 }
 
 }
-- 
GitLab


From fe05f2d6642a3dedf9cac05bbf294c8114e40fe7 Mon Sep 17 00:00:00 2001
From: Romain BERNARD <romain.bernard@uca.fr>
Date: Tue, 16 Jul 2024 16:56:17 +0200
Subject: [PATCH 146/327] remove unused classes

---
 src/ShortestPath/ShortestPathContainer.h      | 20 -------------------
 .../TimeDependentShortestPathContainer.h      | 20 -------------------
 2 files changed, 40 deletions(-)
 delete mode 100644 src/ShortestPath/ShortestPathContainer.h
 delete mode 100644 src/ShortestPath/TimeDependentShortestPathContainer.h

diff --git a/src/ShortestPath/ShortestPathContainer.h b/src/ShortestPath/ShortestPathContainer.h
deleted file mode 100644
index 3a3b9a5..0000000
--- a/src/ShortestPath/ShortestPathContainer.h
+++ /dev/null
@@ -1,20 +0,0 @@
-//
-// Created by rbernard on 20/02/2024.
-//
-
-#ifndef GREEDYALGORITHM_SHORTESTPATHCONTAINER_H
-#define GREEDYALGORITHM_SHORTESTPATHCONTAINER_H
-
-#include "ShortestPath.h"
-
-/**
- * Abstract class defining the search API for x to y shortest path containers
- */
-template <typename KeyPoint>
-class ShortestPathContainer {
-public:
-    virtual ShortestPath<KeyPoint> findShortestPath(int startNode, int destinationNode, int startTimestep) = 0;
-};
-
-
-#endif //GREEDYALGORITHM_SHORTESTPATHCONTAINER_H
diff --git a/src/ShortestPath/TimeDependentShortestPathContainer.h b/src/ShortestPath/TimeDependentShortestPathContainer.h
deleted file mode 100644
index d5eec8a..0000000
--- a/src/ShortestPath/TimeDependentShortestPathContainer.h
+++ /dev/null
@@ -1,20 +0,0 @@
-//
-// Created by rbernard on 20/02/2024.
-//
-
-#ifndef GREEDYALGORITHM_TIMEDEPENDENTSHORTESTPATHCONTAINER_H
-#define GREEDYALGORITHM_TIMEDEPENDENTSHORTESTPATHCONTAINER_H
-
-#include <vector>
-#include "ShortestPathContainer.h"
-
-template <typename KeyPoint>
-class TimeDependentShortestPathContainer {
-public:
-    virtual ShortestPath<KeyPoint> findShortestPath(int startNode, int destinationNode, int startTimestep) = 0;
-    virtual std::vector<ShortestPath<KeyPoint>> findDestinationsFrom(int startNode, int startTimestep) = 0;
-    virtual std::vector<ShortestPath<KeyPoint>> findDepartureListToArriveAtWindow(int destinationNode, int minArrivalTimestep, int maxArrivalTimestep) = 0;
-};
-
-
-#endif //GREEDYALGORITHM_TIMEDEPENDENTSHORTESTPATHCONTAINER_H
-- 
GitLab


From af3bcf5950c5146bdc9646c32458be43630f337a Mon Sep 17 00:00:00 2001
From: Romain BERNARD <romain.bernard@uca.fr>
Date: Tue, 16 Jul 2024 16:59:22 +0200
Subject: [PATCH 147/327] use const here

---
 src/ShortestPath/Transit/TransitShortestPathPrecompute.cpp | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/src/ShortestPath/Transit/TransitShortestPathPrecompute.cpp b/src/ShortestPath/Transit/TransitShortestPathPrecompute.cpp
index 20dbf83..fbfaeb0 100644
--- a/src/ShortestPath/Transit/TransitShortestPathPrecompute.cpp
+++ b/src/ShortestPath/Transit/TransitShortestPathPrecompute.cpp
@@ -31,7 +31,7 @@ TransitStateContainer TransitShortestPathPrecompute::executeAlgorithm(const Grap
         statePriorityQueue.pop();
         if(!solutionsContainer.strictlyDominates(currentState)) {
             DEBUG_MSG("\n\nComparing state " + currentState.toString() + " and " + solutionsContainer.getBestSolution(currentState.getNodeIndex(), currentState.getNbConnections()).toString());
-            for (auto& lineStop : graph.getPTLinesSet(currentState.getNodeIndex()))
+            for (auto const& lineStop : graph.getPTLinesSet(currentState.getNodeIndex()))
             {
                 int nextNode = lineStop.getNextNodeIndex();
                 //If there is a proper next node and if it's not the same as our last used line stop predecessor
-- 
GitLab


From 9aa5a13b7176c5c2ef32cebd5096fe6027fe42a7 Mon Sep 17 00:00:00 2001
From: Romain BERNARD <romain.bernard@uca.fr>
Date: Tue, 16 Jul 2024 17:05:47 +0200
Subject: [PATCH 148/327] add MAX_TRANSIT_CONNECTIONS constant

---
 .../Transit/TransitAlgorithmState.h           | 63 +++++++------------
 src/utils/Constants.h                         |  1 +
 2 files changed, 25 insertions(+), 39 deletions(-)

diff --git a/src/ShortestPath/Transit/TransitAlgorithmState.h b/src/ShortestPath/Transit/TransitAlgorithmState.h
index 133d003..671e889 100644
--- a/src/ShortestPath/Transit/TransitAlgorithmState.h
+++ b/src/ShortestPath/Transit/TransitAlgorithmState.h
@@ -9,33 +9,29 @@
 #include <array>
 #include <cstdint>
 #include "../../instance/graph/LineStop.h"
+#include "../../utils/Constants.h"
 
 class TransitAlgorithmState {
 private:
     int _nodeIndex;
-    int _instant;
-    int _passageIndex;
-    std::vector<LineStop> _connections;
-    int _precedingNodeIndex;
+    int _instant{INT16_MAX};
+    int _passageIndex{-1};
+    std::vector<LineStop> _connections{Constants::MAX_TRANSIT_CONNECTIONS};
+    int _precedingNodeIndex{-1};
 
 public:
-    TransitAlgorithmState(int currentNode, int currentInstant, int currentPassageIndex, int precedingNodeIndex) {
-        _nodeIndex = currentNode;
-        _instant = currentInstant;
-        _passageIndex = currentPassageIndex;
-        _precedingNodeIndex = precedingNodeIndex;
-        _connections.reserve(2); //TODO : replace constant max amount of connexions with a global parameter
+    TransitAlgorithmState(int currentNode, int currentInstant, int currentPassageIndex, int precedingNodeIndex) :
+            _nodeIndex(currentNode), _instant(currentInstant),
+            _passageIndex(currentPassageIndex), _precedingNodeIndex(precedingNodeIndex) {
+        _connections.reserve(Constants::MAX_TRANSIT_CONNECTIONS); //TODO : replace constant max amount of connexions with a global parameter
     }
 
-    TransitAlgorithmState(TransitAlgorithmState& baseState) {
-        _nodeIndex = baseState.getNodeIndex();
-        _instant = baseState.getInstant();
-        _passageIndex = baseState.getPassageIndex();
-        _precedingNodeIndex = baseState.getPrecedingNodeIndex();
-
+    TransitAlgorithmState(TransitAlgorithmState const& baseState) :
+    _nodeIndex(baseState.getNodeIndex()), _instant(baseState.getInstant()),
+    _passageIndex(baseState.getPassageIndex()), _precedingNodeIndex(baseState.getPrecedingNodeIndex()) {
         //Copy old connections
         _connections.clear();
-        _connections.reserve(2);
+        _connections.reserve(Constants::MAX_TRANSIT_CONNECTIONS);
         for(auto& lineStop : baseState.getConnections()) {
             _connections.emplace_back(lineStop);
         }
@@ -43,15 +39,12 @@ public:
 
     TransitAlgorithmState(TransitAlgorithmState&& baseStatePointer) = default;
 
-    TransitAlgorithmState(TransitAlgorithmState& baseState, const LineStop& newConnection) {
-        _nodeIndex = baseState.getNodeIndex();
-        _instant = baseState.getInstant();
-        _passageIndex = baseState.getPassageIndex();
-        _precedingNodeIndex = baseState.getPrecedingNodeIndex();
-
+    TransitAlgorithmState(TransitAlgorithmState const& baseState, const LineStop& newConnection) :
+    _nodeIndex(baseState.getNodeIndex()), _instant(baseState.getInstant()),
+    _passageIndex(baseState.getPassageIndex()), _precedingNodeIndex(baseState.getPrecedingNodeIndex()) {
         //Copy old connections
         _connections.clear();
-        _connections.reserve(2);
+        _connections.reserve(Constants::MAX_TRANSIT_CONNECTIONS);
         for(auto& lineStop : baseState.getConnections()) {
             _connections.emplace_back(lineStop);
         }
@@ -59,20 +52,12 @@ public:
         addNewConnection(newConnection);
     }
 
-    explicit TransitAlgorithmState(int nodeIndex) {
-        _nodeIndex = nodeIndex;
-        _instant = INT16_MAX;
-        _passageIndex = -1;
-        _precedingNodeIndex = -1;
-        _connections.reserve(2);
+    explicit TransitAlgorithmState(int nodeIndex) : _nodeIndex(nodeIndex) {
+        _connections.reserve(Constants::MAX_TRANSIT_CONNECTIONS);
     }
 
-    explicit TransitAlgorithmState() {
-        _nodeIndex = -1;
-        _instant = INT16_MAX;
-        _passageIndex = -1;
-        _precedingNodeIndex = -1;
-        _connections.reserve(2);
+    explicit TransitAlgorithmState() : _nodeIndex(-1) {
+        _connections.reserve(Constants::MAX_TRANSIT_CONNECTIONS);
     }
 
     [[nodiscard]] int getNodeIndex() const {
@@ -96,7 +81,7 @@ public:
     }
 
     [[nodiscard]] bool canAddConnection() const {
-        return _connections.size() < 2;
+        return _connections.size() < Constants::MAX_TRANSIT_CONNECTIONS;
     }
 
     [[nodiscard]] size_t getNbConnections() const {
@@ -150,7 +135,7 @@ public:
         }
     }
 
-    bool canAddNewConnection() {return _connections.size() < _connections.max_size(); }
+    bool canAddNewConnection() const {return _connections.size() < _connections.max_size(); }
 
     /**
      * Strict dominance between two transit shortest path states happens if state *this* has :
@@ -161,7 +146,7 @@ public:
     [[nodiscard]] bool strictlyDominates(const TransitAlgorithmState& rhs) const {
         return this->getNodeIndex() == rhs.getNodeIndex()
         && this->getLastConnectionLine().getLineId() == rhs.getLastConnectionLine().getLineId()
-//        /*TODO : check */ && (this->getLastConnectionLine() == rhs.getLastConnectionLine() || this->getNbConnections() == 2) /***/
+//        TODO : check  && (this->getLastConnectionLine() == rhs.getLastConnectionLine() || this->getNbConnections() == Constants::MAX_TRANSIT_CONNECTIONS)
         && ((this->getInstant() < rhs.getInstant() && this->getConnections().size() <= rhs.getConnections().size())
         || (this->getInstant() == rhs.getInstant() && this->getConnections().size() < rhs.getConnections().size()));
     }
diff --git a/src/utils/Constants.h b/src/utils/Constants.h
index 47f3b51..1778d8f 100644
--- a/src/utils/Constants.h
+++ b/src/utils/Constants.h
@@ -9,6 +9,7 @@
 class Constants {
 public:
     static constexpr int VEHICLE_CAPACITY = 4;
+    static constexpr int MAX_TRANSIT_CONNECTIONS = 2;
 };
 
 
-- 
GitLab


From 52229af3800970a3b1efdf3af0aada744663f3e3 Mon Sep 17 00:00:00 2001
From: Romain BERNARD <romain.bernard@uca.fr>
Date: Tue, 16 Jul 2024 17:12:22 +0200
Subject: [PATCH 149/327] remove unused constructor

---
 src/ShortestPath/Transit/TransitStateContainer.h | 8 --------
 1 file changed, 8 deletions(-)

diff --git a/src/ShortestPath/Transit/TransitStateContainer.h b/src/ShortestPath/Transit/TransitStateContainer.h
index b568d03..048961e 100644
--- a/src/ShortestPath/Transit/TransitStateContainer.h
+++ b/src/ShortestPath/Transit/TransitStateContainer.h
@@ -21,14 +21,6 @@ private:
     std::vector<std::vector<TransitAlgorithmState>>  solutionVector;
 
 public:
-    explicit TransitStateContainer(int size)
-    {
-        solutionVector.resize(size);
-        for(size_t i = 0; i < size; ++i) {
-            solutionVector[i].emplace_back();
-            solutionVector[i].emplace_back();
-        }
-    }
     explicit TransitStateContainer(size_t size)
     {
         //Reserve space for all nodes and add empty solutions to reserve memory
-- 
GitLab


From e4d947359cdb761d3bea97ddca44b437633467b2 Mon Sep 17 00:00:00 2001
From: Romain BERNARD <romain.bernard@uca.fr>
Date: Tue, 16 Jul 2024 17:19:18 +0200
Subject: [PATCH 150/327] add default constructor to allow resize instead of
 reserve

---
 src/instance/graph/LineStop.h | 1 +
 1 file changed, 1 insertion(+)

diff --git a/src/instance/graph/LineStop.h b/src/instance/graph/LineStop.h
index 5414a08..3669ef1 100644
--- a/src/instance/graph/LineStop.h
+++ b/src/instance/graph/LineStop.h
@@ -16,6 +16,7 @@ private:
     int _stopIndex{}; //index for the stop relative to this node in the Line object
 
 public:
+    LineStop() = default;
     LineStop(const Line& lineRef, int stopIndex) : _lineRef(lineRef), _stopIndex(stopIndex) {}
 
     [[nodiscard]] Line getLineRef() const {
-- 
GitLab


From 778ae10aa77710f99b8a2f53f5f9a85d27526e2b Mon Sep 17 00:00:00 2001
From: Romain BERNARD <romain.bernard@uca.fr>
Date: Tue, 16 Jul 2024 17:27:12 +0200
Subject: [PATCH 151/327] remove unused classes and functions (formatting
 results is handled via TransitShortestPathContainer serialization methods)

---
 CMakeLists.txt                                           | 3 ---
 src/ShortestPath/Transit/TransitShortestPathPrecompute.h | 2 --
 2 files changed, 5 deletions(-)

diff --git a/CMakeLists.txt b/CMakeLists.txt
index 0423a97..a06a619 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -29,9 +29,6 @@ add_executable(GreedyAlgorithm
         src/instance/graph/LineStop.h
         src/services/DatFile/DATRow.h
         src/utils/SearchAlgorithms.h
-        src/ShortestPath/ShortestPathContainer.h
-        src/ShortestPath/TimeDependentShortestPathContainer.h
-        src/ShortestPath/TimeDependentShortestPathContainer.h
         src/ShortestPath/ShortestPath.h
         src/ShortestPath/Transit/TransitShortestPath.h
         src/ShortestPath/Transit/TransitShortestPathPrecompute.cpp
diff --git a/src/ShortestPath/Transit/TransitShortestPathPrecompute.h b/src/ShortestPath/Transit/TransitShortestPathPrecompute.h
index 229cd0c..f4e25e9 100644
--- a/src/ShortestPath/Transit/TransitShortestPathPrecompute.h
+++ b/src/ShortestPath/Transit/TransitShortestPathPrecompute.h
@@ -5,14 +5,12 @@
 #ifndef GREEDYALGORITHM_TRANSITSHORTESTPATHPRECOMPUTE_H
 #define GREEDYALGORITHM_TRANSITSHORTESTPATHPRECOMPUTE_H
 
-#include "../TimeDependentShortestPathContainer.h"
 #include "TransitShortestPath.h"
 #include "../../instance/graph/Graph.h"
 #include "TransitStateContainer.h"
 
 class TransitShortestPathPrecompute {
 public:
-    static ShortestPathContainer<TransitShortestPath> formatResults(TimeDependentShortestPathContainer<TransitShortestPath> container);
     static TransitStateContainer executeAlgorithm(const Graph& graph, int nodeIndex, int instant);
 };
 
-- 
GitLab


From 72d56402bfaace3dddf08dbb8d00fd2988d1a422 Mon Sep 17 00:00:00 2001
From: Romain BERNARD <romain.bernard@uca.fr>
Date: Tue, 16 Jul 2024 17:46:00 +0200
Subject: [PATCH 152/327] use resize to properly set array max size

---
 src/ShortestPath/Transit/TransitAlgorithmState.h | 10 +++++-----
 1 file changed, 5 insertions(+), 5 deletions(-)

diff --git a/src/ShortestPath/Transit/TransitAlgorithmState.h b/src/ShortestPath/Transit/TransitAlgorithmState.h
index 671e889..d50da64 100644
--- a/src/ShortestPath/Transit/TransitAlgorithmState.h
+++ b/src/ShortestPath/Transit/TransitAlgorithmState.h
@@ -23,7 +23,7 @@ public:
     TransitAlgorithmState(int currentNode, int currentInstant, int currentPassageIndex, int precedingNodeIndex) :
             _nodeIndex(currentNode), _instant(currentInstant),
             _passageIndex(currentPassageIndex), _precedingNodeIndex(precedingNodeIndex) {
-        _connections.reserve(Constants::MAX_TRANSIT_CONNECTIONS); //TODO : replace constant max amount of connexions with a global parameter
+        _connections.resize(Constants::MAX_TRANSIT_CONNECTIONS);
     }
 
     TransitAlgorithmState(TransitAlgorithmState const& baseState) :
@@ -31,7 +31,7 @@ public:
     _passageIndex(baseState.getPassageIndex()), _precedingNodeIndex(baseState.getPrecedingNodeIndex()) {
         //Copy old connections
         _connections.clear();
-        _connections.reserve(Constants::MAX_TRANSIT_CONNECTIONS);
+        _connections.resize(Constants::MAX_TRANSIT_CONNECTIONS);
         for(auto& lineStop : baseState.getConnections()) {
             _connections.emplace_back(lineStop);
         }
@@ -44,7 +44,7 @@ public:
     _passageIndex(baseState.getPassageIndex()), _precedingNodeIndex(baseState.getPrecedingNodeIndex()) {
         //Copy old connections
         _connections.clear();
-        _connections.reserve(Constants::MAX_TRANSIT_CONNECTIONS);
+        _connections.resize(Constants::MAX_TRANSIT_CONNECTIONS);
         for(auto& lineStop : baseState.getConnections()) {
             _connections.emplace_back(lineStop);
         }
@@ -53,11 +53,11 @@ public:
     }
 
     explicit TransitAlgorithmState(int nodeIndex) : _nodeIndex(nodeIndex) {
-        _connections.reserve(Constants::MAX_TRANSIT_CONNECTIONS);
+        _connections.resize(Constants::MAX_TRANSIT_CONNECTIONS);
     }
 
     explicit TransitAlgorithmState() : _nodeIndex(-1) {
-        _connections.reserve(Constants::MAX_TRANSIT_CONNECTIONS);
+        _connections.resize(Constants::MAX_TRANSIT_CONNECTIONS);
     }
 
     [[nodiscard]] int getNodeIndex() const {
-- 
GitLab


From 6fd0d294e4ff6fbbd37c5c6255e5a1fa631b69bf Mon Sep 17 00:00:00 2001
From: Romain BERNARD <romain.bernard@uca.fr>
Date: Tue, 16 Jul 2024 18:41:29 +0200
Subject: [PATCH 153/327] Initialize classes for vehicle shortest paths
 computation

---
 CMakeLists.txt                                |  9 ++++
 src/ShortestPath/Vehicle/VehiclePathState.h   | 49 +++++++++++++++++++
 .../Vehicle/VehicleShortestPath.cpp           |  5 ++
 .../Vehicle/VehicleShortestPath.h             | 45 +++++++++++++++++
 .../VehicleShortestPathCalculation.cpp        |  5 ++
 .../Vehicle/VehicleShortestPathCalculation.h  | 14 ++++++
 .../Vehicle/VehicleShortestPathContainer.cpp  |  5 ++
 .../Vehicle/VehicleShortestPathContainer.h    | 14 ++++++
 8 files changed, 146 insertions(+)
 create mode 100644 src/ShortestPath/Vehicle/VehiclePathState.h
 create mode 100644 src/ShortestPath/Vehicle/VehicleShortestPath.cpp
 create mode 100644 src/ShortestPath/Vehicle/VehicleShortestPath.h
 create mode 100644 src/ShortestPath/Vehicle/VehicleShortestPathCalculation.cpp
 create mode 100644 src/ShortestPath/Vehicle/VehicleShortestPathCalculation.h
 create mode 100644 src/ShortestPath/Vehicle/VehicleShortestPathContainer.cpp
 create mode 100644 src/ShortestPath/Vehicle/VehicleShortestPathContainer.h

diff --git a/CMakeLists.txt b/CMakeLists.txt
index a06a619..818e1d2 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -113,6 +113,15 @@ add_executable(GraphGeneration
         "src/utils/Instance Generation/Graph/PTLineGenerationParameters.h"
         src/algorithm/DARP/Heuristics/BestInsertionHeuristic.cpp
         src/algorithm/DARP/Heuristics/BestInsertionHeuristic.h
+        src/algorithm/Multimodal/Heuristics/SimpleModularHeuristic.cpp
+        src/algorithm/Multimodal/Heuristics/SimpleModularHeuristic.h
+        src/ShortestPath/Vehicle/VehicleShortestPath.cpp
+        src/ShortestPath/Vehicle/VehicleShortestPath.h
+        src/ShortestPath/Vehicle/VehiclePathState.h
+        src/ShortestPath/Vehicle/VehicleShortestPathCalculation.cpp
+        src/ShortestPath/Vehicle/VehicleShortestPathCalculation.h
+        src/ShortestPath/Vehicle/VehicleShortestPathContainer.cpp
+        src/ShortestPath/Vehicle/VehicleShortestPathContainer.h
 )
 
 target_include_directories(GreedyAlgorithm PRIVATE ${PYTHON_INCLUDE_DIRS})
diff --git a/src/ShortestPath/Vehicle/VehiclePathState.h b/src/ShortestPath/Vehicle/VehiclePathState.h
new file mode 100644
index 0000000..d98d024
--- /dev/null
+++ b/src/ShortestPath/Vehicle/VehiclePathState.h
@@ -0,0 +1,49 @@
+//
+// Created by romain on 16/07/24.
+//
+
+#ifndef GREEDYALGORITHM_VEHICLEPATHSTATE_H
+#define GREEDYALGORITHM_VEHICLEPATHSTATE_H
+
+#include <limits>
+#include <cstdlib>
+#include <compare>
+
+class VehiclePathState {
+private:
+    size_t _nodeIndex{std::numeric_limits<size_t>::max()};
+    uint _instant{std::numeric_limits<uint>::max()};
+
+public:
+    VehiclePathState() = default;
+    VehiclePathState(size_t nodeIndex, uint instant) : _nodeIndex(nodeIndex), _instant(instant) {}
+    VehiclePathState(const VehiclePathState& base) = default;
+    VehiclePathState(VehiclePathState&& base) = default;
+
+    [[nodiscard]] size_t getNodeIndex() const {
+        return _nodeIndex;
+    }
+
+    void setNodeIndex(size_t nodeIndex) {
+        _nodeIndex = nodeIndex;
+    }
+
+    [[nodiscard]] uint getInstant() const {
+        return _instant;
+    }
+
+    void setInstant(uint instant) {
+        _instant = instant;
+    }
+
+    auto operator<=>(const VehiclePathState &rhs) const {
+        if (this->_nodeIndex != rhs.getNodeIndex()) {
+            return std::partial_ordering::unordered;
+        }
+
+        return std::partial_order(_instant, rhs.getInstant());
+    }
+};
+
+
+#endif //GREEDYALGORITHM_VEHICLEPATHSTATE_H
diff --git a/src/ShortestPath/Vehicle/VehicleShortestPath.cpp b/src/ShortestPath/Vehicle/VehicleShortestPath.cpp
new file mode 100644
index 0000000..b315976
--- /dev/null
+++ b/src/ShortestPath/Vehicle/VehicleShortestPath.cpp
@@ -0,0 +1,5 @@
+//
+// Created by romain on 16/07/24.
+//
+
+#include "VehicleShortestPath.h"
diff --git a/src/ShortestPath/Vehicle/VehicleShortestPath.h b/src/ShortestPath/Vehicle/VehicleShortestPath.h
new file mode 100644
index 0000000..c756172
--- /dev/null
+++ b/src/ShortestPath/Vehicle/VehicleShortestPath.h
@@ -0,0 +1,45 @@
+//
+// Created by romain on 16/07/24.
+//
+
+#ifndef GREEDYALGORITHM_VEHICLESHORTESTPATH_H
+#define GREEDYALGORITHM_VEHICLESHORTESTPATH_H
+
+#include <compare>
+#include "../ShortestPath.h"
+#include "../../instance/graph/Node.h"
+
+class VehicleShortestPath : public ShortestPath<size_t> {
+private:
+    uint _duration{0};
+public:
+    VehicleShortestPath() = default;
+    explicit VehicleShortestPath(uint duration) : _duration(duration) {}
+
+    [[nodiscard]] uint getDuration() const {
+        return _duration;
+    }
+
+    void setDuration(uint duration) {
+        _duration = duration;
+    }
+
+    [[nodiscard]] const size_t* getDeparture() const override {
+        return _keyPoints.cbegin().base();
+    }
+
+    [[nodiscard]] const size_t* getArrival() const override {
+        return (_keyPoints.cend() - 1).base();
+    }
+
+    auto operator<=>(const VehicleShortestPath &rhs) const {
+        if (this->getDeparture() != rhs.getDeparture() || this->getArrival() != rhs.getArrival()) {
+            return std::partial_ordering::unordered;
+        }
+
+        return std::partial_order(_duration, rhs.getDuration());
+    }
+};
+
+
+#endif //GREEDYALGORITHM_VEHICLESHORTESTPATH_H
diff --git a/src/ShortestPath/Vehicle/VehicleShortestPathCalculation.cpp b/src/ShortestPath/Vehicle/VehicleShortestPathCalculation.cpp
new file mode 100644
index 0000000..983a9b5
--- /dev/null
+++ b/src/ShortestPath/Vehicle/VehicleShortestPathCalculation.cpp
@@ -0,0 +1,5 @@
+//
+// Created by romain on 16/07/24.
+//
+
+#include "VehicleShortestPathCalculation.h"
diff --git a/src/ShortestPath/Vehicle/VehicleShortestPathCalculation.h b/src/ShortestPath/Vehicle/VehicleShortestPathCalculation.h
new file mode 100644
index 0000000..4b6c16b
--- /dev/null
+++ b/src/ShortestPath/Vehicle/VehicleShortestPathCalculation.h
@@ -0,0 +1,14 @@
+//
+// Created by romain on 16/07/24.
+//
+
+#ifndef GREEDYALGORITHM_VEHICLESHORTESTPATHCALCULATION_H
+#define GREEDYALGORITHM_VEHICLESHORTESTPATHCALCULATION_H
+
+
+class VehicleShortestPathCalculation {
+
+};
+
+
+#endif //GREEDYALGORITHM_VEHICLESHORTESTPATHCALCULATION_H
diff --git a/src/ShortestPath/Vehicle/VehicleShortestPathContainer.cpp b/src/ShortestPath/Vehicle/VehicleShortestPathContainer.cpp
new file mode 100644
index 0000000..460e3de
--- /dev/null
+++ b/src/ShortestPath/Vehicle/VehicleShortestPathContainer.cpp
@@ -0,0 +1,5 @@
+//
+// Created by romain on 16/07/24.
+//
+
+#include "VehicleShortestPathContainer.h"
diff --git a/src/ShortestPath/Vehicle/VehicleShortestPathContainer.h b/src/ShortestPath/Vehicle/VehicleShortestPathContainer.h
new file mode 100644
index 0000000..d8ada01
--- /dev/null
+++ b/src/ShortestPath/Vehicle/VehicleShortestPathContainer.h
@@ -0,0 +1,14 @@
+//
+// Created by romain on 16/07/24.
+//
+
+#ifndef GREEDYALGORITHM_VEHICLESHORTESTPATHCONTAINER_H
+#define GREEDYALGORITHM_VEHICLESHORTESTPATHCONTAINER_H
+
+
+class VehicleShortestPathContainer {
+
+};
+
+
+#endif //GREEDYALGORITHM_VEHICLESHORTESTPATHCONTAINER_H
-- 
GitLab


From 0c69d3348299b2f515f3c8be8d68d812975ae5b0 Mon Sep 17 00:00:00 2001
From: Romain BERNARD <romain.bernard@uca.fr>
Date: Wed, 17 Jul 2024 15:22:22 +0200
Subject: [PATCH 154/327] init shortestPathContainer API

---
 CMakeLists.txt                                |  1 -
 .../Vehicle/VehicleShortestPathContainer.cpp  |  5 ----
 .../Vehicle/VehicleShortestPathContainer.h    | 29 +++++++++++++++++++
 3 files changed, 29 insertions(+), 6 deletions(-)
 delete mode 100644 src/ShortestPath/Vehicle/VehicleShortestPathContainer.cpp

diff --git a/CMakeLists.txt b/CMakeLists.txt
index 818e1d2..e70091f 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -120,7 +120,6 @@ add_executable(GraphGeneration
         src/ShortestPath/Vehicle/VehiclePathState.h
         src/ShortestPath/Vehicle/VehicleShortestPathCalculation.cpp
         src/ShortestPath/Vehicle/VehicleShortestPathCalculation.h
-        src/ShortestPath/Vehicle/VehicleShortestPathContainer.cpp
         src/ShortestPath/Vehicle/VehicleShortestPathContainer.h
 )
 
diff --git a/src/ShortestPath/Vehicle/VehicleShortestPathContainer.cpp b/src/ShortestPath/Vehicle/VehicleShortestPathContainer.cpp
deleted file mode 100644
index 460e3de..0000000
--- a/src/ShortestPath/Vehicle/VehicleShortestPathContainer.cpp
+++ /dev/null
@@ -1,5 +0,0 @@
-//
-// Created by romain on 16/07/24.
-//
-
-#include "VehicleShortestPathContainer.h"
diff --git a/src/ShortestPath/Vehicle/VehicleShortestPathContainer.h b/src/ShortestPath/Vehicle/VehicleShortestPathContainer.h
index d8ada01..37af162 100644
--- a/src/ShortestPath/Vehicle/VehicleShortestPathContainer.h
+++ b/src/ShortestPath/Vehicle/VehicleShortestPathContainer.h
@@ -6,8 +6,37 @@
 #define GREEDYALGORITHM_VEHICLESHORTESTPATHCONTAINER_H
 
 
+#include <vector>
+#include <cstdint>
+#include <algorithm>
+
 class VehicleShortestPathContainer {
+private:
+    std::vector<std::vector<uint>> _distanceMatrix{};
+public:
+    VehicleShortestPathContainer() = default;
+    VehicleShortestPathContainer(size_t matrixSize) {
+        _distanceMatrix.resize(matrixSize);
+        for(int i = 0; i < _distanceMatrix.capacity(); ++i)
+            _distanceMatrix[i].resize(matrixSize, INT16_MAX);
+    }
+
+    [[nodiscard]] const std::vector<std::vector<uint>> &getDistanceMatrix() const {
+        return _distanceMatrix;
+    }
+
+    /**
+     * Replaces all the results for the given starting node with the given results vector.
+     * the whole vector is cleared before
+     * @param startingNode
+     * @param results
+     */
+    void replaceResultsCollection(size_t startingNode, std::vector<uint>& results) {
+        _distanceMatrix[startingNode].clear();
+        std::ranges::move(results, _distanceMatrix[startingNode].begin());
+    }
 
+    std::vector<uint>& operator[](size_t idx) { return _distanceMatrix[idx]; }
 };
 
 
-- 
GitLab


From 611d53d43db757f09d5b6b318c563aae5628a573 Mon Sep 17 00:00:00 2001
From: Romain BERNARD <romain.bernard@uca.fr>
Date: Wed, 17 Jul 2024 18:30:55 +0200
Subject: [PATCH 155/327] use uint and size_t where appropriate and update API

---
 src/instance/graph/Graph.cpp | 14 +++++++++++---
 src/instance/graph/Graph.h   | 14 +++++++++-----
 2 files changed, 20 insertions(+), 8 deletions(-)

diff --git a/src/instance/graph/Graph.cpp b/src/instance/graph/Graph.cpp
index 17b2159..1e4b8cf 100644
--- a/src/instance/graph/Graph.cpp
+++ b/src/instance/graph/Graph.cpp
@@ -38,7 +38,7 @@ Graph::Graph(const std::string& nodesFilePath, const std::string& edgesFilePath,
     }
 
     shortestSAEVPaths.reserve(nodesVector.size());
-    for(std::vector<int> yValues : shortestSAEVPaths) { yValues.reserve(nodesVector.size()); }
+    for(std::vector<uint> yValues : shortestSAEVPaths) { yValues.reserve(nodesVector.size()); }
 
     //Edges instantiation
     std::ifstream edgesFile(edgesFilePath);
@@ -320,10 +320,18 @@ void Graph::parseDistanceMatrix(std::ifstream &infile, DATRow currentRow) {
     }
 }
 
-int Graph::getDepotNodeIdx() const {
+size_t Graph::getDepotNodeIdx() const {
     return _depotNodeIdx;
 }
 
-void Graph::setDepotNodeIdx(int depotNodeIdx) {
+void Graph::setDepotNodeIdx(size_t depotNodeIdx) {
     _depotNodeIdx = depotNodeIdx;
 }
+
+const std::vector<std::vector<uint>> &Graph::getShortestSaevPaths() const {
+    return shortestSAEVPaths;
+}
+
+void Graph::setShortestSaevPaths(const std::vector<std::vector<uint>> &shortestSaevPaths) {
+    shortestSAEVPaths = shortestSaevPaths;
+}
diff --git a/src/instance/graph/Graph.h b/src/instance/graph/Graph.h
index 2843207..5a64241 100644
--- a/src/instance/graph/Graph.h
+++ b/src/instance/graph/Graph.h
@@ -20,8 +20,8 @@ private:
     std::vector<Node> nodesVector; //The full list of nodes created in the graph
     std::vector<Edge> edgesVector;
     std::vector<Line> transitLines;
-    std::vector<std::vector<int>> shortestSAEVPaths;
-    int _depotNodeIdx{0}; //Index of the depot node, defaults to 0, the first node created in the graph
+    std::vector<std::vector<uint>> shortestSAEVPaths;
+    size_t _depotNodeIdx{0}; //Index of the depot node, defaults to 0, the first node created in the graph
 
     /**
      * For every LineStop on every node of the graph, verify the node returned by looking into LineStop->Line(stopIdx)
@@ -56,8 +56,8 @@ public:
         return nodesVector[nodeIndex].getPTLinesSet().size();
     }
 
-    [[nodiscard]] int getDepotNodeIdx() const;
-    void setDepotNodeIdx(int depotNodeIdx);
+    [[nodiscard]] size_t getDepotNodeIdx() const;
+    void setDepotNodeIdx(size_t depotNodeIdx);
 
     /**
      * @return The graph's edge vector
@@ -150,7 +150,11 @@ public:
      */
     void createAndAddEdge(size_t edgeStartNodeIndex, size_t edgeEndNodeIndex, double length);
 
-    [[nodiscard]] int getShortestSAEVPath(size_t x, size_t y) const { return shortestSAEVPaths[x][y]; }
+    [[nodiscard]] const std::vector<std::vector<uint>> &getShortestSaevPaths() const;
+
+    void setShortestSaevPaths(const std::vector<std::vector<uint>> &shortestSaevPaths);
+
+    [[nodiscard]] uint getShortestSAEVPath(size_t x, size_t y) const { return shortestSAEVPaths[x][y]; }
 
     void parseDistanceMatrix(std::ifstream &infile, DATRow currentRow);
 };
-- 
GitLab


From aa874bb26ee7b273c188767593110109b75dc7d0 Mon Sep 17 00:00:00 2001
From: Romain BERNARD <romain.bernard@uca.fr>
Date: Wed, 17 Jul 2024 18:31:27 +0200
Subject: [PATCH 156/327] update container API and docs

---
 .../Vehicle/VehicleShortestPathContainer.h    | 34 +++++++++++++++----
 1 file changed, 27 insertions(+), 7 deletions(-)

diff --git a/src/ShortestPath/Vehicle/VehicleShortestPathContainer.h b/src/ShortestPath/Vehicle/VehicleShortestPathContainer.h
index 37af162..0adbfa6 100644
--- a/src/ShortestPath/Vehicle/VehicleShortestPathContainer.h
+++ b/src/ShortestPath/Vehicle/VehicleShortestPathContainer.h
@@ -15,7 +15,14 @@ private:
     std::vector<std::vector<uint>> _distanceMatrix{};
 public:
     VehicleShortestPathContainer() = default;
-    VehicleShortestPathContainer(size_t matrixSize) {
+
+    /**
+     * Moves the given shortestPathsMatrix to initialize the container with the given distances.
+     * @param shortestPathsMatrix
+     */
+    explicit VehicleShortestPathContainer(std::vector<std::vector<uint>> shortestPathsMatrix) : _distanceMatrix(std::move(shortestPathsMatrix)) {}
+
+    explicit VehicleShortestPathContainer(size_t matrixSize) {
         _distanceMatrix.resize(matrixSize);
         for(int i = 0; i < _distanceMatrix.capacity(); ++i)
             _distanceMatrix[i].resize(matrixSize, INT16_MAX);
@@ -27,15 +34,28 @@ public:
 
     /**
      * Replaces all the results for the given starting node with the given results vector.
-     * the whole vector is cleared before
-     * @param startingNode
-     * @param results
+     * the whole vector is cleared before moving the results vector data
+     * @param startingNodeIdx starting node of the paths in our results/destination distance vector
+     * @param results a vector which will be moved to this current results collection
      */
-    void replaceResultsCollection(size_t startingNode, std::vector<uint>& results) {
-        _distanceMatrix[startingNode].clear();
-        std::ranges::move(results, _distanceMatrix[startingNode].begin());
+    void replaceResultsCollection(size_t startingNodeIdx, std::vector<uint>& results) {
+        _distanceMatrix[startingNodeIdx].clear();
+        std::ranges::move(results, _distanceMatrix[startingNodeIdx].begin());
     }
 
+    /**
+     * Gives the shortest path time from a given node index to a given destination node index
+     * @param from origin node index
+     * @param to destination node index
+     * @return the distance of the shortest path between those two nodes
+     */
+    uint getShortestPath(size_t from, size_t to) { return _distanceMatrix[from][to]; }
+
+    /**
+     *
+     * @param idx Node index from
+     * @return The collection of distances to get to every graph node from the given index
+     */
     std::vector<uint>& operator[](size_t idx) { return _distanceMatrix[idx]; }
 };
 
-- 
GitLab


From 3167e0c1cc03dbf39227b24360fc9542e6433d57 Mon Sep 17 00:00:00 2001
From: Romain BERNARD <romain.bernard@uca.fr>
Date: Wed, 17 Jul 2024 18:31:58 +0200
Subject: [PATCH 157/327] remove unnecessary copy/move constructors

---
 src/ShortestPath/Vehicle/VehiclePathState.h | 2 --
 1 file changed, 2 deletions(-)

diff --git a/src/ShortestPath/Vehicle/VehiclePathState.h b/src/ShortestPath/Vehicle/VehiclePathState.h
index d98d024..7e81806 100644
--- a/src/ShortestPath/Vehicle/VehiclePathState.h
+++ b/src/ShortestPath/Vehicle/VehiclePathState.h
@@ -17,8 +17,6 @@ private:
 public:
     VehiclePathState() = default;
     VehiclePathState(size_t nodeIndex, uint instant) : _nodeIndex(nodeIndex), _instant(instant) {}
-    VehiclePathState(const VehiclePathState& base) = default;
-    VehiclePathState(VehiclePathState&& base) = default;
 
     [[nodiscard]] size_t getNodeIndex() const {
         return _nodeIndex;
-- 
GitLab


From ab5a5008bf6d716cb7f5a48139a4265084b0a7af Mon Sep 17 00:00:00 2001
From: Romain BERNARD <romain.bernard@uca.fr>
Date: Wed, 17 Jul 2024 18:33:06 +0200
Subject: [PATCH 158/327] implement Dijsktra to update existing distance matrix
 (TODO: lots of additional debug & allow computation of a matrix via edges)

---
 .../VehicleShortestPathCalculation.cpp        | 41 +++++++++++++++++++
 .../Vehicle/VehicleShortestPathCalculation.h  |  7 ++++
 2 files changed, 48 insertions(+)

diff --git a/src/ShortestPath/Vehicle/VehicleShortestPathCalculation.cpp b/src/ShortestPath/Vehicle/VehicleShortestPathCalculation.cpp
index 983a9b5..cb15117 100644
--- a/src/ShortestPath/Vehicle/VehicleShortestPathCalculation.cpp
+++ b/src/ShortestPath/Vehicle/VehicleShortestPathCalculation.cpp
@@ -2,4 +2,45 @@
 // Created by romain on 16/07/24.
 //
 
+#include <queue>
 #include "VehicleShortestPathCalculation.h"
+#include "VehiclePathState.h"
+
+std::vector<uint> VehicleShortestPathCalculation::computeShortestPathsFromNode(const Graph& graph, size_t startingNodeIdx) {
+    std::vector<uint> results{graph.getShortestSaevPaths()[startingNodeIdx]};
+    std::priority_queue<VehiclePathState> stateQueue{};
+    stateQueue.emplace(startingNodeIdx, 0);
+
+    uint newDistance = INT32_MAX;
+    VehiclePathState currentState;
+    while(!stateQueue.empty()) {
+        currentState = stateQueue.top();
+        stateQueue.pop();
+        //Iterate over all possible nodes, as the graph is complete in the case of a distance matrix
+        for(size_t i = 0; i < results.capacity(); ++i) {
+            newDistance = currentState.getInstant() + graph.getShortestSAEVPath(currentState.getNodeIndex(), i);
+            if(newDistance < results[i]) {
+                stateQueue.emplace(i, newDistance);
+                results[i] = newDistance;
+            }
+        }
+    }
+
+    return results;
+}
+
+VehicleShortestPathContainer VehicleShortestPathCalculation::computeShortestPathsForGraph(const Graph &graph) {
+    std::vector<std::vector<uint>> results;
+    results.resize(graph.getNbNodes());
+    for(size_t i = 0; i < graph.getNbNodes(); ++i) {
+        results[i].resize(graph.getNbNodes());
+        std::ranges::move(computeShortestPathsFromNode(graph, i), results[i].begin());
+    }
+
+    return VehicleShortestPathContainer(results);
+}
+
+void VehicleShortestPathCalculation::computeAndUpdateShortestPathsForGraph(Graph &graph) {
+    VehicleShortestPathContainer results = computeShortestPathsForGraph(graph);
+    graph.setShortestSaevPaths(results.getDistanceMatrix());
+}
diff --git a/src/ShortestPath/Vehicle/VehicleShortestPathCalculation.h b/src/ShortestPath/Vehicle/VehicleShortestPathCalculation.h
index 4b6c16b..efd7122 100644
--- a/src/ShortestPath/Vehicle/VehicleShortestPathCalculation.h
+++ b/src/ShortestPath/Vehicle/VehicleShortestPathCalculation.h
@@ -6,7 +6,14 @@
 #define GREEDYALGORITHM_VEHICLESHORTESTPATHCALCULATION_H
 
 
+#include "VehicleShortestPathContainer.h"
+#include "../../instance/graph/Graph.h"
+
 class VehicleShortestPathCalculation {
+public:
+    static void computeAndUpdateShortestPathsForGraph(Graph& graph);
+    static VehicleShortestPathContainer computeShortestPathsForGraph(const Graph& graph);
+    static std::vector<uint> computeShortestPathsFromNode(const Graph& graph, size_t startingNodeIdx);
 
 };
 
-- 
GitLab


From f06631265a602dab7be4e0c7267db535df89c17f Mon Sep 17 00:00:00 2001
From: Romain BERNARD <romain.bernard@uca.fr>
Date: Mon, 22 Jul 2024 16:33:25 +0200
Subject: [PATCH 159/327] rename shortest paths container to be more precise on
 its format

---
 CMakeLists.txt                                   |  2 +-
 ...Container.h => MatrixShortestPathContainer.h} | 16 ++++++++--------
 .../Vehicle/VehicleShortestPathCalculation.cpp   |  7 ++++---
 .../Vehicle/VehicleShortestPathCalculation.h     |  4 ++--
 test/CMakeLists.txt                              |  1 +
 5 files changed, 16 insertions(+), 14 deletions(-)
 rename src/ShortestPath/Vehicle/{VehicleShortestPathContainer.h => MatrixShortestPathContainer.h} (76%)

diff --git a/CMakeLists.txt b/CMakeLists.txt
index e70091f..04bbbfc 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -115,12 +115,12 @@ add_executable(GraphGeneration
         src/algorithm/DARP/Heuristics/BestInsertionHeuristic.h
         src/algorithm/Multimodal/Heuristics/SimpleModularHeuristic.cpp
         src/algorithm/Multimodal/Heuristics/SimpleModularHeuristic.h
-        src/ShortestPath/Vehicle/VehicleShortestPath.cpp
         src/ShortestPath/Vehicle/VehicleShortestPath.h
         src/ShortestPath/Vehicle/VehiclePathState.h
         src/ShortestPath/Vehicle/VehicleShortestPathCalculation.cpp
         src/ShortestPath/Vehicle/VehicleShortestPathCalculation.h
         src/ShortestPath/Vehicle/VehicleShortestPathContainer.h
+        src/ShortestPath/Vehicle/MatrixShortestPathContainer.h
 )
 
 target_include_directories(GreedyAlgorithm PRIVATE ${PYTHON_INCLUDE_DIRS})
diff --git a/src/ShortestPath/Vehicle/VehicleShortestPathContainer.h b/src/ShortestPath/Vehicle/MatrixShortestPathContainer.h
similarity index 76%
rename from src/ShortestPath/Vehicle/VehicleShortestPathContainer.h
rename to src/ShortestPath/Vehicle/MatrixShortestPathContainer.h
index 0adbfa6..704c724 100644
--- a/src/ShortestPath/Vehicle/VehicleShortestPathContainer.h
+++ b/src/ShortestPath/Vehicle/MatrixShortestPathContainer.h
@@ -2,29 +2,29 @@
 // Created by romain on 16/07/24.
 //
 
-#ifndef GREEDYALGORITHM_VEHICLESHORTESTPATHCONTAINER_H
-#define GREEDYALGORITHM_VEHICLESHORTESTPATHCONTAINER_H
+#ifndef GREEDYALGORITHM_MATRIXSHORTESTPATHCONTAINER_H
+#define GREEDYALGORITHM_MATRIXSHORTESTPATHCONTAINER_H
 
 
 #include <vector>
 #include <cstdint>
 #include <algorithm>
 
-class VehicleShortestPathContainer {
+class MatrixShortestPathContainer {
 private:
     std::vector<std::vector<uint>> _distanceMatrix{};
 public:
-    VehicleShortestPathContainer() = default;
+    MatrixShortestPathContainer() = default;
 
     /**
      * Moves the given shortestPathsMatrix to initialize the container with the given distances.
      * @param shortestPathsMatrix
      */
-    explicit VehicleShortestPathContainer(std::vector<std::vector<uint>> shortestPathsMatrix) : _distanceMatrix(std::move(shortestPathsMatrix)) {}
+    explicit MatrixShortestPathContainer(std::vector<std::vector<uint>> shortestPathsMatrix) : _distanceMatrix(std::move(shortestPathsMatrix)) {}
 
-    explicit VehicleShortestPathContainer(size_t matrixSize) {
+    explicit MatrixShortestPathContainer(size_t matrixSize) {
         _distanceMatrix.resize(matrixSize);
-        for(int i = 0; i < _distanceMatrix.capacity(); ++i)
+        for(size_t i = 0; i < _distanceMatrix.capacity(); ++i)
             _distanceMatrix[i].resize(matrixSize, INT16_MAX);
     }
 
@@ -60,4 +60,4 @@ public:
 };
 
 
-#endif //GREEDYALGORITHM_VEHICLESHORTESTPATHCONTAINER_H
+#endif //GREEDYALGORITHM_MATRIXSHORTESTPATHCONTAINER_H
diff --git a/src/ShortestPath/Vehicle/VehicleShortestPathCalculation.cpp b/src/ShortestPath/Vehicle/VehicleShortestPathCalculation.cpp
index cb15117..2a16710 100644
--- a/src/ShortestPath/Vehicle/VehicleShortestPathCalculation.cpp
+++ b/src/ShortestPath/Vehicle/VehicleShortestPathCalculation.cpp
@@ -29,7 +29,7 @@ std::vector<uint> VehicleShortestPathCalculation::computeShortestPathsFromNode(c
     return results;
 }
 
-VehicleShortestPathContainer VehicleShortestPathCalculation::computeShortestPathsForGraph(const Graph &graph) {
+MatrixShortestPathContainer VehicleShortestPathCalculation::computeShortestPathsForGraph(const Graph &graph) {
     std::vector<std::vector<uint>> results;
     results.resize(graph.getNbNodes());
     for(size_t i = 0; i < graph.getNbNodes(); ++i) {
@@ -37,10 +37,11 @@ VehicleShortestPathContainer VehicleShortestPathCalculation::computeShortestPath
         std::ranges::move(computeShortestPathsFromNode(graph, i), results[i].begin());
     }
 
-    return VehicleShortestPathContainer(results);
+    return MatrixShortestPathContainer(results);
 }
 
+
 void VehicleShortestPathCalculation::computeAndUpdateShortestPathsForGraph(Graph &graph) {
-    VehicleShortestPathContainer results = computeShortestPathsForGraph(graph);
+    MatrixShortestPathContainer results = computeShortestPathsForGraph(graph);
     graph.setShortestSaevPaths(results.getDistanceMatrix());
 }
diff --git a/src/ShortestPath/Vehicle/VehicleShortestPathCalculation.h b/src/ShortestPath/Vehicle/VehicleShortestPathCalculation.h
index efd7122..49f11fd 100644
--- a/src/ShortestPath/Vehicle/VehicleShortestPathCalculation.h
+++ b/src/ShortestPath/Vehicle/VehicleShortestPathCalculation.h
@@ -6,13 +6,13 @@
 #define GREEDYALGORITHM_VEHICLESHORTESTPATHCALCULATION_H
 
 
-#include "VehicleShortestPathContainer.h"
+#include "MatrixShortestPathContainer.h"
 #include "../../instance/graph/Graph.h"
 
 class VehicleShortestPathCalculation {
 public:
     static void computeAndUpdateShortestPathsForGraph(Graph& graph);
-    static VehicleShortestPathContainer computeShortestPathsForGraph(const Graph& graph);
+    static MatrixShortestPathContainer computeShortestPathsForGraph(const Graph& graph);
     static std::vector<uint> computeShortestPathsFromNode(const Graph& graph, size_t startingNodeIdx);
 
 };
diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt
index 5d97ecd..283eb32 100644
--- a/test/CMakeLists.txt
+++ b/test/CMakeLists.txt
@@ -71,6 +71,7 @@ add_executable(Constraint_Propag_DEB
         "../src/utils/Instance Generation/Requests/RequestGenerationParameters.h"
         "../src/utils/Instance Generation/Graph/OSRMGraphGenerator.h"
         ../src/utils/Constants.h
+        ../src/ShortestPath/Vehicle/MatrixShortestPathContainer.h
 )
 
 add_executable(BestInsertionHeuristic_DEB
-- 
GitLab


From 9706fd6723507037f1c0c3913eff9209a8a89085 Mon Sep 17 00:00:00 2001
From: Romain BERNARD <romain.bernard@uca.fr>
Date: Mon, 22 Jul 2024 16:40:46 +0200
Subject: [PATCH 160/327] add container for a simple ordered destination list

---
 .../Vehicle/ClosestDestinationsContainer.h    | 46 +++++++++++++++++++
 src/ShortestPath/Vehicle/VehicleDestination.h | 46 +++++++++++++++++++
 2 files changed, 92 insertions(+)
 create mode 100644 src/ShortestPath/Vehicle/ClosestDestinationsContainer.h
 create mode 100644 src/ShortestPath/Vehicle/VehicleDestination.h

diff --git a/src/ShortestPath/Vehicle/ClosestDestinationsContainer.h b/src/ShortestPath/Vehicle/ClosestDestinationsContainer.h
new file mode 100644
index 0000000..d78f788
--- /dev/null
+++ b/src/ShortestPath/Vehicle/ClosestDestinationsContainer.h
@@ -0,0 +1,46 @@
+//
+// Created by romain on 22/07/24.
+//
+
+#ifndef GREEDYALGORITHM_CLOSESTDESTINATIONSCONTAINER_H
+#define GREEDYALGORITHM_CLOSESTDESTINATIONSCONTAINER_H
+
+
+#include <cstddef>
+#include <utility>
+#include <queue>
+#include <set>
+#include "VehicleShortestPath.h"
+#include "VehicleDestination.h"
+
+class ClosestDestinationsContainer {
+private:
+    size_t _startingNodeIdx;
+    std::set<VehicleDestination> _orderedDestinations{};
+
+public:
+    explicit ClosestDestinationsContainer(size_t startingNodeIdx) : _startingNodeIdx(startingNodeIdx) {}
+
+    size_t getStartingNodeIdx() const {
+        return _startingNodeIdx;
+    }
+
+    void setStartingNodeIdx(size_t startingNodeIdx) {
+        _startingNodeIdx = startingNodeIdx;
+    }
+
+    [[nodiscard]] const std::set<VehicleDestination> &getOrderedDestinations() const {
+        return _orderedDestinations;
+    }
+
+    auto cbegin() {
+        return _orderedDestinations.cbegin();
+    }
+
+    void addDestination(size_t destinationNodeIdx, uint distance) {
+        _orderedDestinations.emplace(destinationNodeIdx, distance);
+    }
+};
+
+
+#endif //GREEDYALGORITHM_CLOSESTDESTINATIONSCONTAINER_H
diff --git a/src/ShortestPath/Vehicle/VehicleDestination.h b/src/ShortestPath/Vehicle/VehicleDestination.h
new file mode 100644
index 0000000..423c40d
--- /dev/null
+++ b/src/ShortestPath/Vehicle/VehicleDestination.h
@@ -0,0 +1,46 @@
+//
+// Created by romain on 22/07/24.
+//
+
+#ifndef GREEDYALGORITHM_VEHICLEDESTINATION_H
+#define GREEDYALGORITHM_VEHICLEDESTINATION_H
+
+
+#include <cstddef>
+#include <cstdlib>
+#include <cstdint>
+#include <compare>
+
+class VehicleDestination {
+private:
+    size_t _destinationNodeIdx;
+    uint _distance{INT32_MAX};
+
+public:
+    explicit VehicleDestination(size_t destinationNodeIdx) : _destinationNodeIdx(destinationNodeIdx) {}
+    VehicleDestination(size_t destinationNodeIdx, uint distance) : _destinationNodeIdx(destinationNodeIdx),
+                                                                   _distance(distance) {}
+
+    [[nodiscard]] size_t getDestinationNodeIdx() const {
+        return _destinationNodeIdx;
+    }
+
+    void setDestinationNodeIdx(size_t destinationNodeIdx) {
+        _destinationNodeIdx = destinationNodeIdx;
+    }
+
+    [[nodiscard]] uint getDistance() const {
+        return _distance;
+    }
+
+    void setDistance(uint distance) {
+        _distance = distance;
+    }
+
+    auto operator<=>(const VehicleDestination &rhs) const {
+        return std::strong_order(_distance, rhs.getDistance());
+    }
+};
+
+
+#endif //GREEDYALGORITHM_VEHICLEDESTINATION_H
-- 
GitLab


From b91654ba3b7cd6cb76a7cc3484cce9d6242e4730 Mon Sep 17 00:00:00 2001
From: Romain BERNARD <romain.bernard@uca.fr>
Date: Mon, 22 Jul 2024 18:02:41 +0200
Subject: [PATCH 161/327] rename arguments

---
 src/instance/graph/Graph.h | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/src/instance/graph/Graph.h b/src/instance/graph/Graph.h
index 5a64241..b757559 100644
--- a/src/instance/graph/Graph.h
+++ b/src/instance/graph/Graph.h
@@ -154,7 +154,7 @@ public:
 
     void setShortestSaevPaths(const std::vector<std::vector<uint>> &shortestSaevPaths);
 
-    [[nodiscard]] uint getShortestSAEVPath(size_t x, size_t y) const { return shortestSAEVPaths[x][y]; }
+    [[nodiscard]] uint getShortestSAEVPath(size_t startingNodeIdx, size_t destinationNodeIdx) const { return shortestSAEVPaths[startingNodeIdx][destinationNodeIdx]; }
 
     void parseDistanceMatrix(std::ifstream &infile, DATRow currentRow);
 };
-- 
GitLab


From e785cd1fba599fdbbb99d715d5651b72d9389b8b Mon Sep 17 00:00:00 2001
From: Romain BERNARD <romain.bernard@uca.fr>
Date: Mon, 22 Jul 2024 18:03:33 +0200
Subject: [PATCH 162/327] add a new function to get closest PT nodes from a
 given point

---
 .../Vehicle/VehicleShortestPathCalculation.cpp      | 13 ++++++++++++-
 .../Vehicle/VehicleShortestPathCalculation.h        | 10 +++++++++-
 2 files changed, 21 insertions(+), 2 deletions(-)

diff --git a/src/ShortestPath/Vehicle/VehicleShortestPathCalculation.cpp b/src/ShortestPath/Vehicle/VehicleShortestPathCalculation.cpp
index 2a16710..cf04907 100644
--- a/src/ShortestPath/Vehicle/VehicleShortestPathCalculation.cpp
+++ b/src/ShortestPath/Vehicle/VehicleShortestPathCalculation.cpp
@@ -40,8 +40,19 @@ MatrixShortestPathContainer VehicleShortestPathCalculation::computeShortestPaths
     return MatrixShortestPathContainer(results);
 }
 
-
 void VehicleShortestPathCalculation::computeAndUpdateShortestPathsForGraph(Graph &graph) {
     MatrixShortestPathContainer results = computeShortestPathsForGraph(graph);
     graph.setShortestSaevPaths(results.getDistanceMatrix());
 }
+
+ClosestDestinationsContainer
+VehicleShortestPathCalculation::getClosestPTNodesFromX(const Graph &graph, size_t startingNodeIdx) {
+    ClosestDestinationsContainer closestDestinationsContainer(startingNodeIdx);
+    for(size_t destinationIdx=0; destinationIdx < graph.getNbNodes(); ++destinationIdx) {
+        if(graph.getNbPTLines(destinationIdx) > 0) {
+            closestDestinationsContainer.addDestination(destinationIdx,
+                                                        graph.getShortestSAEVPath(startingNodeIdx, destinationIdx));
+        }
+    }
+    return closestDestinationsContainer;
+}
diff --git a/src/ShortestPath/Vehicle/VehicleShortestPathCalculation.h b/src/ShortestPath/Vehicle/VehicleShortestPathCalculation.h
index 49f11fd..436644f 100644
--- a/src/ShortestPath/Vehicle/VehicleShortestPathCalculation.h
+++ b/src/ShortestPath/Vehicle/VehicleShortestPathCalculation.h
@@ -8,13 +8,21 @@
 
 #include "MatrixShortestPathContainer.h"
 #include "../../instance/graph/Graph.h"
+#include "ClosestDestinationsContainer.h"
 
 class VehicleShortestPathCalculation {
 public:
     static void computeAndUpdateShortestPathsForGraph(Graph& graph);
     static MatrixShortestPathContainer computeShortestPathsForGraph(const Graph& graph);
     static std::vector<uint> computeShortestPathsFromNode(const Graph& graph, size_t startingNodeIdx);
-
+    /**
+     * Returns an ordered set of closest PT SAV-compatible nodes from a given starting node index.
+     * Standard use case expects that the starting node index is a request origin
+     * @param graph
+     * @param startingNodeIdx
+     * @return An ordered set containing PT nodes accessible via SAV from the given starting node index
+     */
+    static ClosestDestinationsContainer getClosestPTNodesFromX(const Graph& graph, size_t startingNodeIdx);
 };
 
 
-- 
GitLab


From 8fd7806416b74c5cecd90df39279e2aabaedcb13 Mon Sep 17 00:00:00 2001
From: Romain BERNARD <romain.bernard@uca.fr>
Date: Mon, 22 Jul 2024 18:04:01 +0200
Subject: [PATCH 163/327] add doc

---
 .../Vehicle/VehicleShortestPathCalculation.h     | 16 ++++++++++++++++
 1 file changed, 16 insertions(+)

diff --git a/src/ShortestPath/Vehicle/VehicleShortestPathCalculation.h b/src/ShortestPath/Vehicle/VehicleShortestPathCalculation.h
index 436644f..3f40cca 100644
--- a/src/ShortestPath/Vehicle/VehicleShortestPathCalculation.h
+++ b/src/ShortestPath/Vehicle/VehicleShortestPathCalculation.h
@@ -12,8 +12,24 @@
 
 class VehicleShortestPathCalculation {
 public:
+    /**
+     * Computes shortest paths from the given graph's distance matrix
+     * @param graph
+     */
     static void computeAndUpdateShortestPathsForGraph(Graph& graph);
+    /**
+     * Computes and returns an updated distance matrix from the given graph's distance matrix computed via Dijsktra's algorithm
+     * @param graph
+     * @return A matrix distances container
+     */
     static MatrixShortestPathContainer computeShortestPathsForGraph(const Graph& graph);
+    /**
+     * Computes the shortest paths to all the nodes in the graph from the given starting node.
+     * If a node is unreachable its default distance is INT32_MAX. Distance from the starting node to itself is 0
+     * @param graph
+     * @param startingNodeIdx
+     * @return a vector indexed by all the nodes with the sortest path's duration from the starting node to the destination node index
+     */
     static std::vector<uint> computeShortestPathsFromNode(const Graph& graph, size_t startingNodeIdx);
     /**
      * Returns an ordered set of closest PT SAV-compatible nodes from a given starting node index.
-- 
GitLab


From 9c301263163687be72a4a39ba5f12e71c2c0ed32 Mon Sep 17 00:00:00 2001
From: Romain BERNARD <romain.bernard@uca.fr>
Date: Mon, 22 Jul 2024 18:08:21 +0200
Subject: [PATCH 164/327] remove unnecessary cpp file

---
 src/ShortestPath/Vehicle/VehicleShortestPath.cpp | 5 -----
 1 file changed, 5 deletions(-)
 delete mode 100644 src/ShortestPath/Vehicle/VehicleShortestPath.cpp

diff --git a/src/ShortestPath/Vehicle/VehicleShortestPath.cpp b/src/ShortestPath/Vehicle/VehicleShortestPath.cpp
deleted file mode 100644
index b315976..0000000
--- a/src/ShortestPath/Vehicle/VehicleShortestPath.cpp
+++ /dev/null
@@ -1,5 +0,0 @@
-//
-// Created by romain on 16/07/24.
-//
-
-#include "VehicleShortestPath.h"
-- 
GitLab


From e839df45660a17dcb06830b20688ad2497d97c52 Mon Sep 17 00:00:00 2001
From: Romain BERNARD <romain.bernard@uca.fr>
Date: Tue, 23 Jul 2024 14:43:43 +0200
Subject: [PATCH 165/327] add closest stations collections to nodes for the
 future algorithm requirements

---
 src/instance/graph/Graph.cpp | 8 ++++++++
 src/instance/graph/Graph.h   | 4 ++++
 src/instance/graph/Node.cpp  | 8 ++++++++
 src/instance/graph/Node.h    | 5 +++++
 4 files changed, 25 insertions(+)

diff --git a/src/instance/graph/Graph.cpp b/src/instance/graph/Graph.cpp
index 1e4b8cf..54d24f8 100644
--- a/src/instance/graph/Graph.cpp
+++ b/src/instance/graph/Graph.cpp
@@ -335,3 +335,11 @@ const std::vector<std::vector<uint>> &Graph::getShortestSaevPaths() const {
 void Graph::setShortestSaevPaths(const std::vector<std::vector<uint>> &shortestSaevPaths) {
     shortestSAEVPaths = shortestSaevPaths;
 }
+
+void Graph::emplaceBackClosestStation(size_t nodeIdx, size_t stationNodeIdx) {
+    nodesVector[nodeIdx].emplaceBackClosestStation(stationNodeIdx);
+}
+
+const size_t Graph::getNbClosestStations(size_t nodeIdx) {
+    return nodesVector[nodeIdx].getClosestStationsNodeIdxVector().size();
+}
diff --git a/src/instance/graph/Graph.h b/src/instance/graph/Graph.h
index b757559..72d0cf4 100644
--- a/src/instance/graph/Graph.h
+++ b/src/instance/graph/Graph.h
@@ -157,6 +157,10 @@ public:
     [[nodiscard]] uint getShortestSAEVPath(size_t startingNodeIdx, size_t destinationNodeIdx) const { return shortestSAEVPaths[startingNodeIdx][destinationNodeIdx]; }
 
     void parseDistanceMatrix(std::ifstream &infile, DATRow currentRow);
+
+    void emplaceBackClosestStation(size_t nodeIdx, size_t stationNodeIdx);
+
+    const size_t getNbClosestStations(size_t nodeIdx);
 };
 
 
diff --git a/src/instance/graph/Node.cpp b/src/instance/graph/Node.cpp
index 6b6f7d9..f11ba11 100644
--- a/src/instance/graph/Node.cpp
+++ b/src/instance/graph/Node.cpp
@@ -47,3 +47,11 @@ Status  Node::statusFromString(std::string from) {
         return Status::work;
     }
 }
+
+void Node::emplaceBackClosestStation(size_t closestStationIdx) {
+    _closestStationsNodeIdxVector.emplace_back(closestStationIdx);
+}
+
+const std::vector<size_t> Node::getClosestStationsNodeIdxVector() {
+    return _closestStationsNodeIdxVector;
+}
diff --git a/src/instance/graph/Node.h b/src/instance/graph/Node.h
index 9e6ee2c..3fc611d 100644
--- a/src/instance/graph/Node.h
+++ b/src/instance/graph/Node.h
@@ -35,6 +35,7 @@ private:
     std::vector<LineStop> _ptLines;
     std::vector<int> _incomingEdgesIndex; //List of edge index in the graph structure for all edges leading to this node
     std::vector<int> _outgoingEdgesIndex; //List of edge index in the graph structure for all edges leading to this node
+    std::vector<size_t> _closestStationsNodeIdxVector;
     //TODO : Should these vectors be considered complete over the whole set of nodes ? Probably ? Considering we will probably pre-process shortest paths between all SAEV stations
 
 public:
@@ -88,6 +89,10 @@ public:
      * @return True if any of _x, _y and _status is not equal between both sides of the operator, false otherwise
      */
     bool operator!=(const Node& rhs) const;
+
+    void emplaceBackClosestStation(size_t closestStationIdx);
+
+    const std::vector<size_t> getClosestStationsNodeIdxVector();
 };
 #include "Line.h"
 #include "LineStop.h"
-- 
GitLab


From f733f77990d71a081bb22c8c557f3a84ccf59b84 Mon Sep 17 00:00:00 2001
From: Romain BERNARD <romain.bernard@uca.fr>
Date: Tue, 23 Jul 2024 14:44:56 +0200
Subject: [PATCH 166/327] refactor shortest paths calculations to compute
 closest stations in the same run

---
 CMakeLists.txt                                |  3 +-
 src/ShortestPath/Vehicle/VehiclePathState.h   |  6 +---
 .../VehicleShortestPathCalculation.cpp        | 34 +++++++++++++------
 .../Vehicle/VehicleShortestPathCalculation.h  |  4 +--
 test/CMakeLists.txt                           |  4 +++
 5 files changed, 33 insertions(+), 18 deletions(-)

diff --git a/CMakeLists.txt b/CMakeLists.txt
index 04bbbfc..cb5198f 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -119,8 +119,9 @@ add_executable(GraphGeneration
         src/ShortestPath/Vehicle/VehiclePathState.h
         src/ShortestPath/Vehicle/VehicleShortestPathCalculation.cpp
         src/ShortestPath/Vehicle/VehicleShortestPathCalculation.h
-        src/ShortestPath/Vehicle/VehicleShortestPathContainer.h
         src/ShortestPath/Vehicle/MatrixShortestPathContainer.h
+        src/ShortestPath/Vehicle/ClosestDestinationsContainer.h
+        src/ShortestPath/Vehicle/VehicleDestination.h
 )
 
 target_include_directories(GreedyAlgorithm PRIVATE ${PYTHON_INCLUDE_DIRS})
diff --git a/src/ShortestPath/Vehicle/VehiclePathState.h b/src/ShortestPath/Vehicle/VehiclePathState.h
index 7e81806..2907a68 100644
--- a/src/ShortestPath/Vehicle/VehiclePathState.h
+++ b/src/ShortestPath/Vehicle/VehiclePathState.h
@@ -35,11 +35,7 @@ public:
     }
 
     auto operator<=>(const VehiclePathState &rhs) const {
-        if (this->_nodeIndex != rhs.getNodeIndex()) {
-            return std::partial_ordering::unordered;
-        }
-
-        return std::partial_order(_instant, rhs.getInstant());
+        return _instant <=> rhs.getInstant();
     }
 };
 
diff --git a/src/ShortestPath/Vehicle/VehicleShortestPathCalculation.cpp b/src/ShortestPath/Vehicle/VehicleShortestPathCalculation.cpp
index cf04907..b0f4710 100644
--- a/src/ShortestPath/Vehicle/VehicleShortestPathCalculation.cpp
+++ b/src/ShortestPath/Vehicle/VehicleShortestPathCalculation.cpp
@@ -5,23 +5,37 @@
 #include <queue>
 #include "VehicleShortestPathCalculation.h"
 #include "VehiclePathState.h"
+#include "../../utils/Constants.h"
 
-std::vector<uint> VehicleShortestPathCalculation::computeShortestPathsFromNode(const Graph& graph, size_t startingNodeIdx) {
+std::vector<uint> VehicleShortestPathCalculation::computeShortestPathsFromNode(Graph& graph, size_t startingNodeIdx) {
     std::vector<uint> results{graph.getShortestSaevPaths()[startingNodeIdx]};
-    std::priority_queue<VehiclePathState> stateQueue{};
-    stateQueue.emplace(startingNodeIdx, 0);
+    std::vector<bool> mark(graph.getNbNodes(),false);
+    std::priority_queue<VehiclePathState,std::vector<VehiclePathState>, std::greater<>> stateQueue{};
+
+    //Init state queue with the current distances to check
+    for(size_t i = 0; i < graph.getNbNodes(); ++i) {
+        stateQueue.emplace(i, results[i]);
+    }
 
     uint newDistance = INT32_MAX;
     VehiclePathState currentState;
     while(!stateQueue.empty()) {
         currentState = stateQueue.top();
         stateQueue.pop();
-        //Iterate over all possible nodes, as the graph is complete in the case of a distance matrix
-        for(size_t i = 0; i < results.capacity(); ++i) {
-            newDistance = currentState.getInstant() + graph.getShortestSAEVPath(currentState.getNodeIndex(), i);
-            if(newDistance < results[i]) {
-                stateQueue.emplace(i, newDistance);
-                results[i] = newDistance;
+        //Only expand and add
+        if(!mark[currentState.getNodeIndex()]) {
+            //Considering order of iteration is by shortest path to starting node, it's fair to add the current state node as a closest station
+            if(graph.getNbPTLines(currentState.getNodeIndex()) > 0 && graph.getNbClosestStations(startingNodeIdx) < Constants::MAX_TRANSIT_ENTRY_CANDIDATES) {
+                graph.emplaceBackClosestStation(startingNodeIdx, currentState.getNodeIndex());
+            }
+
+            //Iterate over all possible nodes, as the graph is complete in the case of a distance matrix
+            for(size_t i = 0; i < results.capacity(); ++i) { //FIXME:change iteration here to allow using edges
+                newDistance = currentState.getInstant() + graph.getShortestSAEVPath(currentState.getNodeIndex(), i);
+                if(newDistance < results[i]) {
+                    stateQueue.emplace(i, newDistance);
+                    results[i] = newDistance;
+                }
             }
         }
     }
@@ -29,7 +43,7 @@ std::vector<uint> VehicleShortestPathCalculation::computeShortestPathsFromNode(c
     return results;
 }
 
-MatrixShortestPathContainer VehicleShortestPathCalculation::computeShortestPathsForGraph(const Graph &graph) {
+MatrixShortestPathContainer VehicleShortestPathCalculation::computeShortestPathsForGraph(Graph &graph) {
     std::vector<std::vector<uint>> results;
     results.resize(graph.getNbNodes());
     for(size_t i = 0; i < graph.getNbNodes(); ++i) {
diff --git a/src/ShortestPath/Vehicle/VehicleShortestPathCalculation.h b/src/ShortestPath/Vehicle/VehicleShortestPathCalculation.h
index 3f40cca..9fbfda8 100644
--- a/src/ShortestPath/Vehicle/VehicleShortestPathCalculation.h
+++ b/src/ShortestPath/Vehicle/VehicleShortestPathCalculation.h
@@ -22,7 +22,7 @@ public:
      * @param graph
      * @return A matrix distances container
      */
-    static MatrixShortestPathContainer computeShortestPathsForGraph(const Graph& graph);
+    static MatrixShortestPathContainer computeShortestPathsForGraph(Graph& graph);
     /**
      * Computes the shortest paths to all the nodes in the graph from the given starting node.
      * If a node is unreachable its default distance is INT32_MAX. Distance from the starting node to itself is 0
@@ -30,7 +30,7 @@ public:
      * @param startingNodeIdx
      * @return a vector indexed by all the nodes with the sortest path's duration from the starting node to the destination node index
      */
-    static std::vector<uint> computeShortestPathsFromNode(const Graph& graph, size_t startingNodeIdx);
+    static std::vector<uint> computeShortestPathsFromNode(Graph& graph, size_t startingNodeIdx);
     /**
      * Returns an ordered set of closest PT SAV-compatible nodes from a given starting node index.
      * Standard use case expects that the starting node index is a request origin
diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt
index 283eb32..d7ec2f4 100644
--- a/test/CMakeLists.txt
+++ b/test/CMakeLists.txt
@@ -71,6 +71,10 @@ add_executable(Constraint_Propag_DEB
         "../src/utils/Instance Generation/Requests/RequestGenerationParameters.h"
         "../src/utils/Instance Generation/Graph/OSRMGraphGenerator.h"
         ../src/utils/Constants.h
+        ../src/ShortestPath/Vehicle/VehiclePathState.h
+        ../src/ShortestPath/Vehicle/VehicleShortestPath.h
+        ../src/ShortestPath/Vehicle/VehicleShortestPathCalculation.h
+        ../src/ShortestPath/Vehicle/VehicleShortestPathCalculation.cpp
         ../src/ShortestPath/Vehicle/MatrixShortestPathContainer.h
 )
 
-- 
GitLab


From 0c469d242f1f124d2e84795feb9eb5a5df9cde66 Mon Sep 17 00:00:00 2001
From: Romain BERNARD <30secondstodraw@gmail.com>
Date: Wed, 24 Jul 2024 10:51:11 +0200
Subject: [PATCH 167/327] add global typedef to fix windows builds

---
 CMakeLists.txt            | 56 +++++++++++++++++++++++----------------
 src/TimeWindow.h          |  1 +
 src/instance/graph/Line.h |  1 +
 src/utils/Globals.h       | 11 ++++++++
 test/CMakeLists.txt       |  2 ++
 5 files changed, 48 insertions(+), 23 deletions(-)
 create mode 100644 src/utils/Globals.h

diff --git a/CMakeLists.txt b/CMakeLists.txt
index 818e1d2..3b19667 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -62,6 +62,7 @@ add_executable(GreedyAlgorithm
         src/routes/vehicle/BestRequestInsertion.h
         src/routes/vehicle/BestInsertionQueue.h
         src/utils/Constants.h
+        src/utils/Globals.h
 )
 
 add_executable(RequestGenerator
@@ -90,29 +91,7 @@ add_executable(RequestGenerator
         "src/utils/Instance Generation/Requests/RequestsGenerator.h"
         "src/utils/Instance Generation/Requests/RequestGenerationParameters.h"
         "src/utils/Instance Generation/Graph/OSRMGraphGenerator.h"
-)
-
-add_executable(GraphGeneration
-        src/instance/graph/Node.cpp
-        src/instance/graph/Node.h
-        src/instance/graph/Edge.cpp
-        src/instance/graph/Edge.h
-        src/instance/graph/Graph.cpp
-        src/instance/graph/Graph.h
-        src/instance/Instance.cpp
-        src/instance/Instance.h
-        src/instance/graph/Line.cpp
-        src/instance/graph/Line.h
-        src/services/CSV/CSVRange.h
-        src/services/CSV/CSVIterator.h
-        src/instance/graph/LineStop.cpp
-        src/instance/graph/LineStop.h
-        src/services/DatFile/DATRow.h
-        "src/utils/Instance Generation/Graph/OSRMGraphGenerator.h"
-        "src/utils/Instance Generation/Graph/GraphGenerator.h"
-        "src/utils/Instance Generation/Graph/PTLineGenerationParameters.h"
-        src/algorithm/DARP/Heuristics/BestInsertionHeuristic.cpp
-        src/algorithm/DARP/Heuristics/BestInsertionHeuristic.h
+        src/utils/Globals.h
         src/algorithm/Multimodal/Heuristics/SimpleModularHeuristic.cpp
         src/algorithm/Multimodal/Heuristics/SimpleModularHeuristic.h
         src/ShortestPath/Vehicle/VehicleShortestPath.cpp
@@ -124,6 +103,37 @@ add_executable(GraphGeneration
         src/ShortestPath/Vehicle/VehicleShortestPathContainer.h
 )
 
+#add_executable(GraphGeneration
+#        src/instance/graph/Node.cpp
+#        src/instance/graph/Node.h
+#        src/instance/graph/Edge.cpp
+#        src/instance/graph/Edge.h
+#        src/instance/graph/Graph.cpp
+#        src/instance/graph/Graph.h
+#        src/instance/Instance.cpp
+#        src/instance/Instance.h
+#        src/instance/graph/Line.cpp
+#        src/instance/graph/Line.h
+#        src/services/CSV/CSVRange.h
+#        src/services/CSV/CSVIterator.h
+#        src/instance/graph/LineStop.cpp
+#        src/instance/graph/LineStop.h
+#        src/services/DatFile/DATRow.h
+#        "src/utils/Instance Generation/Graph/OSRMGraphGenerator.h"
+#        "src/utils/Instance Generation/Graph/GraphGenerator.h"
+#        "src/utils/Instance Generation/Graph/PTLineGenerationParameters.h"
+#        src/algorithm/DARP/Heuristics/BestInsertionHeuristic.cpp
+#        src/algorithm/DARP/Heuristics/BestInsertionHeuristic.h
+#        src/algorithm/Multimodal/Heuristics/SimpleModularHeuristic.cpp
+#        src/algorithm/Multimodal/Heuristics/SimpleModularHeuristic.h
+#        src/ShortestPath/Vehicle/VehicleShortestPath.cpp
+#        src/ShortestPath/Vehicle/VehicleShortestPath.h
+#        src/ShortestPath/Vehicle/VehiclePathState.h
+#        src/ShortestPath/Vehicle/VehicleShortestPathCalculation.cpp
+#        src/ShortestPath/Vehicle/VehicleShortestPathCalculation.h
+#        src/ShortestPath/Vehicle/VehicleShortestPathContainer.h
+#)
+
 target_include_directories(GreedyAlgorithm PRIVATE ${PYTHON_INCLUDE_DIRS})
 target_link_libraries(GreedyAlgorithm ${PYTHON_LIBRARIES})
 
diff --git a/src/TimeWindow.h b/src/TimeWindow.h
index 04daa4b..5024c7d 100644
--- a/src/TimeWindow.h
+++ b/src/TimeWindow.h
@@ -6,6 +6,7 @@
 #define GREEDYALGORITHM_TIMEWINDOW_H
 
 #include <cstdlib>
+#include "utils/Globals.h"
 
 /**
  * Represents [min, max] time windows with appropriate operators for TW operations (+,-,isInTimeWindow).
diff --git a/src/instance/graph/Line.h b/src/instance/graph/Line.h
index da7fcfb..2b8bbc9 100644
--- a/src/instance/graph/Line.h
+++ b/src/instance/graph/Line.h
@@ -10,6 +10,7 @@
 #include <vector>
 #include <string>
 #include "../../utils/SearchAlgorithms.h"
+#include "../../utils/Globals.h"
 
 class Line {
 private:
diff --git a/src/utils/Globals.h b/src/utils/Globals.h
new file mode 100644
index 0000000..43b8f61
--- /dev/null
+++ b/src/utils/Globals.h
@@ -0,0 +1,11 @@
+//
+// Created by Bebs on 19/07/2024.
+//
+
+#ifndef GREEDYALGORITHM_GLOBALS_H
+#define GREEDYALGORITHM_GLOBALS_H
+
+typedef unsigned int uint;
+typedef unsigned long ulong;
+
+#endif //GREEDYALGORITHM_GLOBALS_H
diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt
index 5d97ecd..bc34d4b 100644
--- a/test/CMakeLists.txt
+++ b/test/CMakeLists.txt
@@ -17,6 +17,7 @@ add_executable(Line_UT
         ../src/instance/graph/Graph.h
         ../src/instance/graph/Line.cpp
         ../src/instance/graph/Line.h
+        ../src/utils/Globals.h
 )
 
 add_executable(Transit_Preprocess_DEB
@@ -35,6 +36,7 @@ add_executable(Transit_Preprocess_DEB
         ../src/ShortestPath/Transit/TransitShortestPathContainer.h
         ../src/ShortestPath/Transit/TransitShortestPathPrecompute.cpp
         ../src/ShortestPath/Transit/TransitShortestPathPrecompute.h
+        ../src/utils/Globals.h
 )
 
 
-- 
GitLab


From c23a32f8c95d061a6522a48fbfaac7fc4e078fb1 Mon Sep 17 00:00:00 2001
From: Romain BERNARD <30secondstodraw@gmail.com>
Date: Wed, 24 Jul 2024 11:10:00 +0200
Subject: [PATCH 168/327] fix CMakeLists.txt due to wrong commits

---
 CMakeLists.txt | 59 +++++++++++++++++++++++++-------------------------
 1 file changed, 29 insertions(+), 30 deletions(-)

diff --git a/CMakeLists.txt b/CMakeLists.txt
index 7298613..12c2ab3 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -92,8 +92,8 @@ add_executable(RequestGenerator
         "src/utils/Instance Generation/Requests/RequestGenerationParameters.h"
         "src/utils/Instance Generation/Graph/OSRMGraphGenerator.h"
         src/utils/Globals.h
-        src/algorithm/Multimodal/Heuristics/SimpleModularHeuristic.cpp
-        src/algorithm/Multimodal/Heuristics/SimpleModularHeuristic.h
+#        src/algorithm/Multimodal/Heuristics/SimpleModularHeuristic.cpp
+#        src/algorithm/Multimodal/Heuristics/SimpleModularHeuristic.h
         src/ShortestPath/Vehicle/VehicleShortestPath.h
         src/ShortestPath/Vehicle/VehiclePathState.h
         src/ShortestPath/Vehicle/VehicleShortestPathCalculation.cpp
@@ -103,36 +103,35 @@ add_executable(RequestGenerator
         src/ShortestPath/Vehicle/VehicleDestination.h
 )
 
-#add_executable(GraphGeneration
-#        src/instance/graph/Node.cpp
-#        src/instance/graph/Node.h
-#        src/instance/graph/Edge.cpp
-#        src/instance/graph/Edge.h
-#        src/instance/graph/Graph.cpp
-#        src/instance/graph/Graph.h
-#        src/instance/Instance.cpp
-#        src/instance/Instance.h
-#        src/instance/graph/Line.cpp
-#        src/instance/graph/Line.h
-#        src/services/CSV/CSVRange.h
-#        src/services/CSV/CSVIterator.h
-#        src/instance/graph/LineStop.cpp
-#        src/instance/graph/LineStop.h
-#        src/services/DatFile/DATRow.h
-#        "src/utils/Instance Generation/Graph/OSRMGraphGenerator.h"
-#        "src/utils/Instance Generation/Graph/GraphGenerator.h"
-#        "src/utils/Instance Generation/Graph/PTLineGenerationParameters.h"
-#        src/algorithm/DARP/Heuristics/BestInsertionHeuristic.cpp
-#        src/algorithm/DARP/Heuristics/BestInsertionHeuristic.h
+add_executable(GraphGeneration
+        src/instance/graph/Node.cpp
+        src/instance/graph/Node.h
+        src/instance/graph/Edge.cpp
+        src/instance/graph/Edge.h
+        src/instance/graph/Graph.cpp
+        src/instance/graph/Graph.h
+        src/instance/Instance.cpp
+        src/instance/Instance.h
+        src/instance/graph/Line.cpp
+        src/instance/graph/Line.h
+        src/services/CSV/CSVRange.h
+        src/services/CSV/CSVIterator.h
+        src/instance/graph/LineStop.cpp
+        src/instance/graph/LineStop.h
+        src/services/DatFile/DATRow.h
+        "src/utils/Instance Generation/Graph/OSRMGraphGenerator.h"
+        "src/utils/Instance Generation/Graph/GraphGenerator.h"
+        "src/utils/Instance Generation/Graph/PTLineGenerationParameters.h"
+        src/algorithm/DARP/Heuristics/BestInsertionHeuristic.cpp
+        src/algorithm/DARP/Heuristics/BestInsertionHeuristic.h
 #        src/algorithm/Multimodal/Heuristics/SimpleModularHeuristic.cpp
 #        src/algorithm/Multimodal/Heuristics/SimpleModularHeuristic.h
-#        src/ShortestPath/Vehicle/VehicleShortestPath.cpp
-#        src/ShortestPath/Vehicle/VehicleShortestPath.h
-#        src/ShortestPath/Vehicle/VehiclePathState.h
-#        src/ShortestPath/Vehicle/VehicleShortestPathCalculation.cpp
-#        src/ShortestPath/Vehicle/VehicleShortestPathCalculation.h
-#        src/ShortestPath/Vehicle/VehicleShortestPathContainer.h
-#)
+        src/ShortestPath/Vehicle/VehicleShortestPath.h
+        src/ShortestPath/Vehicle/VehiclePathState.h
+        src/ShortestPath/Vehicle/VehicleShortestPathCalculation.cpp
+        src/ShortestPath/Vehicle/VehicleShortestPathCalculation.h
+        src/ShortestPath/Vehicle/MatrixShortestPathContainer.h
+)
 
 target_include_directories(GreedyAlgorithm PRIVATE ${PYTHON_INCLUDE_DIRS})
 target_link_libraries(GreedyAlgorithm ${PYTHON_LIBRARIES})
-- 
GitLab


From 77d7874fb4902d17cbedbb4ece3cd9b1cb281086 Mon Sep 17 00:00:00 2001
From: Romain BERNARD <30secondstodraw@gmail.com>
Date: Wed, 24 Jul 2024 12:53:53 +0200
Subject: [PATCH 169/327] refactor edges API

---
 src/instance/graph/Edge.cpp  | 28 +++++++++++-----------------
 src/instance/graph/Edge.h    | 23 ++++++++++-------------
 src/instance/graph/Graph.cpp |  2 +-
 src/instance/graph/Graph.h   |  1 +
 4 files changed, 23 insertions(+), 31 deletions(-)

diff --git a/src/instance/graph/Edge.cpp b/src/instance/graph/Edge.cpp
index 5c8a043..c9be6db 100644
--- a/src/instance/graph/Edge.cpp
+++ b/src/instance/graph/Edge.cpp
@@ -4,32 +4,26 @@
 
 #include "Edge.h"
 
-int Edge::getNodeStart() const {
-    return _start;
+size_t Edge::getStartNodeIdx() const {
+    return _startNodeIdx;
 }
 
-void Edge::setNodeStart(int start) {
-    Edge::_start = start;
+void Edge::setStartNodeIdx(size_t startNodeIdx) {
+    Edge::_startNodeIdx = startNodeIdx;
 }
 
-int Edge::getNodeEnd() const {
-    return _end;
+size_t Edge::getEndNodeIdx() const {
+    return _endNodeIdx;
 }
 
-void Edge::setNodeEnd(int end) {
-    Edge::_end = end;
+void Edge::setEndNodeIdx(size_t endNodeIdx) {
+    Edge::_endNodeIdx = endNodeIdx;
 }
 
-double Edge::getLength() const {
+uint Edge::getLength() const {
     return _length;
 }
 
-void Edge::setLength(double d) {
-    Edge::_length = d;
-}
-
-Edge::Edge(int start, int end, double length) {
-    _start = start;
-    _end = end;
-    _length = length;
+void Edge::setLength(uint length) {
+    Edge::_length = length;
 }
diff --git a/src/instance/graph/Edge.h b/src/instance/graph/Edge.h
index a7126a0..064c4a4 100644
--- a/src/instance/graph/Edge.h
+++ b/src/instance/graph/Edge.h
@@ -10,24 +10,21 @@
 
 class Edge {
 private:
-    int _start;
-    int _end;
-    double _length;
+    size_t _startNodeIdx;
+    size_t _endNodeIdx;
+    uint _length;
 
 public:
-    int getNodeStart() const;
+    [[nodiscard]] size_t getStartNodeIdx() const;
+    void setStartNodeIdx(size_t startNodeIdx);
 
-    void setNodeStart(int start);
+    [[nodiscard]] size_t getEndNodeIdx() const;
+    void setEndNodeIdx(size_t endNodeIdx);
 
-    int getNodeEnd() const;
+    [[nodiscard]] uint getLength() const;
+    void setLength(uint length);
 
-    void setNodeEnd(int end);
-
-    double getLength() const;
-
-    void setLength(double d);
-
-    Edge(int start, int end, double length);
+    Edge(size_t startNodeIdx, size_t endNodeIdx, uint length) : _startNodeIdx(startNodeIdx), _endNodeIdx(endNodeIdx), _length(length) {}
 };
 
 
diff --git a/src/instance/graph/Graph.cpp b/src/instance/graph/Graph.cpp
index 54d24f8..c05fc96 100644
--- a/src/instance/graph/Graph.cpp
+++ b/src/instance/graph/Graph.cpp
@@ -133,7 +133,7 @@ void Graph::exportGraphToFile(const fs::path& exportFolderPath) {
     if(!edgesVector.empty()) {
         outfileGraph << "#Edges format : node_in,node_out,length" << std::endl;
         for (auto &edge: this->edgesVector) {
-            outfileGraph << edge.getNodeStart() << "," << edge.getNodeEnd() << "," << edge.getLength() << std::endl;
+            outfileGraph << edge.getStartNodeIdx() << "," << edge.getEndNodeIdx() << "," << edge.getLength() << std::endl;
         }
     }
 
diff --git a/src/instance/graph/Graph.h b/src/instance/graph/Graph.h
index 72d0cf4..61c4627 100644
--- a/src/instance/graph/Graph.h
+++ b/src/instance/graph/Graph.h
@@ -74,6 +74,7 @@ public:
         return nodesVector[nodeIndex].getOutgoingEdges().size();
     }
 
+    //TODO: try and define an Edge iterator over a given node's incoming/outgoing
 
     [[nodiscard]] size_t getNbEdges(size_t nodeIndex) const {
         return nodesVector[nodeIndex].getIncomingEdges().size() + nodesVector[nodeIndex].getOutgoingEdges().size();
-- 
GitLab


From 468ba41b91b2fa1cb8ce3dedf0b680dbaece5f68 Mon Sep 17 00:00:00 2001
From: Romain BERNARD <30secondstodraw@gmail.com>
Date: Wed, 24 Jul 2024 13:00:21 +0200
Subject: [PATCH 170/327] allow Dijkstra expansion over arcs or matrix

---
 .../VehicleShortestPathCalculation.cpp        | 44 +++++++++++++++----
 .../Vehicle/VehicleShortestPathCalculation.h  |  8 +++-
 src/instance/graph/Edge.h                     |  7 +--
 3 files changed, 46 insertions(+), 13 deletions(-)

diff --git a/src/ShortestPath/Vehicle/VehicleShortestPathCalculation.cpp b/src/ShortestPath/Vehicle/VehicleShortestPathCalculation.cpp
index b0f4710..e27c6f6 100644
--- a/src/ShortestPath/Vehicle/VehicleShortestPathCalculation.cpp
+++ b/src/ShortestPath/Vehicle/VehicleShortestPathCalculation.cpp
@@ -7,7 +7,8 @@
 #include "VehiclePathState.h"
 #include "../../utils/Constants.h"
 
-std::vector<uint> VehicleShortestPathCalculation::computeShortestPathsFromNode(Graph& graph, size_t startingNodeIdx) {
+std::vector<uint>
+VehicleShortestPathCalculation::computeShortestPathsFromNode(Graph &graph, size_t startingNodeIdx, bool useEdges) {
     std::vector<uint> results{graph.getShortestSaevPaths()[startingNodeIdx]};
     std::vector<bool> mark(graph.getNbNodes(),false);
     std::priority_queue<VehiclePathState,std::vector<VehiclePathState>, std::greater<>> stateQueue{};
@@ -17,7 +18,6 @@ std::vector<uint> VehicleShortestPathCalculation::computeShortestPathsFromNode(G
         stateQueue.emplace(i, results[i]);
     }
 
-    uint newDistance = INT32_MAX;
     VehiclePathState currentState;
     while(!stateQueue.empty()) {
         currentState = stateQueue.top();
@@ -30,12 +30,10 @@ std::vector<uint> VehicleShortestPathCalculation::computeShortestPathsFromNode(G
             }
 
             //Iterate over all possible nodes, as the graph is complete in the case of a distance matrix
-            for(size_t i = 0; i < results.capacity(); ++i) { //FIXME:change iteration here to allow using edges
-                newDistance = currentState.getInstant() + graph.getShortestSAEVPath(currentState.getNodeIndex(), i);
-                if(newDistance < results[i]) {
-                    stateQueue.emplace(i, newDistance);
-                    results[i] = newDistance;
-                }
+            if (useEdges) {
+                expandStatesViaEdges(currentState, results, stateQueue, graph);
+            } else {
+                expandStatesViaMatrix(currentState, results, stateQueue, graph);
             }
         }
     }
@@ -48,7 +46,7 @@ MatrixShortestPathContainer VehicleShortestPathCalculation::computeShortestPaths
     results.resize(graph.getNbNodes());
     for(size_t i = 0; i < graph.getNbNodes(); ++i) {
         results[i].resize(graph.getNbNodes());
-        std::ranges::move(computeShortestPathsFromNode(graph, i), results[i].begin());
+        std::ranges::move(computeShortestPathsFromNode(graph, i, false), results[i].begin());
     }
 
     return MatrixShortestPathContainer(results);
@@ -70,3 +68,31 @@ VehicleShortestPathCalculation::getClosestPTNodesFromX(const Graph &graph, size_
     }
     return closestDestinationsContainer;
 }
+
+void VehicleShortestPathCalculation::expandStatesViaMatrix(const VehiclePathState& currentState, std::vector<uint> &results,
+                                                           std::priority_queue<VehiclePathState, std::vector<VehiclePathState>, std::greater<>> &stateQueue,
+                                                           const Graph& graph) {
+    uint newDistance = INT32_MAX;
+    for(size_t i = 0; i < results.capacity(); ++i) {
+        newDistance = currentState.getInstant() + graph.getShortestSAEVPath(currentState.getNodeIndex(), i);
+        if(newDistance < results[i]) {
+            stateQueue.emplace(i, newDistance);
+            results[i] = newDistance;
+        }
+    }
+}
+
+void VehicleShortestPathCalculation::expandStatesViaEdges(const VehiclePathState &currentState, std::vector<uint> &results,
+                                                          std::priority_queue<VehiclePathState, std::vector<VehiclePathState>, std::greater<>> &stateQueue,
+                                                          const Graph& graph) {
+    Edge edge;
+    uint newDistance = INT32_MAX;
+    for(const auto& edgeIndex : graph.getNode(currentState.getNodeIndex()).getOutgoingEdges()) {
+        edge = graph.getEdgesVector()[edgeIndex];
+        newDistance = currentState.getInstant() + edge.getLength();
+        if(newDistance < results[edge.getEndNodeIdx()]) {
+            stateQueue.emplace(edge.getEndNodeIdx(), newDistance);
+            results[edge.getEndNodeIdx()] = newDistance;
+        }
+    }
+}
diff --git a/src/ShortestPath/Vehicle/VehicleShortestPathCalculation.h b/src/ShortestPath/Vehicle/VehicleShortestPathCalculation.h
index 9fbfda8..c2ab0e9 100644
--- a/src/ShortestPath/Vehicle/VehicleShortestPathCalculation.h
+++ b/src/ShortestPath/Vehicle/VehicleShortestPathCalculation.h
@@ -9,6 +9,7 @@
 #include "MatrixShortestPathContainer.h"
 #include "../../instance/graph/Graph.h"
 #include "ClosestDestinationsContainer.h"
+#include "VehiclePathState.h"
 
 class VehicleShortestPathCalculation {
 public:
@@ -30,7 +31,7 @@ public:
      * @param startingNodeIdx
      * @return a vector indexed by all the nodes with the sortest path's duration from the starting node to the destination node index
      */
-    static std::vector<uint> computeShortestPathsFromNode(Graph& graph, size_t startingNodeIdx);
+    static std::vector<uint> computeShortestPathsFromNode(Graph &graph, size_t startingNodeIdx, bool useEdges);
     /**
      * Returns an ordered set of closest PT SAV-compatible nodes from a given starting node index.
      * Standard use case expects that the starting node index is a request origin
@@ -39,6 +40,11 @@ public:
      * @return An ordered set containing PT nodes accessible via SAV from the given starting node index
      */
     static ClosestDestinationsContainer getClosestPTNodesFromX(const Graph& graph, size_t startingNodeIdx);
+private:
+    static void expandStatesViaEdges(const VehiclePathState& currentState, std::vector<uint> &results,
+                                     std::priority_queue<VehiclePathState, std::vector<VehiclePathState>, std::greater<>> &stateQueue, const Graph& graph);
+    static void expandStatesViaMatrix(const VehiclePathState& currentState, std::vector<uint> &results,
+                                      std::priority_queue<VehiclePathState, std::vector<VehiclePathState>, std::greater<>> &stateQueue, const Graph& graph);
 };
 
 
diff --git a/src/instance/graph/Edge.h b/src/instance/graph/Edge.h
index 064c4a4..29d819a 100644
--- a/src/instance/graph/Edge.h
+++ b/src/instance/graph/Edge.h
@@ -10,9 +10,9 @@
 
 class Edge {
 private:
-    size_t _startNodeIdx;
-    size_t _endNodeIdx;
-    uint _length;
+    size_t _startNodeIdx{};
+    size_t _endNodeIdx{};
+    uint _length{};
 
 public:
     [[nodiscard]] size_t getStartNodeIdx() const;
@@ -24,6 +24,7 @@ public:
     [[nodiscard]] uint getLength() const;
     void setLength(uint length);
 
+    Edge() = default; //only used to reserve memory space for a variable in some instances
     Edge(size_t startNodeIdx, size_t endNodeIdx, uint length) : _startNodeIdx(startNodeIdx), _endNodeIdx(endNodeIdx), _length(length) {}
 };
 
-- 
GitLab


From e62fa2578f83892adfc9be1ac444820dd1aaa04c Mon Sep 17 00:00:00 2001
From: Romain BERNARD <romain.bernard@uca.fr>
Date: Wed, 24 Jul 2024 18:11:03 +0200
Subject: [PATCH 171/327] use an upper bound that doesn't risk warping back to
 start once converted to uint

---
 src/instance/graph/Graph.cpp | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/src/instance/graph/Graph.cpp b/src/instance/graph/Graph.cpp
index c05fc96..0f408d3 100644
--- a/src/instance/graph/Graph.cpp
+++ b/src/instance/graph/Graph.cpp
@@ -315,7 +315,7 @@ void Graph::parseDistanceMatrix(std::ifstream &infile, DATRow currentRow) {
         auto& matrixLine = shortestSAEVPaths.emplace_back();
         for(int i = 0; i < currentRow.size(); ++i) {
             std::from_chars(currentRow[i].data(), currentRow[i].data() + currentRow[i].size(), intVal);
-            matrixLine.emplace_back(intVal);
+            matrixLine.emplace_back(intVal < 0 ? INT16_MAX : intVal);
         }
     }
 }
-- 
GitLab


From 0d0b373ccb153667960b2dedca437339740de99a Mon Sep 17 00:00:00 2001
From: Romain BERNARD <romain.bernard@uca.fr>
Date: Wed, 24 Jul 2024 18:11:30 +0200
Subject: [PATCH 172/327] properly mark nodes during calculation

---
 src/ShortestPath/Vehicle/VehicleShortestPathCalculation.cpp | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/src/ShortestPath/Vehicle/VehicleShortestPathCalculation.cpp b/src/ShortestPath/Vehicle/VehicleShortestPathCalculation.cpp
index e27c6f6..26dffc2 100644
--- a/src/ShortestPath/Vehicle/VehicleShortestPathCalculation.cpp
+++ b/src/ShortestPath/Vehicle/VehicleShortestPathCalculation.cpp
@@ -24,6 +24,8 @@ VehicleShortestPathCalculation::computeShortestPathsFromNode(Graph &graph, size_
         stateQueue.pop();
         //Only expand and add
         if(!mark[currentState.getNodeIndex()]) {
+            mark[currentState.getNodeIndex()] = true;
+
             //Considering order of iteration is by shortest path to starting node, it's fair to add the current state node as a closest station
             if(graph.getNbPTLines(currentState.getNodeIndex()) > 0 && graph.getNbClosestStations(startingNodeIdx) < Constants::MAX_TRANSIT_ENTRY_CANDIDATES) {
                 graph.emplaceBackClosestStation(startingNodeIdx, currentState.getNodeIndex());
-- 
GitLab


From 7e188dfd65c351902b1bfe1b5970418b2ceb70e7 Mon Sep 17 00:00:00 2001
From: Romain BERNARD <romain.bernard@uca.fr>
Date: Wed, 24 Jul 2024 18:11:58 +0200
Subject: [PATCH 173/327] add graph preprocess example

---
 .../graph preprocess/book example/graph.dat   | 18 ++++++++++
 test/CMakeLists.txt                           | 36 ++++++++++++++++++-
 test/src/GraphPreprocessDebug.cpp             | 20 +++++++++++
 3 files changed, 73 insertions(+), 1 deletion(-)
 create mode 100644 resources/test/instances/graph preprocess/book example/graph.dat
 create mode 100644 test/src/GraphPreprocessDebug.cpp

diff --git a/resources/test/instances/graph preprocess/book example/graph.dat b/resources/test/instances/graph preprocess/book example/graph.dat
new file mode 100644
index 0000000..f12c12d
--- /dev/null
+++ b/resources/test/instances/graph preprocess/book example/graph.dat	
@@ -0,0 +1,18 @@
+#Params (seed)
+123456789
+#Nodes format : status (work, leisure, residential),x,y
+residential,0,0
+residential,0,1
+work,1,1
+work,2,0
+work,2,1
+#Matrix
+0,10,5,-1,-1
+-1,0,2,1,-1
+-1,3,0,-1,2
+-1,-1,-1,0,4
+7,-1,-1,6,0
+#PT line format : freq (min), start_time, end_time, node_1, ..., node_n
+15,340,560,1,2
+#Depot node index
+0
\ No newline at end of file
diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt
index f9fbc8b..b1a13fb 100644
--- a/test/CMakeLists.txt
+++ b/test/CMakeLists.txt
@@ -115,7 +115,41 @@ add_executable(BestInsertionHeuristic_DEB
         ../src/utils/Constants.h
 )
 
+add_executable(GraphPreprocess_DEB
+        src/GraphPreprocessDebug.cpp
+        ../src/TimeWindow.cpp
+        ../src/TimeWindow.h
+        ../src/instance/graph/Node.cpp
+        ../src/instance/graph/Node.h
+        ../src/instance/graph/Edge.cpp
+        ../src/instance/graph/Edge.h
+        ../src/instance/graph/Graph.cpp
+        ../src/instance/graph/Graph.h
+        ../src/instance/graph/Line.cpp
+        ../src/instance/graph/Line.h
+        ../src/instance/requests/Request.cpp
+        ../src/instance/requests/Request.h
+        ../src/routes/vehicle/SAEVRoute.cpp
+        ../src/routes/vehicle/SAEVRoute.h
+        ../src/routes/vehicle/propagation/SAEVRouteChange.cpp
+        ../src/routes/vehicle/propagation/SAEVRouteChange.h
+        ../src/routes/vehicle/propagation/SAEVRouteChangelist.cpp
+        ../src/routes/vehicle/propagation/SAEVRouteChangelist.h
+        ../src/routes/vehicle/SAEVKeyPoint.cpp
+        ../src/routes/vehicle/SAEVKeyPoint.h
+        ../src/routes/KeyPoint.cpp
+        ../src/routes/KeyPoint.h
+        ../src/routes/requests/RequestKeyPoint.cpp
+        ../src/routes/requests/RequestKeyPoint.h
+        ../src/routes/requests/RequestRoute.cpp
+        ../src/routes/requests/RequestRoute.h
+        ../src/ShortestPath/Vehicle/VehicleShortestPathCalculation.h
+        ../src/ShortestPath/Vehicle/VehicleShortestPathCalculation.cpp
+        ../src/utils/Constants.h
+)
+
 target_link_libraries(Line_UT gtest gtest_main)
 target_link_libraries(Transit_Preprocess_DEB gtest gtest_main)
 target_link_libraries(Constraint_Propag_DEB gtest gtest_main)
-target_link_libraries(BestInsertionHeuristic_DEB gtest gtest_main)
\ No newline at end of file
+target_link_libraries(BestInsertionHeuristic_DEB gtest gtest_main)
+target_link_libraries(GraphPreprocess_DEB gtest gtest_main)
\ No newline at end of file
diff --git a/test/src/GraphPreprocessDebug.cpp b/test/src/GraphPreprocessDebug.cpp
new file mode 100644
index 0000000..40870da
--- /dev/null
+++ b/test/src/GraphPreprocessDebug.cpp
@@ -0,0 +1,20 @@
+//
+// Created by romain on 24/07/24.
+//
+
+#include "../lib/googletest/googletest/include/gtest/gtest.h"
+#include "../../src/ShortestPath/Vehicle/VehicleShortestPathCalculation.h"
+
+
+TEST(GraphPreprocessDebug, DebugBookInstance) {
+    std::string instancesPath = "../../resources/test/instances/graph preprocess/";
+    std::string instanceFolder = "book example/";
+    std::string graphDatFile = "graph.dat";
+
+    //Parse graph
+    Graph graph(instancesPath + instanceFolder + graphDatFile);
+    VehicleShortestPathCalculation::computeAndUpdateShortestPathsForGraph(graph);
+
+    std::string exportFolder = "../../resources/test/outputs/preprocess_debug/";
+    graph.exportGraphToFile(exportFolder + instanceFolder);
+}
-- 
GitLab


From d0df9ccfa2942fff9a9bff34ca6851f91bb3b53a Mon Sep 17 00:00:00 2001
From: Romain BERNARD <romain.bernard@uca.fr>
Date: Wed, 24 Jul 2024 18:24:13 +0200
Subject: [PATCH 174/327] add max entry/exit candidates constants

---
 src/utils/Constants.h | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/src/utils/Constants.h b/src/utils/Constants.h
index 1778d8f..d164468 100644
--- a/src/utils/Constants.h
+++ b/src/utils/Constants.h
@@ -10,6 +10,8 @@ class Constants {
 public:
     static constexpr int VEHICLE_CAPACITY = 4;
     static constexpr int MAX_TRANSIT_CONNECTIONS = 2;
+    static constexpr int MAX_TRANSIT_ENTRY_CANDIDATES = 10;
+    static constexpr int MAX_TRANSIT_EXIT_CANDIDATES = 10;
 };
 
 
-- 
GitLab


From 28c35b321219f3cbb41d4ad0ed22b957804ca72d Mon Sep 17 00:00:00 2001
From: Romain BERNARD <30secondstodraw@gmail.com>
Date: Thu, 25 Jul 2024 13:07:21 +0200
Subject: [PATCH 175/327] Create TransitAccess class for transit entries/exits
 in our modular heuristic

---
 CMakeLists.txt                                |  1 +
 .../Multimodal/Heuristics/TransitAccess.h     | 39 +++++++++++++++++++
 2 files changed, 40 insertions(+)
 create mode 100644 src/algorithm/Multimodal/Heuristics/TransitAccess.h

diff --git a/CMakeLists.txt b/CMakeLists.txt
index 12c2ab3..3f4456a 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -63,6 +63,7 @@ add_executable(GreedyAlgorithm
         src/routes/vehicle/BestInsertionQueue.h
         src/utils/Constants.h
         src/utils/Globals.h
+        src/algorithm/Multimodal/Heuristics/TransitAccess.h
 )
 
 add_executable(RequestGenerator
diff --git a/src/algorithm/Multimodal/Heuristics/TransitAccess.h b/src/algorithm/Multimodal/Heuristics/TransitAccess.h
new file mode 100644
index 0000000..a1ec4f6
--- /dev/null
+++ b/src/algorithm/Multimodal/Heuristics/TransitAccess.h
@@ -0,0 +1,39 @@
+//
+// Created by Bebs on 24/07/2024.
+//
+
+#ifndef GREEDYALGORITHM_TRANSITACCESS_H
+#define GREEDYALGORITHM_TRANSITACCESS_H
+
+
+#include <cstddef>
+#include "../../../utils/Globals.h"
+
+class TransitAccess {
+    size_t _accessNodeIdx{};
+    uint _accessTimestamp{};
+
+public:
+    TransitAccess() = default;
+    TransitAccess(size_t accessNodeIdx, uint accessTimestamp) : _accessNodeIdx(accessNodeIdx),
+                                                                _accessTimestamp(accessTimestamp) {}
+
+    [[nodiscard]] size_t getAccessNodeIdx() const {
+        return _accessNodeIdx;
+    }
+
+    void setAccessNodeIdx(size_t accessNodeIdx) {
+        _accessNodeIdx = accessNodeIdx;
+    }
+
+    [[nodiscard]] uint getAccessTimestamp() const {
+        return _accessTimestamp;
+    }
+
+    void setAccessTimestamp(uint accessTimestamp) {
+        _accessTimestamp = accessTimestamp;
+    }
+};
+
+
+#endif //GREEDYALGORITHM_TRANSITACCESS_H
-- 
GitLab


From 8cec117a4383258d520932243734c8e53fd0a46b Mon Sep 17 00:00:00 2001
From: Romain BERNARD <30secondstodraw@gmail.com>
Date: Thu, 25 Jul 2024 13:07:50 +0200
Subject: [PATCH 176/327] Allow request construction from a given TransitAccess
 object

---
 src/instance/requests/Request.cpp | 26 +++++++++++++++++++++++++-
 src/instance/requests/Request.h   |  4 +++-
 2 files changed, 28 insertions(+), 2 deletions(-)

diff --git a/src/instance/requests/Request.cpp b/src/instance/requests/Request.cpp
index 02aaa80..c8b921d 100644
--- a/src/instance/requests/Request.cpp
+++ b/src/instance/requests/Request.cpp
@@ -197,9 +197,33 @@ void Request::resetKeyPoint(int routeIndex) {
     _currentRoute.resetKeyPoint(routeIndex);
 }
 
-std::string Request::to_string_export() {
+std::string Request::to_string_export() const {
     std::string res = std::to_string(_originNodeIndex) + "," + std::to_string(_destinationNodeIndex) //FIXME:replace with std::format whenever possible
             + "," + std::to_string(_arrivalTW.min) + "," + std::to_string(_arrivalTW.max)
             + "," + std::to_string(_deltaTime) + "," + std::to_string(_weight);
     return res;
 }
+
+Request::Request(const Graph& graph, const Request &baseRequest, const TransitAccess &access, bool isEntry) {
+    if(isEntry) {
+        _originNodeIndex = baseRequest.getOriginNodeIndex();
+        _destinationNodeIndex = access.getAccessNodeIdx();
+
+        _departureTW = baseRequest.getDepartureTw();
+
+        _arrivalTW.min = baseRequest.getDepartureTw().min + graph.getShortestSAEVPath(_originNodeIndex, access.getAccessNodeIdx());
+        _arrivalTW.max = access.getAccessTimestamp();
+    } else {
+        _originNodeIndex = access.getAccessNodeIdx();
+        _destinationNodeIndex = baseRequest.getDestinationNodeIndex();
+
+        _departureTW.min = access.getAccessTimestamp();
+        _departureTW.max =baseRequest.getArrivalTw().max - graph.getShortestSAEVPath(access.getAccessNodeIdx(), _destinationNodeIndex);
+
+        _arrivalTW.min = baseRequest.getArrivalTw().min;
+        _arrivalTW.max = _departureTW.min + _deltaTime; //Reduce max arrival TW to a value we are 100% sure is compatible with our current min departure time
+    }
+
+    _deltaTime = std::numeric_limits<uint>::max();
+    _weight = baseRequest.getWeight();
+}
diff --git a/src/instance/requests/Request.h b/src/instance/requests/Request.h
index d24cf79..06af51c 100644
--- a/src/instance/requests/Request.h
+++ b/src/instance/requests/Request.h
@@ -9,6 +9,7 @@
 #include "../../TimeWindow.h"
 #include "../../routes/requests/RequestRoute.h"
 #include "../graph/Graph.h"
+#include "../../algorithm/Multimodal/Heuristics/TransitAccess.h"
 
 class Request {
 private:
@@ -32,6 +33,7 @@ public:
             const uint deltaTime, const uint weight, const Graph& graph);
     Request(const DATRow& currentRow, const Graph& graph);
     Request(const DATRow& currentRow, double deltaRatio, const Graph& graph);
+    Request(const Graph& graph, const Request &baseRequest, const TransitAccess &access, bool isEntry)
 
     static std::vector<Request> getRequestsFromFile(const std::string& datFilePath, const Graph& graph);
 
@@ -82,7 +84,7 @@ public:
      * Format : origin_idx,destination_idx,min,max,delta,capacity
      * @return A properly formatted string to import back again
      */
-    std::string to_string_export();
+    std::string to_string_export() const;
 };
 
 
-- 
GitLab


From dcebb9df33f6fca5d267b7b853040ecd1a762666 Mon Sep 17 00:00:00 2001
From: Romain BERNARD <romain.bernard@uca.fr>
Date: Thu, 25 Jul 2024 14:47:01 +0200
Subject: [PATCH 177/327] use const &

---
 src/instance/graph/Node.cpp | 4 ++--
 src/instance/graph/Node.h   | 4 ++--
 2 files changed, 4 insertions(+), 4 deletions(-)

diff --git a/src/instance/graph/Node.cpp b/src/instance/graph/Node.cpp
index f11ba11..00d6905 100644
--- a/src/instance/graph/Node.cpp
+++ b/src/instance/graph/Node.cpp
@@ -39,7 +39,7 @@ bool Node::operator!=(const Node &rhs) const {
            || _status != rhs.getStatus();
 }
 
-Status  Node::statusFromString(std::string from) {
+Status  Node::statusFromString(const std::string& from) {
     auto pair = stringToStatusMap.find(from);
     if (pair != stringToStatusMap.end()) {
         return pair->second;
@@ -52,6 +52,6 @@ void Node::emplaceBackClosestStation(size_t closestStationIdx) {
     _closestStationsNodeIdxVector.emplace_back(closestStationIdx);
 }
 
-const std::vector<size_t> Node::getClosestStationsNodeIdxVector() {
+const std::vector<size_t> & Node::getClosestStationsNodeIdxVector() const {
     return _closestStationsNodeIdxVector;
 }
diff --git a/src/instance/graph/Node.h b/src/instance/graph/Node.h
index 3fc611d..ceacd80 100644
--- a/src/instance/graph/Node.h
+++ b/src/instance/graph/Node.h
@@ -64,7 +64,7 @@ public:
      * @param from String serving as basis for conversion (trailing spaces and capitalization don't matter)
      * @return A status depending on the given string. If no status corresponds to the given String, will default to Work
      */
-    static Status statusFromString(std::string from) ;
+    static Status statusFromString(const std::string& from) ;
     /**
      * Formats x and y data in a Coordinate object and returns it
      * @return A new Coordinate object with x and y data
@@ -92,7 +92,7 @@ public:
 
     void emplaceBackClosestStation(size_t closestStationIdx);
 
-    const std::vector<size_t> getClosestStationsNodeIdxVector();
+    [[nodiscard]] const std::vector<size_t>& getClosestStationsNodeIdxVector() const;
 };
 #include "Line.h"
 #include "LineStop.h"
-- 
GitLab


From eed9f288af9cb8963489981999003c864cca327a Mon Sep 17 00:00:00 2001
From: Romain BERNARD <romain.bernard@uca.fr>
Date: Thu, 25 Jul 2024 15:07:51 +0200
Subject: [PATCH 178/327] refactor vector search functions to have separate
 iterator and index versions available

---
 .../Transit/TransitShortestPathPrecompute.cpp       |  3 ++-
 src/instance/graph/Line.h                           | 11 ++++++++++-
 src/instance/graph/LineStop.h                       | 13 ++++++++++++-
 src/utils/SearchAlgorithms.h                        | 11 ++++++++++-
 4 files changed, 34 insertions(+), 4 deletions(-)

diff --git a/src/ShortestPath/Transit/TransitShortestPathPrecompute.cpp b/src/ShortestPath/Transit/TransitShortestPathPrecompute.cpp
index fbfaeb0..70d1208 100644
--- a/src/ShortestPath/Transit/TransitShortestPathPrecompute.cpp
+++ b/src/ShortestPath/Transit/TransitShortestPathPrecompute.cpp
@@ -42,7 +42,8 @@ TransitStateContainer TransitShortestPathPrecompute::executeAlgorithm(const Grap
                     if(currentState.isEmpty() || currentState.getLastConnectionLine() != lineStop.getLineRef()) // if new line is different than current line
                     {
                         if(currentState.canAddConnection()) {
-                            nextPassageIndex = lineStop.findNextScheduledPassage(lineStop.getStopIndex(), currentState.getInstant());
+                            nextPassageIndex = lineStop.findNextScheduledPassageIdx(lineStop.getStopIndex(),
+                                                                                    currentState.getInstant());
                             if (nextPassageIndex == lineStop.getLineRef().scheduleSize()) {
                                 newState.setNodeIndex(-1);
                             } else {
diff --git a/src/instance/graph/Line.h b/src/instance/graph/Line.h
index 2b8bbc9..4e19e28 100644
--- a/src/instance/graph/Line.h
+++ b/src/instance/graph/Line.h
@@ -38,9 +38,18 @@ public:
      * @param instant The instant of arrival at the station, hence we look for the value itself or the first greater instant
      * @return a vector index corresponding to the next valid passage at the given station and after or at the given instant
      */
-    [[nodiscard]] size_t findNextScheduledPassage(size_t stationIdx, uint instant) const {
+    [[nodiscard]] auto findNextScheduledPassage(size_t stationIdx, uint instant) const {
         return SearchAlgorithms<int>::findNextSortedValue(_timetables[stationIdx], instant);
     }
+    /**
+     * Searches for the next scheduled passage at a given station after a given instant O(log n)
+     * @param stationIdx The station number for which we want to search the schedule
+     * @param instant The instant of arrival at the station, hence we look for the value itself or the first greater instant
+     * @return a vector index corresponding to the next valid passage at the given station and after or at the given instant
+     */
+    [[nodiscard]] size_t findNextScheduledPassageIdx(size_t stationIdx, uint instant) const {
+        return SearchAlgorithms<int>::findNextSortedValueIdx(_timetables[stationIdx], instant);
+    }
     /**
      * Returns the instant for the given station at a given schedule position, O(1)
      * @param stationIdx The station number for which we want to search the schedule
diff --git a/src/instance/graph/LineStop.h b/src/instance/graph/LineStop.h
index 3669ef1..d213f71 100644
--- a/src/instance/graph/LineStop.h
+++ b/src/instance/graph/LineStop.h
@@ -24,7 +24,18 @@ public:
     }
 
     [[nodiscard]] int getInstant(int stationIdx, int scheduleIdx) const { return _lineRef.getInstant(stationIdx, scheduleIdx); }
-    [[nodiscard]] int findNextScheduledPassage(int stationIdx, int instant) const { return _lineRef.findNextScheduledPassage(stationIdx, instant); }
+    [[nodiscard]] size_t findNextScheduledPassageIdx(uint instant) const {
+        return _lineRef.findNextScheduledPassageIdx(_stopIndex, instant);
+    }
+    [[nodiscard]] size_t findNextScheduledPassageIdx(size_t stationIdx, uint instant) const {
+        return _lineRef.findNextScheduledPassageIdx(stationIdx, instant);
+    }
+    [[nodiscard]] auto findNextScheduledPassage(uint instant) const {
+        return _lineRef.findNextScheduledPassage(_stopIndex, instant);
+    }
+    [[nodiscard]] auto findNextScheduledPassage(size_t stationIdx, uint instant) const {
+        return _lineRef.findNextScheduledPassage(stationIdx, instant);
+    }
 
     [[nodiscard]] size_t getNodeIndex() const
     {
diff --git a/src/utils/SearchAlgorithms.h b/src/utils/SearchAlgorithms.h
index cd987ee..239ee0e 100644
--- a/src/utils/SearchAlgorithms.h
+++ b/src/utils/SearchAlgorithms.h
@@ -12,13 +12,22 @@
 template <typename Comparable>
 class SearchAlgorithms {
 public:
+    /**
+     * Returns an iterator to the first item higher or equal than the comparable value given
+     * @param sortedVector a sorted vector in which to search for a value. If the vector isn't sorted, there is no guarantee that we return the appropriate index or that performance is O(log n)
+     * @param value the comparable value we are looking for in the vector
+     * @return an iterator to the first item higher or equal than the comparable value given
+     */
+    static std::vector<Comparable>::iterator findNextSortedValue(std::vector<Comparable> sortedVector, Comparable value) {
+        return std::ranges::lower_bound(sortedVector, value);
+    }
     /**
      * Returns the first index corresponding exactly to the given value in the
      * @param sortedVector a sorted vector in which to search for a value. If the vector isn't sorted, there is no guarantee that we return the appropriate index or that performance is O(log n)
      * @param value the comparable value we are looking for in the vector
      * @return the size of the vector if all vector values are lower than our search, the index of the first larger or equal value otherwise
      */
-    static size_t findNextSortedValue(std::vector<Comparable> sortedVector, Comparable value) {
+    static size_t findNextSortedValueIdx(std::vector<Comparable> sortedVector, Comparable value) {
         auto iterator = std::ranges::lower_bound(sortedVector, value);
         return std::distance(sortedVector.begin(), iterator);
     }
-- 
GitLab


From 224189ca6a5f65443a2d244bafc40c0adc01e53b Mon Sep 17 00:00:00 2001
From: Romain BERNARD <romain.bernard@uca.fr>
Date: Thu, 25 Jul 2024 15:10:46 +0200
Subject: [PATCH 179/327] refactors for const correctness and code clarity

---
 src/instance/graph/Graph.cpp | 2 +-
 src/instance/graph/Line.h    | 2 +-
 src/instance/graph/Node.cpp  | 8 ++++----
 src/instance/graph/Node.h    | 6 +++---
 4 files changed, 9 insertions(+), 9 deletions(-)

diff --git a/src/instance/graph/Graph.cpp b/src/instance/graph/Graph.cpp
index 0f408d3..a705d4a 100644
--- a/src/instance/graph/Graph.cpp
+++ b/src/instance/graph/Graph.cpp
@@ -341,5 +341,5 @@ void Graph::emplaceBackClosestStation(size_t nodeIdx, size_t stationNodeIdx) {
 }
 
 const size_t Graph::getNbClosestStations(size_t nodeIdx) {
-    return nodesVector[nodeIdx].getClosestStationsNodeIdxVector().size();
+    return nodesVector[nodeIdx].getBestStationsNodeIdxVector().size();
 }
diff --git a/src/instance/graph/Line.h b/src/instance/graph/Line.h
index 4e19e28..8174ed2 100644
--- a/src/instance/graph/Line.h
+++ b/src/instance/graph/Line.h
@@ -27,7 +27,7 @@ public:
     void addNode(const int node){this->_nodes.emplace_back(node);};
     [[nodiscard]] bool isEmpty() const{return this->_nodes.empty() || _timetables.empty();}
 
-    [[nodiscard]] std::vector<int> getTimetable(size_t pos) const{ return _timetables[pos];};
+    [[nodiscard]] const std::vector<int>& getTimetable(size_t pos) const{ return _timetables[pos];};
     [[nodiscard]] std::vector<std::vector<int>> getTimetables() const{ return _timetables;};
     void addTimetable(const std::vector<int>& timetable) { _timetables.push_back(timetable);};
     void setTimetable(size_t pos, const std::vector<int>& timetable) { _timetables.insert(_timetables.begin() + pos, timetable);};
diff --git a/src/instance/graph/Node.cpp b/src/instance/graph/Node.cpp
index 00d6905..b31ab04 100644
--- a/src/instance/graph/Node.cpp
+++ b/src/instance/graph/Node.cpp
@@ -13,7 +13,7 @@ Node::Node() {
     _y = -1;
 }
 
-bool Node::isPTNode() {
+bool Node::isPTNode() const {
     return &_ptLines == nullptr || _ptLines.empty();
 }
 
@@ -49,9 +49,9 @@ Status  Node::statusFromString(const std::string& from) {
 }
 
 void Node::emplaceBackClosestStation(size_t closestStationIdx) {
-    _closestStationsNodeIdxVector.emplace_back(closestStationIdx);
+    _bestStationsNodeIdxVector.emplace_back(closestStationIdx);
 }
 
-const std::vector<size_t> & Node::getClosestStationsNodeIdxVector() const {
-    return _closestStationsNodeIdxVector;
+const std::vector<size_t> & Node::getBestStationsNodeIdxVector() const {
+    return _bestStationsNodeIdxVector;
 }
diff --git a/src/instance/graph/Node.h b/src/instance/graph/Node.h
index ceacd80..7861acf 100644
--- a/src/instance/graph/Node.h
+++ b/src/instance/graph/Node.h
@@ -35,7 +35,7 @@ private:
     std::vector<LineStop> _ptLines;
     std::vector<int> _incomingEdgesIndex; //List of edge index in the graph structure for all edges leading to this node
     std::vector<int> _outgoingEdgesIndex; //List of edge index in the graph structure for all edges leading to this node
-    std::vector<size_t> _closestStationsNodeIdxVector;
+    std::vector<size_t> _bestStationsNodeIdxVector;
     //TODO : Should these vectors be considered complete over the whole set of nodes ? Probably ? Considering we will probably pre-process shortest paths between all SAEV stations
 
 public:
@@ -52,7 +52,7 @@ public:
     /**
      * @return True if this node contains one or more LineStop
      */
-    bool isPTNode();
+    bool isPTNode() const;
     /**
      * Adds a new LineStop to the LineStop set
      * @param line the line referenced by the LineStop
@@ -92,7 +92,7 @@ public:
 
     void emplaceBackClosestStation(size_t closestStationIdx);
 
-    [[nodiscard]] const std::vector<size_t>& getClosestStationsNodeIdxVector() const;
+    [[nodiscard]] const std::vector<size_t>& getBestStationsNodeIdxVector() const;
 };
 #include "Line.h"
 #include "LineStop.h"
-- 
GitLab


From 59a0d8d1cfdf1156229ba17480af0d2c8ee66144 Mon Sep 17 00:00:00 2001
From: Romain BERNARD <romain.bernard@uca.fr>
Date: Thu, 25 Jul 2024 17:17:14 +0200
Subject: [PATCH 180/327] use more precise typing for our constants

---
 src/utils/Constants.h | 8 ++++----
 1 file changed, 4 insertions(+), 4 deletions(-)

diff --git a/src/utils/Constants.h b/src/utils/Constants.h
index d164468..6e97b58 100644
--- a/src/utils/Constants.h
+++ b/src/utils/Constants.h
@@ -8,10 +8,10 @@
 
 class Constants {
 public:
-    static constexpr int VEHICLE_CAPACITY = 4;
-    static constexpr int MAX_TRANSIT_CONNECTIONS = 2;
-    static constexpr int MAX_TRANSIT_ENTRY_CANDIDATES = 10;
-    static constexpr int MAX_TRANSIT_EXIT_CANDIDATES = 10;
+    static constexpr uint VEHICLE_CAPACITY = 4;
+    static constexpr uint MAX_TRANSIT_CONNECTIONS = 2;
+    static constexpr size_t MAX_TRANSIT_ENTRY_CANDIDATES = 10;
+    static constexpr size_t MAX_TRANSIT_EXIT_CANDIDATES = 10;
 };
 
 
-- 
GitLab


From ccfb0f9c47bc49f0ed574b560693a1a50e9eeab5 Mon Sep 17 00:00:00 2001
From: Romain BERNARD <romain.bernard@uca.fr>
Date: Thu, 25 Jul 2024 17:18:22 +0200
Subject: [PATCH 181/327] add getSchedule to the lineStop API to directly get
 this stop's schedule via its line and stop index

---
 src/instance/graph/LineStop.h | 4 ++++
 1 file changed, 4 insertions(+)

diff --git a/src/instance/graph/LineStop.h b/src/instance/graph/LineStop.h
index d213f71..1c0eed2 100644
--- a/src/instance/graph/LineStop.h
+++ b/src/instance/graph/LineStop.h
@@ -83,6 +83,10 @@ public:
         _stopIndex = rhs.getStopIndex();
         return *this;
     }
+
+    [[nodiscard]] const std::vector<int>& getSchedule() const {
+        return _lineRef.getTimetable(_stopIndex);
+    }
 };
 
 
-- 
GitLab


From f8cbe62a838a2d96ffd3cb475acf9a9bc3d411e5 Mon Sep 17 00:00:00 2001
From: Romain BERNARD <romain.bernard@uca.fr>
Date: Thu, 25 Jul 2024 17:19:23 +0200
Subject: [PATCH 182/327] init SimpleModularHeuristic with the API to get best
 transit entries (TODO: lotsa testing)

---
 CMakeLists.txt                                | 14 +++--
 .../Heuristics/SimpleModularHeuristic.cpp     | 32 ++++++++++
 .../Heuristics/SimpleModularHeuristic.h       | 60 +++++++++++++++++++
 3 files changed, 102 insertions(+), 4 deletions(-)
 create mode 100644 src/algorithm/Multimodal/Heuristics/SimpleModularHeuristic.cpp
 create mode 100644 src/algorithm/Multimodal/Heuristics/SimpleModularHeuristic.h

diff --git a/CMakeLists.txt b/CMakeLists.txt
index 3f4456a..fee3d65 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -63,6 +63,8 @@ add_executable(GreedyAlgorithm
         src/routes/vehicle/BestInsertionQueue.h
         src/utils/Constants.h
         src/utils/Globals.h
+        src/algorithm/Multimodal/Heuristics/SimpleModularHeuristic.h
+        src/algorithm/Multimodal/Heuristics/SimpleModularHeuristic.cpp
         src/algorithm/Multimodal/Heuristics/TransitAccess.h
 )
 
@@ -93,8 +95,8 @@ add_executable(RequestGenerator
         "src/utils/Instance Generation/Requests/RequestGenerationParameters.h"
         "src/utils/Instance Generation/Graph/OSRMGraphGenerator.h"
         src/utils/Globals.h
-#        src/algorithm/Multimodal/Heuristics/SimpleModularHeuristic.cpp
-#        src/algorithm/Multimodal/Heuristics/SimpleModularHeuristic.h
+        src/algorithm/Multimodal/Heuristics/SimpleModularHeuristic.cpp
+        src/algorithm/Multimodal/Heuristics/SimpleModularHeuristic.h
         src/ShortestPath/Vehicle/VehicleShortestPath.h
         src/ShortestPath/Vehicle/VehiclePathState.h
         src/ShortestPath/Vehicle/VehicleShortestPathCalculation.cpp
@@ -125,15 +127,19 @@ add_executable(GraphGeneration
         "src/utils/Instance Generation/Graph/PTLineGenerationParameters.h"
         src/algorithm/DARP/Heuristics/BestInsertionHeuristic.cpp
         src/algorithm/DARP/Heuristics/BestInsertionHeuristic.h
-#        src/algorithm/Multimodal/Heuristics/SimpleModularHeuristic.cpp
-#        src/algorithm/Multimodal/Heuristics/SimpleModularHeuristic.h
+        src/algorithm/Multimodal/Heuristics/SimpleModularHeuristic.cpp
+        src/algorithm/Multimodal/Heuristics/SimpleModularHeuristic.h
         src/ShortestPath/Vehicle/VehicleShortestPath.h
         src/ShortestPath/Vehicle/VehiclePathState.h
         src/ShortestPath/Vehicle/VehicleShortestPathCalculation.cpp
         src/ShortestPath/Vehicle/VehicleShortestPathCalculation.h
         src/ShortestPath/Vehicle/MatrixShortestPathContainer.h
+        src/algorithm/Multimodal/Heuristics/TransitAccess.h
 )
 
 target_include_directories(GreedyAlgorithm PRIVATE ${PYTHON_INCLUDE_DIRS})
 target_link_libraries(GreedyAlgorithm ${PYTHON_LIBRARIES})
 
+add_executable(ModularHeuristic_DEB
+        src/algorithm/Multimodal/Heuristics/SimpleModularHeuristic.h
+        src/algorithm/Multimodal/Heuristics/SimpleModularHeuristic.cpp)
diff --git a/src/algorithm/Multimodal/Heuristics/SimpleModularHeuristic.cpp b/src/algorithm/Multimodal/Heuristics/SimpleModularHeuristic.cpp
new file mode 100644
index 0000000..b0f6eee
--- /dev/null
+++ b/src/algorithm/Multimodal/Heuristics/SimpleModularHeuristic.cpp
@@ -0,0 +1,32 @@
+//
+// Created by romain on 15/07/24.
+//
+
+#include "SimpleModularHeuristic.h"
+
+std::vector<TransitAccess> SimpleModularHeuristic::getBestTransitEntriesList(const Request &baseRequest) {
+    const auto& bestStationsIndexVector = _graph->getNode(
+            baseRequest.getOriginNodeIndex()).getBestStationsNodeIdxVector();
+    std::vector<TransitAccess> results{bestStationsIndexVector.size()}; //init results vector to the appropriate size
+    //Iterate over the best stations saved prior
+    for(const auto& bestStationNodeIdx : bestStationsIndexVector) {
+        int maxDepartureTime = -1;
+
+        //Iterate over the lines available on the node selected
+        for(const Node& bestStationNode = _graph->getNode(bestStationNodeIdx);
+            const auto& lineStop : bestStationNode.getPTLinesSet()) {
+            //Find the next passage lower or equal to our max entry time constraint
+            auto iterator = lineStop.findNextScheduledPassage(getMaxEntryConstraint(baseRequest, bestStationNodeIdx))--;
+            if(iterator != lineStop.getSchedule().end() && *iterator > maxDepartureTime //If we've found a valid time that's superior to our current max time
+            && *iterator > getMinEntryConstraint(baseRequest, bestStationNodeIdx)) { //and respects min entry time, replace old value
+                maxDepartureTime = *iterator;
+            }
+        }
+
+        //If we've found a valid max departure time for this station, add it to the list
+        if(maxDepartureTime > -1) {
+            results.emplace_back(bestStationNodeIdx, maxDepartureTime);
+        }
+    }
+    return results;
+}
diff --git a/src/algorithm/Multimodal/Heuristics/SimpleModularHeuristic.h b/src/algorithm/Multimodal/Heuristics/SimpleModularHeuristic.h
new file mode 100644
index 0000000..6388cab
--- /dev/null
+++ b/src/algorithm/Multimodal/Heuristics/SimpleModularHeuristic.h
@@ -0,0 +1,60 @@
+//
+// Created by romain on 15/07/24.
+//
+
+#ifndef GREEDYALGORITHM_SIMPLEMODULARHEURISTIC_H
+#define GREEDYALGORITHM_SIMPLEMODULARHEURISTIC_H
+
+
+#include <cstddef>
+#include <vector>
+#include "../../../instance/requests/Request.h"
+#include "../../../routes/vehicle/SAEVRoute.h"
+#include "TransitAccess.h"
+
+class SimpleModularHeuristic {
+    const Graph* _graph{nullptr};
+    SAEVRoute* _route{nullptr};
+
+    //Best candidates function
+    /**
+     * Creates and returns a vector of TransitAccess objects representing possible
+     * transit entries that can be converted to Request objects to try and insert them
+     * in a vehicle. <br>
+     * <br>
+     * This vector is sorted in the same way as Node._bestStationsNodeIdxVector and has max size
+     * Constants::MAX_TRANSIT_ENTRY_CANDIDATES. There can be less or even 0 elements if no candidate
+     * has a transit departure tmax in getMinEntryConstraint <= tmax <= getMaxEntryConstraint
+     *
+     * @param baseRequest the request we wish to find potential transit entries for
+     * @return A vector consisting of all valid TransitAccess objects wrt the base request
+     * and the min/max exit constraints. If no valid access is found, we return an empty vector.
+     */
+    std::vector<TransitAccess> getBestTransitEntriesList(const Request &baseRequest);
+
+    /**
+     * Creates and returns a vector of TransitAccess objects representing possible
+     * transit entries that can be converted to Request objects to try and insert them
+     * in a vehicle. <br>
+     * <br>
+     * This vector is sorted according to the sort function the class was initialized with
+     * (default = t' + T(y,Dr)) and has max size Constants::MAX_TRANSIT_EXIT_CANDIDATES.
+     * There can be less, or even 0 elements if no candidate has a transit departure tmax in
+     * getMinEntryConstraint <= tmax <= getMaxEntryConstraint
+     *
+     * @param transitEntryRequest the transit entry sub-request we wish to find potential exits from
+     * @return A vector consisting of all valid TransitAccess objects wrt the entry request's state
+     * and the min/max entry constraints. If no valid access is found, we return an empty vector.
+     */
+     std::vector<TransitAccess> getBestTransitExitsList(Request transitEntryRequest);
+
+    //Entry filter
+    uint getMinEntryConstraint(Request request, size_t node);
+    uint getMaxEntryConstraint(Request request, size_t node);
+    //Exit filter
+    uint getMinExitConstraint(Request request, size_t node);
+    uint getMaxExitConstraint(Request request, size_t node);
+};
+
+
+#endif //GREEDYALGORITHM_SIMPLEMODULARHEURISTIC_H
-- 
GitLab


From 0a858235b7ff8293486c7070b0aeba5a2dc57e5b Mon Sep 17 00:00:00 2001
From: Romain BERNARD <30secondstodraw@gmail.com>
Date: Fri, 26 Jul 2024 12:29:19 +0200
Subject: [PATCH 183/327] typo

---
 src/instance/requests/Request.h | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/src/instance/requests/Request.h b/src/instance/requests/Request.h
index 06af51c..d884aba 100644
--- a/src/instance/requests/Request.h
+++ b/src/instance/requests/Request.h
@@ -33,7 +33,7 @@ public:
             const uint deltaTime, const uint weight, const Graph& graph);
     Request(const DATRow& currentRow, const Graph& graph);
     Request(const DATRow& currentRow, double deltaRatio, const Graph& graph);
-    Request(const Graph& graph, const Request &baseRequest, const TransitAccess &access, bool isEntry)
+    Request(const Graph& graph, const Request &baseRequest, const TransitAccess &access, bool isEntry);
 
     static std::vector<Request> getRequestsFromFile(const std::string& datFilePath, const Graph& graph);
 
-- 
GitLab


From 863323e99c3f1bc6af599661f8b17e77081782e8 Mon Sep 17 00:00:00 2001
From: Romain BERNARD <30secondstodraw@gmail.com>
Date: Fri, 26 Jul 2024 13:44:52 +0200
Subject: [PATCH 184/327] add globals for windows build

---
 src/ShortestPath/Vehicle/MatrixShortestPathContainer.h | 1 +
 1 file changed, 1 insertion(+)

diff --git a/src/ShortestPath/Vehicle/MatrixShortestPathContainer.h b/src/ShortestPath/Vehicle/MatrixShortestPathContainer.h
index 704c724..740102e 100644
--- a/src/ShortestPath/Vehicle/MatrixShortestPathContainer.h
+++ b/src/ShortestPath/Vehicle/MatrixShortestPathContainer.h
@@ -9,6 +9,7 @@
 #include <vector>
 #include <cstdint>
 #include <algorithm>
+#include "../../utils/Globals.h"
 
 class MatrixShortestPathContainer {
 private:
-- 
GitLab


From 28d04b36d2a0ec0784aea092b0ac14f3c6e37509 Mon Sep 17 00:00:00 2001
From: Romain BERNARD <30secondstodraw@gmail.com>
Date: Fri, 26 Jul 2024 13:45:17 +0200
Subject: [PATCH 185/327] use the appropriate delta time to set exit
 sub-request arrival TW

---
 src/instance/requests/Request.cpp | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/src/instance/requests/Request.cpp b/src/instance/requests/Request.cpp
index c8b921d..80b6fe5 100644
--- a/src/instance/requests/Request.cpp
+++ b/src/instance/requests/Request.cpp
@@ -218,10 +218,10 @@ Request::Request(const Graph& graph, const Request &baseRequest, const TransitAc
         _destinationNodeIndex = baseRequest.getDestinationNodeIndex();
 
         _departureTW.min = access.getAccessTimestamp();
-        _departureTW.max =baseRequest.getArrivalTw().max - graph.getShortestSAEVPath(access.getAccessNodeIdx(), _destinationNodeIndex);
+        _departureTW.max = baseRequest.getArrivalTw().max - graph.getShortestSAEVPath(access.getAccessNodeIdx(), _destinationNodeIndex);
 
         _arrivalTW.min = baseRequest.getArrivalTw().min;
-        _arrivalTW.max = _departureTW.min + _deltaTime; //Reduce max arrival TW to a value we are 100% sure is compatible with our current min departure time
+        _arrivalTW.max = _departureTW.min + baseRequest.getDeltaTime(); //Reduce max arrival TW to a value we are 100% sure is compatible with our current min departure time
     }
 
     _deltaTime = std::numeric_limits<uint>::max();
-- 
GitLab


From 81900f3d4e752b5fec77cf96f58fb39c1dcb313b Mon Sep 17 00:00:00 2001
From: Romain BERNARD <romain.bernard@uca.fr>
Date: Fri, 26 Jul 2024 16:18:06 +0200
Subject: [PATCH 186/327] type correctness refactors + small sonar issues

---
 src/instance/requests/Request.cpp | 14 +++++++-------
 src/instance/requests/Request.h   | 13 +++++++------
 2 files changed, 14 insertions(+), 13 deletions(-)

diff --git a/src/instance/requests/Request.cpp b/src/instance/requests/Request.cpp
index 80b6fe5..032c504 100644
--- a/src/instance/requests/Request.cpp
+++ b/src/instance/requests/Request.cpp
@@ -9,14 +9,14 @@
 Request::Request(const size_t departureNodeIndex, const size_t arrivalNodeIndex, const TimeWindow &arrivalTw,
                  const uint deltaTime, const uint weight) : _originNodeIndex(departureNodeIndex),
                                                             _destinationNodeIndex(arrivalNodeIndex), _arrivalTW(arrivalTw),
-                                                            _deltaTime(deltaTime), _currentDeltaTime(deltaTime), _weight(weight) {
+                                                            _deltaTime(deltaTime), _weight(weight), _currentDeltaTime(deltaTime) {
     _departureTW = _arrivalTW - deltaTime;
 }
 
 Request::Request(const size_t departureNodeIndex, const size_t arrivalNodeIndex, const TimeWindow &arrivalTw,
                  const uint deltaTime, const uint weight, const Graph& graph) :
         _originNodeIndex(departureNodeIndex), _destinationNodeIndex(arrivalNodeIndex),
-        _arrivalTW(arrivalTw), _deltaTime(deltaTime), _currentDeltaTime(deltaTime), _weight(weight) {
+        _arrivalTW(arrivalTw), _deltaTime(deltaTime), _weight(weight), _currentDeltaTime(deltaTime) {
     _departureTW.min = _arrivalTW.min - deltaTime;
     _departureTW.max = _arrivalTW.max - graph.getShortestSAEVPath(departureNodeIndex, arrivalNodeIndex);
 }
@@ -95,23 +95,23 @@ const TimeWindow &Request::getArrivalTw() const {
     return _arrivalTW;
 }
 
-int Request::getDeltaTime() const {
+uint Request::getDeltaTime() const {
     return _deltaTime;
 }
 
-int Request::getWeight() const {
+uint Request::getWeight() const {
     return _weight;
 }
 
-int Request::getCurrentDeltaTime() const {
+uint Request::getCurrentDeltaTime() const {
     return _currentDeltaTime;
 }
 
-int Request::getRequestServiceStart() const {
+uint Request::getRequestServiceStart() const {
     return _requestServiceStart;
 }
 
-int Request::getRequestServiceEnd() const {
+uint Request::getRequestServiceEnd() const {
     return _requestServiceEnd;
 }
 
diff --git a/src/instance/requests/Request.h b/src/instance/requests/Request.h
index d884aba..0ea951f 100644
--- a/src/instance/requests/Request.h
+++ b/src/instance/requests/Request.h
@@ -16,6 +16,7 @@ private:
     //Request base members (const and initialized on _request creation)
     size_t _originNodeIndex; //Starting point of the user _request //TODO (?) change this to a Node pointer eventually
     size_t _destinationNodeIndex; //
+    TimeWindow _departureTW;
     TimeWindow _arrivalTW; //[min,max] time window for arrival to the destination node
     uint _deltaTime; //Base delta time, aka the maximum total duration of the path to serve this _request
     uint _weight; //How much space the requests takes in the vehicle (defaults to 1)
@@ -41,11 +42,11 @@ public:
     [[nodiscard]] size_t getOriginNodeIndex() const;
     [[nodiscard]] size_t getDestinationNodeIndex() const;
     [[nodiscard]] const TimeWindow &getArrivalTw() const;
-    [[nodiscard]] int getDeltaTime() const;
-    [[nodiscard]] int getWeight() const;
-    [[nodiscard]] int getCurrentDeltaTime() const;
-    [[nodiscard]] int getRequestServiceStart() const;
-    [[nodiscard]] int getRequestServiceEnd() const;
+    [[nodiscard]] uint getDeltaTime() const;
+    [[nodiscard]] uint getWeight() const;
+    [[nodiscard]] uint getCurrentDeltaTime() const;
+    [[nodiscard]] uint getRequestServiceStart() const;
+    [[nodiscard]] uint getRequestServiceEnd() const;
     [[nodiscard]] const RequestRoute &getCurrentRoute() const;
     [[nodiscard]] const TimeWindow &getDepartureTw() const;
     [[nodiscard]] uint getMinDepartureTw() const;
@@ -84,7 +85,7 @@ public:
      * Format : origin_idx,destination_idx,min,max,delta,capacity
      * @return A properly formatted string to import back again
      */
-    std::string to_string_export() const;
+    [[nodiscard]] std::string to_string_export() const;
 };
 
 
-- 
GitLab


From 27f0941b92ded573dc613fcdc90ef6ec27b56723 Mon Sep 17 00:00:00 2001
From: Romain BERNARD <romain.bernard@uca.fr>
Date: Fri, 26 Jul 2024 16:19:15 +0200
Subject: [PATCH 187/327] documentation

---
 src/instance/requests/Request.h | 11 +++++++++++
 1 file changed, 11 insertions(+)

diff --git a/src/instance/requests/Request.h b/src/instance/requests/Request.h
index 0ea951f..da2f1d1 100644
--- a/src/instance/requests/Request.h
+++ b/src/instance/requests/Request.h
@@ -23,8 +23,19 @@ private:
 
     //Request helpful members (used for constraint propagation and remember the current state of the _request)
     uint _currentDeltaTime; //deltaTime - currentRouteDuration
+    /**
+     * Store the timestamp when this request effectively starts its route here once we planified its route in detail
+     */
     uint _requestServiceStart;
+    /**
+     * Store the timestamp when this request effectively ends its route here once we planified its route in detail
+     */
     uint _requestServiceEnd;
+    /**
+     * This object divides our request's route in four key points for each step in the user's path:<br>
+     * SAEV departure -> Transit entrance -> Transit exit -> SAEV end <br>
+     * Through this object, we'll save the request's path during resolution
+     */
     RequestRoute _currentRoute{this};
     TimeWindow _departureTW; //For now, a virtual TW on departures, used for constraint propagation
 public:
-- 
GitLab


From b971fe6f9732bc9c3c8de5d8f3873d07b3dcfc09 Mon Sep 17 00:00:00 2001
From: Romain BERNARD <romain.bernard@uca.fr>
Date: Fri, 26 Jul 2024 16:33:14 +0200
Subject: [PATCH 188/327] add transit travel time ratio to Requests to estimate
 possible transit duration

---
 src/instance/requests/Request.cpp | 25 ++++++++++++++++++++++++-
 src/instance/requests/Request.h   | 13 ++++++++++++-
 src/utils/Constants.h             | 12 ++++++++++++
 3 files changed, 48 insertions(+), 2 deletions(-)

diff --git a/src/instance/requests/Request.cpp b/src/instance/requests/Request.cpp
index 032c504..4c98afd 100644
--- a/src/instance/requests/Request.cpp
+++ b/src/instance/requests/Request.cpp
@@ -223,7 +223,30 @@ Request::Request(const Graph& graph, const Request &baseRequest, const TransitAc
         _arrivalTW.min = baseRequest.getArrivalTw().min;
         _arrivalTW.max = _departureTW.min + baseRequest.getDeltaTime(); //Reduce max arrival TW to a value we are 100% sure is compatible with our current min departure time
     }
-
+    _transitTravelTimeRatio = baseRequest.getTransitTravelTimeRatio();
     _deltaTime = std::numeric_limits<uint>::max();
     _weight = baseRequest.getWeight();
 }
+
+double Request::getTransitTravelTimeRatio() const {
+    return _transitTravelTimeRatio;
+}
+
+void Request::setTransitTravelTimeRatio(double transitTravelTimeRatio) {
+    _transitTravelTimeRatio = transitTravelTimeRatio;
+}
+
+double Request::computeTransitTravelTimeRatio(double deltaRatio, double travelTimeRatio) {
+    double computedRatio = (1.0 + (travelTimeRatio * (1.0 - deltaRatio)));
+    if(computedRatio < 1)
+        return 1;
+    else if(computedRatio > deltaRatio)
+        return deltaRatio;
+    else
+        return computedRatio;
+}
+
+double Request::computeTransitTravelTimeRatio(const Graph &graph, double travelTimeRatio) const {
+    double deltaRatio = (graph.getShortestSAEVPath(_originNodeIndex, _destinationNodeIndex))/(double)_deltaTime;
+    return computeTransitTravelTimeRatio(deltaRatio, travelTimeRatio);
+}
diff --git a/src/instance/requests/Request.h b/src/instance/requests/Request.h
index da2f1d1..51db4fd 100644
--- a/src/instance/requests/Request.h
+++ b/src/instance/requests/Request.h
@@ -10,6 +10,7 @@
 #include "../../routes/requests/RequestRoute.h"
 #include "../graph/Graph.h"
 #include "../../algorithm/Multimodal/Heuristics/TransitAccess.h"
+#include "../../utils/Constants.h"
 
 class Request {
 private:
@@ -37,7 +38,10 @@ private:
      * Through this object, we'll save the request's path during resolution
      */
     RequestRoute _currentRoute{this};
-    TimeWindow _departureTW; //For now, a virtual TW on departures, used for constraint propagation
+    /**
+     * A ratio by which to multiply the direct vehicle path to guesstimate an upper bound on transit travel time
+     */
+    double _transitTravelTimeRatio{Constants::BASE_TRANSIT_TRAVEL_TIME_RATIO};
 public:
     Request(const size_t departureNodeIndex, const size_t arrivalNodeIndex,
             const TimeWindow &arrivalTw, const uint deltaTime, const uint weight);
@@ -90,6 +94,13 @@ public:
 
     void resetKeyPoint(int routeIndex);
 
+    [[nodiscard]] double getTransitTravelTimeRatio() const;
+
+    void setTransitTravelTimeRatio(double transitTravelTimeRatio);
+
+    [[nodiscard]] static double computeTransitTravelTimeRatio(double deltaRatio, double travelTimeRatio);
+    [[nodiscard]] double computeTransitTravelTimeRatio(const Graph &graph, double travelTimeRatio) const;
+
     /**
      * Creates a string in an appropriate format for the request to be exported to a file that can be imported again
      * <br> <br>
diff --git a/src/utils/Constants.h b/src/utils/Constants.h
index 6e97b58..bd96f98 100644
--- a/src/utils/Constants.h
+++ b/src/utils/Constants.h
@@ -10,8 +10,20 @@ class Constants {
 public:
     static constexpr uint VEHICLE_CAPACITY = 4;
     static constexpr uint MAX_TRANSIT_CONNECTIONS = 2;
+    /**
+     * The maximum amount of transit entry stations checked during our heuristic algorithm
+     */
     static constexpr size_t MAX_TRANSIT_ENTRY_CANDIDATES = 10;
+    /**
+     * The maximum amount of transit exit stations checked during our heuristic algorithm
+     */
     static constexpr size_t MAX_TRANSIT_EXIT_CANDIDATES = 10;
+    static constexpr double DEFAULT_DELTA_RATIO = 1.5;
+/**
+     * A ratio between 1 and deltaRatio that'll allow us to compute each
+     * request's transit travel time ratio with regards to its delta ratio
+     */
+    static constexpr double BASE_TRANSIT_TRAVEL_TIME_RATIO = 1.4;
 };
 
 
-- 
GitLab


From bbc3a22b7b18c9f0764048a1b107e5ec86f07c9d Mon Sep 17 00:00:00 2001
From: Romain BERNARD <30secondstodraw@gmail.com>
Date: Fri, 26 Jul 2024 18:54:09 +0200
Subject: [PATCH 189/327] implement min/max transit entry constraints functions

---
 .../Heuristics/SimpleModularHeuristic.cpp     | 24 +++++++++++++++++++
 .../Heuristics/SimpleModularHeuristic.h       | 17 +++++++++----
 2 files changed, 37 insertions(+), 4 deletions(-)

diff --git a/src/algorithm/Multimodal/Heuristics/SimpleModularHeuristic.cpp b/src/algorithm/Multimodal/Heuristics/SimpleModularHeuristic.cpp
index b0f6eee..d58e5b9 100644
--- a/src/algorithm/Multimodal/Heuristics/SimpleModularHeuristic.cpp
+++ b/src/algorithm/Multimodal/Heuristics/SimpleModularHeuristic.cpp
@@ -30,3 +30,27 @@ std::vector<TransitAccess> SimpleModularHeuristic::getBestTransitEntriesList(con
     }
     return results;
 }
+
+uint SimpleModularHeuristic::getMinEntryConstraint(const Request &request, size_t entryNodeIndex) {
+    return request.getMinDepartureTw() + _graph->getShortestSAEVPath(request.getOriginNodeIndex(), entryNodeIndex);
+}
+
+uint SimpleModularHeuristic::getMaxEntryConstraint(const Request &request, size_t entryNodeIndex) {
+    return request.getMinDepartureTw() + _graph->getShortestSAEVPath(entryNodeIndex, request.getDestinationNodeIndex()) * request.getTransitTravelTimeRatio();
+}
+
+const Graph *SimpleModularHeuristic::getGraph() const {
+    return _graph;
+}
+
+void SimpleModularHeuristic::setGraph(const Graph *graph) {
+    _graph = graph;
+}
+
+SAEVRoute *SimpleModularHeuristic::getRoute() const {
+    return _route;
+}
+
+void SimpleModularHeuristic::setRoute(SAEVRoute *route) {
+    _route = route;
+}
diff --git a/src/algorithm/Multimodal/Heuristics/SimpleModularHeuristic.h b/src/algorithm/Multimodal/Heuristics/SimpleModularHeuristic.h
index 6388cab..9c29228 100644
--- a/src/algorithm/Multimodal/Heuristics/SimpleModularHeuristic.h
+++ b/src/algorithm/Multimodal/Heuristics/SimpleModularHeuristic.h
@@ -13,8 +13,11 @@
 #include "TransitAccess.h"
 
 class SimpleModularHeuristic {
+private:
     const Graph* _graph{nullptr};
     SAEVRoute* _route{nullptr};
+public:
+    SimpleModularHeuristic(const Graph *graph, SAEVRoute *route) : _graph(graph), _route(route) {}
 
     //Best candidates function
     /**
@@ -49,11 +52,17 @@ class SimpleModularHeuristic {
      std::vector<TransitAccess> getBestTransitExitsList(Request transitEntryRequest);
 
     //Entry filter
-    uint getMinEntryConstraint(Request request, size_t node);
-    uint getMaxEntryConstraint(Request request, size_t node);
+    uint getMinEntryConstraint(const Request &request, size_t entryNodeIndex);
+    uint getMaxEntryConstraint(const Request &request, size_t entryNodeIndex);
     //Exit filter
-    uint getMinExitConstraint(Request request, size_t node);
-    uint getMaxExitConstraint(Request request, size_t node);
+    uint getMinExitConstraint(const Request &request, size_t exitNodeIndex);
+    uint getMaxExitConstraint(const Request &request, size_t exitNodeIndex);
+
+    const Graph *getGraph() const;
+    void setGraph(const Graph *graph);
+
+    SAEVRoute *getRoute() const;
+    void setRoute(SAEVRoute *route);
 };
 
 
-- 
GitLab


From cf2c1c32bc3eb4ee368000107710cdccbbffac77 Mon Sep 17 00:00:00 2001
From: Romain BERNARD <romain.bernard@uca.fr>
Date: Wed, 21 Aug 2024 17:41:07 +0200
Subject: [PATCH 190/327] implement min/max constraints and make the
 appropriate members protected

---
 .../Multimodal/Heuristics/SimpleModularHeuristic.cpp      | 8 ++++----
 .../Multimodal/Heuristics/SimpleModularHeuristic.h        | 6 ++++--
 2 files changed, 8 insertions(+), 6 deletions(-)

diff --git a/src/algorithm/Multimodal/Heuristics/SimpleModularHeuristic.cpp b/src/algorithm/Multimodal/Heuristics/SimpleModularHeuristic.cpp
index d58e5b9..8022933 100644
--- a/src/algorithm/Multimodal/Heuristics/SimpleModularHeuristic.cpp
+++ b/src/algorithm/Multimodal/Heuristics/SimpleModularHeuristic.cpp
@@ -31,12 +31,12 @@ std::vector<TransitAccess> SimpleModularHeuristic::getBestTransitEntriesList(con
     return results;
 }
 
-uint SimpleModularHeuristic::getMinEntryConstraint(const Request &request, size_t entryNodeIndex) {
-    return request.getMinDepartureTw() + _graph->getShortestSAEVPath(request.getOriginNodeIndex(), entryNodeIndex);
+uint SimpleModularHeuristic::getMinEntryConstraint(const Request &request, size_t ptEntryNodeIdx) const {
+    return request.getMinDepartureTw() + _graph->getShortestSAEVPath(request.getOriginNodeIndex(), ptEntryNodeIdx);
 }
 
-uint SimpleModularHeuristic::getMaxEntryConstraint(const Request &request, size_t entryNodeIndex) {
-    return request.getMinDepartureTw() + _graph->getShortestSAEVPath(entryNodeIndex, request.getDestinationNodeIndex()) * request.getTransitTravelTimeRatio();
+uint SimpleModularHeuristic::getMaxEntryConstraint(const Request &request, size_t ptEntryNodeIdx) const {
+    return (uint) std::floor(request.getMaxArrivalTw() - _graph->getShortestSAEVPath(ptEntryNodeIdx, request.getDestinationNodeIndex()) * request.getTransitTravelTimeRatio());
 }
 
 const Graph *SimpleModularHeuristic::getGraph() const {
diff --git a/src/algorithm/Multimodal/Heuristics/SimpleModularHeuristic.h b/src/algorithm/Multimodal/Heuristics/SimpleModularHeuristic.h
index 9c29228..d1486b3 100644
--- a/src/algorithm/Multimodal/Heuristics/SimpleModularHeuristic.h
+++ b/src/algorithm/Multimodal/Heuristics/SimpleModularHeuristic.h
@@ -51,9 +51,11 @@ public:
      */
      std::vector<TransitAccess> getBestTransitExitsList(Request transitEntryRequest);
 
+//Protected member function for overriding as we make this more modular
+protected:
     //Entry filter
-    uint getMinEntryConstraint(const Request &request, size_t entryNodeIndex);
-    uint getMaxEntryConstraint(const Request &request, size_t entryNodeIndex);
+    [[nodiscard]] uint getMinEntryConstraint(const Request &request, size_t ptEntryNodeIdx) const;
+    [[nodiscard]] uint getMaxEntryConstraint(const Request &request, size_t ptEntryNodeIdx) const;
     //Exit filter
     uint getMinExitConstraint(const Request &request, size_t exitNodeIndex);
     uint getMaxExitConstraint(const Request &request, size_t exitNodeIndex);
-- 
GitLab


From ff55a3ae6b1a9ab0dfecec2b7c4379b2395903bf Mon Sep 17 00:00:00 2001
From: Romain BERNARD <romain.bernard@uca.fr>
Date: Wed, 21 Aug 2024 17:43:16 +0200
Subject: [PATCH 191/327] add public interface for the heuristic

---
 .../Multimodal/Heuristics/SimpleModularHeuristic.h       | 9 +++++++++
 1 file changed, 9 insertions(+)

diff --git a/src/algorithm/Multimodal/Heuristics/SimpleModularHeuristic.h b/src/algorithm/Multimodal/Heuristics/SimpleModularHeuristic.h
index d1486b3..c2bebe2 100644
--- a/src/algorithm/Multimodal/Heuristics/SimpleModularHeuristic.h
+++ b/src/algorithm/Multimodal/Heuristics/SimpleModularHeuristic.h
@@ -19,6 +19,15 @@ private:
 public:
     SimpleModularHeuristic(const Graph *graph, SAEVRoute *route) : _graph(graph), _route(route) {}
 
+//Public interface to interact with the modular heuristic
+public:
+    SimpleModularHeuristic(const Graph *graph, SAEVRoute *route) : _graph(graph), _route(route) {}
+
+    void multimodalRequestsInsertion(const std::vector<Request>& requestsToInsert);
+
+//Private members for heuristic internal functions we don't wish to see overriden
+private:
+
     //Best candidates function
     /**
      * Creates and returns a vector of TransitAccess objects representing possible
-- 
GitLab


From 8eb0198f394aab62335edb797f41dbc610eade16 Mon Sep 17 00:00:00 2001
From: Romain BERNARD <romain.bernard@uca.fr>
Date: Wed, 21 Aug 2024 17:53:42 +0200
Subject: [PATCH 192/327] separate closest stations list size limit and transit
 entry candidate size limit

---
 src/ShortestPath/Vehicle/VehicleShortestPathCalculation.cpp   | 2 +-
 .../Multimodal/Heuristics/SimpleModularHeuristic.cpp          | 3 +++
 src/utils/Constants.h                                         | 4 ++++
 3 files changed, 8 insertions(+), 1 deletion(-)

diff --git a/src/ShortestPath/Vehicle/VehicleShortestPathCalculation.cpp b/src/ShortestPath/Vehicle/VehicleShortestPathCalculation.cpp
index 26dffc2..234dc24 100644
--- a/src/ShortestPath/Vehicle/VehicleShortestPathCalculation.cpp
+++ b/src/ShortestPath/Vehicle/VehicleShortestPathCalculation.cpp
@@ -27,7 +27,7 @@ VehicleShortestPathCalculation::computeShortestPathsFromNode(Graph &graph, size_
             mark[currentState.getNodeIndex()] = true;
 
             //Considering order of iteration is by shortest path to starting node, it's fair to add the current state node as a closest station
-            if(graph.getNbPTLines(currentState.getNodeIndex()) > 0 && graph.getNbClosestStations(startingNodeIdx) < Constants::MAX_TRANSIT_ENTRY_CANDIDATES) {
+            if(graph.getNbPTLines(currentState.getNodeIndex()) > 0 && graph.getNbClosestStations(startingNodeIdx) < Constants::CLOSEST_STATIONS_LIST_SIZE) {
                 graph.emplaceBackClosestStation(startingNodeIdx, currentState.getNodeIndex());
             }
 
diff --git a/src/algorithm/Multimodal/Heuristics/SimpleModularHeuristic.cpp b/src/algorithm/Multimodal/Heuristics/SimpleModularHeuristic.cpp
index 8022933..886037e 100644
--- a/src/algorithm/Multimodal/Heuristics/SimpleModularHeuristic.cpp
+++ b/src/algorithm/Multimodal/Heuristics/SimpleModularHeuristic.cpp
@@ -26,6 +26,9 @@ std::vector<TransitAccess> SimpleModularHeuristic::getBestTransitEntriesList(con
         //If we've found a valid max departure time for this station, add it to the list
         if(maxDepartureTime > -1) {
             results.emplace_back(bestStationNodeIdx, maxDepartureTime);
+            if(results.size() == Constants::MAX_TRANSIT_ENTRY_CANDIDATES) {
+                break;
+            }
         }
     }
     return results;
diff --git a/src/utils/Constants.h b/src/utils/Constants.h
index bd96f98..9c2dcdd 100644
--- a/src/utils/Constants.h
+++ b/src/utils/Constants.h
@@ -10,6 +10,10 @@ class Constants {
 public:
     static constexpr uint VEHICLE_CAPACITY = 4;
     static constexpr uint MAX_TRANSIT_CONNECTIONS = 2;
+    /**
+     * The max amount of closest stations we preprocess for a given node (namely request origin nodes)
+     */
+    static constexpr size_t CLOSEST_STATIONS_LIST_SIZE = 30;
     /**
      * The maximum amount of transit entry stations checked during our heuristic algorithm
      */
-- 
GitLab


From 2f38cebc91fe557f732b31927560a3b9d8d61905 Mon Sep 17 00:00:00 2001
From: Romain BERNARD <romain.bernard@uca.fr>
Date: Thu, 22 Aug 2024 16:03:28 +0200
Subject: [PATCH 193/327] reset time windows and node index if request is
 changed for a given SAEV key point

---
 src/routes/vehicle/SAEVKeyPoint.cpp | 9 +++++++++
 1 file changed, 9 insertions(+)

diff --git a/src/routes/vehicle/SAEVKeyPoint.cpp b/src/routes/vehicle/SAEVKeyPoint.cpp
index 9f7527f..fff28f4 100644
--- a/src/routes/vehicle/SAEVKeyPoint.cpp
+++ b/src/routes/vehicle/SAEVKeyPoint.cpp
@@ -86,6 +86,15 @@ int SAEVKeyPoint::getDeltaTime() const {
 
 void SAEVKeyPoint::setRequest(const Request *requestPointer) {
     _requestPointer = requestPointer;
+    if(_isOrigin) {
+        setNodeIndex(_requestPointer->getOriginNodeIndex());
+        _minTW = _requestPointer->getDepartureTw().min;
+        _maxTW = _requestPointer->getDepartureTw().max;
+    } else {
+        setNodeIndex(_requestPointer->getDestinationNodeIndex());
+        _minTW = _requestPointer->getArrivalTw().min;
+        _maxTW = _requestPointer->getArrivalTw().max;
+    }
 }
 
 SAEVKeyPoint *SAEVKeyPoint::getCounterpart() const {
-- 
GitLab


From 36fccb3cba3437b83a047c1b8c4e99f73aac2b7b Mon Sep 17 00:00:00 2001
From: Romain BERNARD <romain.bernard@uca.fr>
Date: Thu, 22 Aug 2024 17:34:00 +0200
Subject: [PATCH 194/327] use getIndex methods where possible

---
 src/routes/vehicle/SAEVRoute.h | 12 ++++++------
 1 file changed, 6 insertions(+), 6 deletions(-)

diff --git a/src/routes/vehicle/SAEVRoute.h b/src/routes/vehicle/SAEVRoute.h
index 8dce807..dacaf12 100644
--- a/src/routes/vehicle/SAEVRoute.h
+++ b/src/routes/vehicle/SAEVRoute.h
@@ -113,11 +113,11 @@ public:
     BestInsertionQueue getBestFeasibleInsertionsQueue(size_t requestId, size_t vehicleId);
     void getBestFeasibleInsertionsQueue(BestInsertionQueue& bestInsertionQueue, size_t requestId, size_t vehicleId);
 
-    SAEVKeyPoint& getRequestOrigin(const size_t requestId) { return _route[requestId * 2];}
-    SAEVKeyPoint& getRequestDestination(const size_t requestId) { return _route[requestId * 2 + 1];}
+    SAEVKeyPoint& getRequestOrigin(const size_t requestId) { return _route[getRequestOriginRouteIdx(requestId)];}
+    SAEVKeyPoint& getRequestDestination(const size_t requestId) { return _route[getRequestDestinationRouteIdx(requestId)];}
 
-    SAEVKeyPoint& getOriginDepot(const size_t vehicleId) { return _route[_nbRequest*2 + vehicleId*2];}
-    SAEVKeyPoint& getDestinationDepot(const size_t vehicleId) { return _route[_nbRequest*2 + vehicleId*2 + 1];}
+    SAEVKeyPoint& getOriginDepot(const size_t vehicleId) { return _route[getOriginDepotRouteIdx(vehicleId)];}
+    SAEVKeyPoint& getDestinationDepot(const size_t vehicleId) { return _route[getDestinationDepotRouteIdx(vehicleId)];}
 
     [[nodiscard]] size_t getRequestOriginRouteIdx(const size_t requestId) const { return requestId * 2;}
     [[nodiscard]] size_t getRequestDestinationRouteIdx(const size_t requestId) const { return requestId * 2 + 1;}
@@ -126,8 +126,8 @@ public:
 
     [[nodiscard]] size_t getOriginDepotRouteIdx(const size_t vehicleId) const { return _nbRequest*2 + vehicleId*2;}
     [[nodiscard]] size_t getDestinationDepotRouteIdx(const size_t vehicleId) const { return _nbRequest*2 + vehicleId*2 + 1;}
-    [[nodiscard]] size_t getOriginDepotNodeIdx(const size_t vehicleId) const { return _route[_nbRequest*2 + vehicleId*2].getNodeIndex();}
-    [[nodiscard]] size_t getDestinationDepotNodeIdx(const size_t vehicleId) const { return _route[_nbRequest*2 + vehicleId*2].getNodeIndex();}
+    [[nodiscard]] size_t getOriginDepotNodeIdx(const size_t vehicleId) const { return _route[getOriginDepotRouteIdx(vehicleId)].getNodeIndex();}
+    [[nodiscard]] size_t getDestinationDepotNodeIdx(const size_t vehicleId) const { return _route[getDestinationDepotRouteIdx(vehicleId)].getNodeIndex();}
 
     [[nodiscard]] size_t getLastActiveVehicleId() const { return _lastActiveVehicleId; }
     void setLastActiveVehicleId(size_t lastActiveVehicleId) { _lastActiveVehicleId = lastActiveVehicleId; }
-- 
GitLab


From 08d7906cfb5d1eae22aa15dc02cbe91f01269866 Mon Sep 17 00:00:00 2001
From: Romain BERNARD <romain.bernard@uca.fr>
Date: Fri, 23 Aug 2024 11:45:12 +0200
Subject: [PATCH 195/327] massive API refactor to directly use keypoints
 wherever possible. Necessary for extending the current data structure to the
 case of entry/exit subrequests

---
 src/routes/vehicle/BestInsertionQueue.h       |  13 +-
 src/routes/vehicle/SAEVRoute.cpp              | 184 +++++++++---------
 src/routes/vehicle/SAEVRoute.h                |  56 ++++--
 .../propagation/SAEVRouteChangelist.cpp       |  10 +-
 .../vehicle/propagation/SAEVRouteChangelist.h |  22 +--
 5 files changed, 146 insertions(+), 139 deletions(-)

diff --git a/src/routes/vehicle/BestInsertionQueue.h b/src/routes/vehicle/BestInsertionQueue.h
index 25b077f..9c42242 100644
--- a/src/routes/vehicle/BestInsertionQueue.h
+++ b/src/routes/vehicle/BestInsertionQueue.h
@@ -11,14 +11,15 @@
 
 class BestInsertionQueue : public std::priority_queue<BestRequestInsertion, std::vector<BestRequestInsertion>, std::greater<>> {
 private:
-    size_t _requestId{std::numeric_limits<size_t>::max()};
+    const SAEVKeyPoint &_originKP;
     size_t _vehicleId{std::numeric_limits<size_t>::max()};
 
 public:
-    explicit BestInsertionQueue(size_t requestId) : _requestId(requestId) {}
-    BestInsertionQueue(size_t requestId, size_t vehicleId) : _requestId(requestId), _vehicleId(vehicleId) {}
+    explicit BestInsertionQueue(const SAEVKeyPoint &originKP) : _originKP(originKP) {}
 
-    BestInsertionQueue(size_t requestId, size_t vehicleId, size_t nbRequests) : BestInsertionQueue(requestId, vehicleId) {
+    BestInsertionQueue(const SAEVKeyPoint &originKP, size_t vehicleId) : _originKP(originKP), _vehicleId(vehicleId) {}
+
+    BestInsertionQueue(const SAEVKeyPoint &originKP, size_t vehicleId, size_t nbRequests) : BestInsertionQueue(originKP, vehicleId) {
         c.reserve(nbRequests^2);
     }
 
@@ -26,8 +27,8 @@ public:
         return _vehicleId;
     }
 
-    [[nodiscard]] size_t getRequestId() const {
-        return _requestId;
+    [[nodiscard]] const SAEVKeyPoint &getOriginKp() const {
+        return _originKP;
     }
 
     /**
diff --git a/src/routes/vehicle/SAEVRoute.cpp b/src/routes/vehicle/SAEVRoute.cpp
index bfb340f..07356ce 100644
--- a/src/routes/vehicle/SAEVRoute.cpp
+++ b/src/routes/vehicle/SAEVRoute.cpp
@@ -37,9 +37,8 @@ SAEVRoute::SAEVRoute(const Graph& graph, const std::vector<Request>& requestList
     }
 }
 
-void SAEVRoute::insertRequest(size_t requestId, SAEVKeyPoint * originRequestPredecessorKP, SAEVKeyPoint * destinationRequestPredecessorKP) {
-    SAEVKeyPoint& originKp = getRequestOrigin(requestId);
-    SAEVKeyPoint& destinationKp = getRequestDestination(requestId);
+void SAEVRoute::insertRequest(SAEVKeyPoint &originKp, SAEVKeyPoint * originRequestPredecessorKP, SAEVKeyPoint * destinationRequestPredecessorKP) {
+    SAEVKeyPoint* destinationKp = originKp.getCounterpart();
 
     SAEVKeyPoint *originSuccKp = originRequestPredecessorKP->getSuccessor();
     SAEVKeyPoint *destinationSuccKp = destinationRequestPredecessorKP->getSuccessor();
@@ -48,44 +47,43 @@ void SAEVRoute::insertRequest(size_t requestId, SAEVKeyPoint * originRequestPred
         //Set values for O/D KPs
         originKp.setPredecessor(originRequestPredecessorKP);
         originKp.setSuccessor(originSuccKp);
-        destinationKp.setPredecessor(destinationRequestPredecessorKP);
-        destinationKp.setSuccessor(destinationSuccKp);
+        destinationKp->setPredecessor(destinationRequestPredecessorKP);
+        destinationKp->setSuccessor(destinationSuccKp);
 
         //Set values for predecessors/successors
         originRequestPredecessorKP->setSuccessor(&originKp);
         originSuccKp->setPredecessor(&originKp);
-        destinationRequestPredecessorKP->setSuccessor(&destinationKp);
-        destinationSuccKp->setPredecessor(&destinationKp);
+        destinationRequestPredecessorKP->setSuccessor(destinationKp);
+        destinationSuccKp->setPredecessor(destinationKp);
     } else {
         //Set values for O/D KPs
         originKp.setPredecessor(originRequestPredecessorKP);
-        originKp.setSuccessor(&destinationKp);
-        destinationKp.setPredecessor(&originKp);
-        destinationKp.setSuccessor(destinationSuccKp);
+        originKp.setSuccessor(destinationKp);
+        destinationKp->setPredecessor(&originKp);
+        destinationKp->setSuccessor(destinationSuccKp);
 
         //Set values for predecessors/successors
         originRequestPredecessorKP->setSuccessor(&originKp);
-        originSuccKp->setPredecessor(&destinationKp);
+        originSuccKp->setPredecessor(destinationKp);
     }
     //Once insertion is done, update weights on the route
-    addRequestWeightToRoute(requestId);
+    addRequestWeightToRoute(originKp);
 }
 
-void SAEVRoute::removeRequest(size_t requestId) {
+void SAEVRoute::removeRequest(SAEVKeyPoint &originKp) {
     //Before undoing the insertion, update weights on the route
-    removeRequestWeightFromRoute(requestId);
+    removeRequestWeightFromRoute(originKp);
 
-    SAEVKeyPoint& originKp = getRequestOrigin(requestId);
-    SAEVKeyPoint& destinationKp = getRequestDestination(requestId);
+    SAEVKeyPoint* destinationKp = originKp.getCounterpart();
 
     //get predecessor and successor for request
     SAEVKeyPoint* originPredecessor = originKp.getPredecessor();
     SAEVKeyPoint* originSuccessor = originKp.getSuccessor();
-    SAEVKeyPoint* destinationPredecessor = destinationKp.getPredecessor();
-    SAEVKeyPoint* destinationSuccessor = destinationKp.getSuccessor();
+    SAEVKeyPoint* destinationPredecessor = destinationKp->getPredecessor();
+    SAEVKeyPoint* destinationSuccessor = destinationKp->getSuccessor();
 
     //Link pred and successor from origin and destination (cases differ if O/D are next to each other
-    if(originSuccessor == &destinationKp) {
+    if(originSuccessor == destinationKp) {
         originPredecessor->setSuccessor(destinationSuccessor);
         destinationSuccessor->setPredecessor(originPredecessor);
     } else {
@@ -98,17 +96,22 @@ void SAEVRoute::removeRequest(size_t requestId) {
     //Revert origin/destination key points to their default state
     originKp.setPredecessor(nullptr);
     originKp.setSuccessor(nullptr);
-    destinationKp.setPredecessor(nullptr);
-    destinationKp.setSuccessor(nullptr);
-    originKp.setMinTw((*_requestList)[requestId].getMinDepartureTw());
-    originKp.setMaxTw((*_requestList)[requestId].getMaxDepartureTw());
-    destinationKp.setMinTw((*_requestList)[requestId].getMinArrivalTw());
-    destinationKp.setMaxTw((*_requestList)[requestId].getMaxArrivalTw());
+    destinationKp->setPredecessor(nullptr);
+    destinationKp->setSuccessor(nullptr);
+    originKp.setMinTw(originKp.getRequest()->getMinDepartureTw());
+    originKp.setMaxTw(originKp.getRequest()->getMaxDepartureTw());
+    destinationKp->setMinTw(originKp.getRequest()->getMinArrivalTw());
+    destinationKp->setMaxTw(originKp.getRequest()->getMaxArrivalTw());
 }
 
 SAEVRouteChangelist
-SAEVRoute::tryAddRequest(const size_t requestId, SAEVKeyPoint * originRequestPredecessorKP, SAEVKeyPoint * destinationRequestPredecessorKP) {
-    const Request* request = &(*_requestList)[requestId];
+SAEVRoute::tryAddRequest(size_t requestId, SAEVKeyPoint * originRequestPredecessorKP, SAEVKeyPoint * destinationRequestPredecessorKP) {
+    return tryAddRequest(getRequestOrigin(requestId), originRequestPredecessorKP, destinationRequestPredecessorKP);
+}
+
+SAEVRouteChangelist
+SAEVRoute::tryAddRequest(SAEVKeyPoint &requestOriginKeyPoint, SAEVKeyPoint * originRequestPredecessorKP, SAEVKeyPoint * destinationRequestPredecessorKP) {
+    const Request* request = requestOriginKeyPoint.getRequest();
     SAEVKeyPoint const* destinationSuccessor = destinationRequestPredecessorKP->getSuccessor();
 
     //Check vehicle capacity
@@ -116,38 +119,37 @@ SAEVRoute::tryAddRequest(const size_t requestId, SAEVKeyPoint * originRequestPre
     do {
         if(currentKP->getCurrentOccupation() + request->getWeight() > SAEVehicle::getCapacity()) {
             DEBUG_MSG("WEIGHT VIOLATION : request weight = " + std::to_string(request->getWeight()) + " incompatible KP = " + currentKP->to_string());
-            return SAEVRouteChangelist(this, requestId, originRequestPredecessorKP, destinationRequestPredecessorKP, SAEVRouteChangelist::InsertionStatus::FAILURE_PRECONDITION_WEIGHT);
+            return SAEVRouteChangelist(this, &requestOriginKeyPoint, originRequestPredecessorKP, destinationRequestPredecessorKP, SAEVRouteChangelist::InsertionStatus::FAILURE_PRECONDITION_WEIGHT);
         }
         currentKP = currentKP->getSuccessor();
     } while (currentKP != destinationSuccessor && currentKP != nullptr);
 
     //Do basic checks on neighbouring nodes from our Origin/Destination insertion points
-    bool isValid = doNeighbouringTWChecks(requestId, originRequestPredecessorKP, destinationRequestPredecessorKP);
+    bool isValid = doNeighbouringTWChecks(requestOriginKeyPoint, originRequestPredecessorKP, destinationRequestPredecessorKP);
 
     if(isValid) {
-        return insertRequestWithPropagation(requestId, originRequestPredecessorKP, destinationRequestPredecessorKP);
+        return insertRequestWithPropagation(requestOriginKeyPoint, originRequestPredecessorKP, destinationRequestPredecessorKP);
     } else {
         DEBUG_MSG("TW VIOLATION on neighbour KPs");
-        return SAEVRouteChangelist(this, requestId, originRequestPredecessorKP, destinationRequestPredecessorKP, SAEVRouteChangelist::InsertionStatus::FAILURE_PRECONDITION_TW);
+        return SAEVRouteChangelist(this, &requestOriginKeyPoint, originRequestPredecessorKP, destinationRequestPredecessorKP, SAEVRouteChangelist::InsertionStatus::FAILURE_PRECONDITION_TW);
     }
 }
 
 bool
-SAEVRoute::doNeighbouringTWChecks(const size_t requestId, const SAEVKeyPoint *originPredecessor, const SAEVKeyPoint *destinationPredecessor) {
+SAEVRoute::doNeighbouringTWChecks(const SAEVKeyPoint &originKP, const SAEVKeyPoint *originPredecessor, const SAEVKeyPoint *destinationPredecessor) const {
 
-    const SAEVKeyPoint& originKP = getRequestOrigin(requestId);
-    const SAEVKeyPoint& destinationKP = getRequestDestination(requestId);
+    const SAEVKeyPoint* destinationKP = originKP.getCounterpart();
     const SAEVKeyPoint* originSuccessor = originPredecessor->getSuccessor();
     const size_t originNodeIndex = originKP.getNodeIndex();
-    const size_t destinationNodeIndex = destinationKP.getNodeIndex();
+    const size_t destinationNodeIndex = destinationKP->getNodeIndex();
 
     if(originPredecessor != destinationPredecessor)
     {
         SAEVKeyPoint const* destinationSuccessor = destinationPredecessor->getSuccessor();
 
         //Tests time windows Origin (yes this if-else could be one giant OR, but I'd rather separate every case)
-        int predOriginTimeWindow = originPredecessor->getMinTw() + _graph->getShortestSAEVPath(originPredecessor->getNodeIndex(), originNodeIndex);
-        int predDestinationTimeWindow = destinationPredecessor->getMinTw() + _graph->getShortestSAEVPath(destinationPredecessor->getNodeIndex(), destinationNodeIndex);
+        uint predOriginTimeWindow = originPredecessor->getMinTw() + _graph->getShortestSAEVPath(originPredecessor->getNodeIndex(), originNodeIndex);
+        uint predDestinationTimeWindow = destinationPredecessor->getMinTw() + _graph->getShortestSAEVPath(destinationPredecessor->getNodeIndex(), destinationNodeIndex);
         if(predOriginTimeWindow > originKP.getMaxTw())
             return false;
         else if(originKP.getMinTw() + _graph->getShortestSAEVPath(originKP.getNodeIndex(), originSuccessor->getNodeIndex()) > originSuccessor->getMaxTw()) // Could be removed ?
@@ -155,22 +157,22 @@ SAEVRoute::doNeighbouringTWChecks(const size_t requestId, const SAEVKeyPoint *or
         else if(predOriginTimeWindow + _graph->getShortestSAEVPath(originKP.getNodeIndex(), originSuccessor->getNodeIndex()) > originSuccessor->getMaxTw())
             return false;
         //Tests time windows Destination
-        else if(predDestinationTimeWindow > destinationKP.getMaxTw())
+        else if(predDestinationTimeWindow > destinationKP->getMaxTw())
             return false;
-        else if(destinationKP.getMinTw() + _graph->getShortestSAEVPath(destinationKP.getNodeIndex(), destinationSuccessor->getNodeIndex()) > destinationSuccessor->getMaxTw()) //could be removed ?
+        else if(destinationKP->getMinTw() + _graph->getShortestSAEVPath(destinationKP->getNodeIndex(), destinationSuccessor->getNodeIndex()) > destinationSuccessor->getMaxTw()) //could be removed ?
             return false;
-        else if(predOriginTimeWindow + _graph->getShortestSAEVPath(destinationKP.getNodeIndex(), destinationSuccessor->getNodeIndex()) > destinationSuccessor->getMaxTw())
+        else if(predOriginTimeWindow + _graph->getShortestSAEVPath(destinationKP->getNodeIndex(), destinationSuccessor->getNodeIndex()) > destinationSuccessor->getMaxTw())
             return false;
     } else { //We need a specific case if origin and destination are inserted after the same node
-        int predMinTWToOrigin = originPredecessor->getMinTw() + _graph->getShortestSAEVPath(originPredecessor->getNodeIndex(), originNodeIndex);
-        int predMinTWToDest = predMinTWToOrigin + _graph->getShortestSAEVPath(originNodeIndex, destinationNodeIndex);
+        uint predMinTWToOrigin = originPredecessor->getMinTw() + _graph->getShortestSAEVPath(originPredecessor->getNodeIndex(), originNodeIndex);
+        uint predMinTWToDest = predMinTWToOrigin + _graph->getShortestSAEVPath(originNodeIndex, destinationNodeIndex);
         if(predMinTWToOrigin > originKP.getMaxTw()) //Path from pred to O
             return false;
-        else if(predMinTWToDest > destinationKP.getMaxTw()) //Path from pred to D
+        else if(predMinTWToDest > destinationKP->getMaxTw()) //Path from pred to D
             return false;
         else if(predMinTWToDest + _graph->getShortestSAEVPath(destinationNodeIndex, originSuccessor->getNodeIndex()) > originSuccessor->getMaxTw()) //Path from pred to successor
             return false;
-        else if(destinationKP.getMinTw() + _graph->getShortestSAEVPath(destinationNodeIndex, originSuccessor->getNodeIndex()) > originSuccessor->getMaxTw()) //Path from D to successor
+        else if(destinationKP->getMinTw() + _graph->getShortestSAEVPath(destinationNodeIndex, originSuccessor->getNodeIndex()) > originSuccessor->getMaxTw()) //Path from D to successor
             return false;
         else if(originKP.getMinTw() + _graph->getShortestSAEVPath(originNodeIndex, destinationNodeIndex) //Path from O to successor
         + _graph->getShortestSAEVPath(destinationNodeIndex, originSuccessor->getNodeIndex()) > originSuccessor->getMaxTw())
@@ -180,29 +182,29 @@ SAEVRoute::doNeighbouringTWChecks(const size_t requestId, const SAEVKeyPoint *or
     return true;
 }
 
-SAEVRouteChangelist SAEVRoute::insertRequestWithPropagation(const size_t requestId, SAEVKeyPoint * originRequestPredecessorKP,
+SAEVRouteChangelist SAEVRoute::insertRequestWithPropagation(SAEVKeyPoint &originKP, SAEVKeyPoint * originRequestPredecessorKP,
                                                             SAEVKeyPoint * destinationRequestPredecessorKP) {
-    //Init changelist
-    SAEVRouteChangelist changelist{this, requestId, originRequestPredecessorKP, destinationRequestPredecessorKP, SAEVRouteChangelist::InsertionStatus::FAILURE_MIN};
+    //Init changelist and detour score
+    SAEVRouteChangelist changelist{this, &originKP, originRequestPredecessorKP, destinationRequestPredecessorKP, SAEVRouteChangelist::InsertionStatus::FAILURE_MIN};
+    double detourScore = getDetourScore(originKP, originRequestPredecessorKP, destinationRequestPredecessorKP);
     //Properly insert the request to facilitate constraint propagation
-    insertRequest(requestId, originRequestPredecessorKP, destinationRequestPredecessorKP);
+    insertRequest(originKP, originRequestPredecessorKP, destinationRequestPredecessorKP);
 
     //Initialize bound propagation signal queue (each item signals a modification done on one of a KeyPoint
     std::queue<std::pair<Bound, SAEVKeyPoint *>> boundPropagationQueue{};
-    SAEVKeyPoint * originKP = &getRequestOrigin(requestId);
-    SAEVKeyPoint * destinationKP = &getRequestDestination(requestId);
-    boundPropagationQueue.emplace(Min, originKP->getPredecessor());
-    boundPropagationQueue.emplace(Max, originKP->getSuccessor());
+    SAEVKeyPoint * destinationKP = originKP.getCounterpart();
+    boundPropagationQueue.emplace(Min, originKP.getPredecessor());
+    boundPropagationQueue.emplace(Max, originKP.getSuccessor());
     boundPropagationQueue.emplace(Min, destinationKP->getPredecessor());
     boundPropagationQueue.emplace(Max, destinationKP->getSuccessor());
-    boundPropagationQueue.emplace(Min, originKP);
-    boundPropagationQueue.emplace(Max, originKP);
+    boundPropagationQueue.emplace(Min, &originKP);
+    boundPropagationQueue.emplace(Max, &originKP);
     boundPropagationQueue.emplace(Min, destinationKP);
     boundPropagationQueue.emplace(Max, destinationKP);
 
     //Pre-init variables used in the loop
-    int oldValue;
-    int newValue;
+    uint oldValue;
+    uint newValue;
     SAEVKeyPoint * predecessorKP;
     SAEVKeyPoint * successorKP;
     SAEVKeyPoint * counterpartKP; //An Origin's Destination, or a Destination's Origin
@@ -212,7 +214,6 @@ SAEVRouteChangelist SAEVRoute::insertRequestWithPropagation(const size_t request
         auto const& [bound, keyPoint] = boundPropagationQueue.front();
         boundPropagationQueue.pop();
         counterpartKP = keyPoint->getCounterpart();
-//        DEBUG_MSG("KP=" + keyPoint->to_string() + "\n");
         if(bound == Min) {
             successorKP = keyPoint->getSuccessor();
             if(successorKP != nullptr) {
@@ -225,12 +226,9 @@ SAEVRouteChangelist SAEVRoute::insertRequestWithPropagation(const size_t request
                         changelist.setStatus(SAEVRouteChangelist::InsertionStatus::FAILURE_MIN);
                         return changelist;
                     }
-//                    DEBUG_MSG("\tMIN Successeur KP=" + successorKP->to_string() + "\n\tModif Min=" + std::to_string(oldValue) + "->" + std::to_string(newValue));
                     changelist.emplace_back(*successorKP, Min, newValue - oldValue);
                     successorKP->setMinTw(newValue);
                     boundPropagationQueue.emplace(Min, successorKP);
-                } else {
-//                    DEBUG_MSG("Pas de changement pour Min du noeud " + successorKP->to_string() + " successeur de " + keyPoint->to_string());
                 }
             }
             //Check counterpart key point delta time
@@ -242,12 +240,9 @@ SAEVRouteChangelist SAEVRoute::insertRequestWithPropagation(const size_t request
                     changelist.setStatus(SAEVRouteChangelist::InsertionStatus::FAILURE_DELTA_MIN);
                     return changelist;
                 }
-//                DEBUG_MSG("\tMIN Counterpart KP=" + counterpartKP->to_string() + "\n\tModif Min=" + std::to_string(oldValue) + "->" + std::to_string(newValue));
                 changelist.emplace_back(*counterpartKP, Min, newValue - oldValue);
                 counterpartKP->setMinTw(newValue);
                 boundPropagationQueue.emplace(Min, counterpartKP);
-            } else if(!keyPoint->isDepot() && keyPoint->isDestination()) {
-//                DEBUG_MSG("Pas de changement pour Min du noeud " + counterpartKP->to_string() + " via  sa destination " + keyPoint->to_string());
             }
         } else { //MAX
             predecessorKP = keyPoint->getPredecessor();
@@ -261,12 +256,9 @@ SAEVRouteChangelist SAEVRoute::insertRequestWithPropagation(const size_t request
                         changelist.setStatus(SAEVRouteChangelist::InsertionStatus::FAILURE_MAX);
                         return changelist;
                     }
-//                    DEBUG_MSG("\tMAX Predecessor KP=" + predecessorKP->to_string() + "\n\tModif Max=" + std::to_string(oldValue) + "->" + std::to_string(newValue));
                     changelist.emplace_back(*predecessorKP, Max, newValue - oldValue);
                     predecessorKP->setMaxTw(newValue);
                     boundPropagationQueue.emplace(Max, predecessorKP);
-                } else {
-//                    DEBUG_MSG("Pas de changement pour Max pour noeud " + predecessorKP->to_string() + " prédécesseur de " + predecessorKP->to_string());
                 }
             }
             //Check counterpart key point delta time
@@ -281,21 +273,19 @@ SAEVRouteChangelist SAEVRoute::insertRequestWithPropagation(const size_t request
                 changelist.emplace_back(*counterpartKP, Max, oldValue - newValue);
                 counterpartKP->setMaxTw(newValue);
                 boundPropagationQueue.emplace(Max, counterpartKP);
-//                DEBUG_MSG("\tMAX Destination KP=" + counterpartKP->to_string() + "\n\tModif Max=" + std::to_string(oldValue) + "->" + std::to_string(newValue));
             }
         }
     }
 
     changelist.setStatus(SAEVRouteChangelist::InsertionStatus::SUCCESS);
-    changelist.setScore(getDetourScore(requestId, originRequestPredecessorKP, destinationRequestPredecessorKP));
+    changelist.setScore(detourScore);
     return changelist;
 }
 
-double SAEVRoute::getDetourScore(const size_t requestId, const SAEVKeyPoint * originRequestPredecessorKP,
+double SAEVRoute::getDetourScore(const SAEVKeyPoint &originKP, const SAEVKeyPoint * originRequestPredecessorKP,
                                  const SAEVKeyPoint * destinationRequestPredecessorKP) {
     double score;
-    const SAEVKeyPoint& originKP = getRequestOrigin(requestId);
-    const SAEVKeyPoint& destinationKP = getRequestDestination(requestId);
+    const SAEVKeyPoint* destinationKP = originKP.getCounterpart();
     const SAEVKeyPoint* originSuccKP = originRequestPredecessorKP->getSuccessor();
     const SAEVKeyPoint* destinationSuccKP = destinationRequestPredecessorKP->getSuccessor();
 
@@ -308,13 +298,13 @@ double SAEVRoute::getDetourScore(const size_t requestId, const SAEVKeyPoint * or
                 - _graph->getShortestSAEVPath(originRequestPredecessorKP->getNodeIndex(), originSuccKP->getNodeIndex()); //T(Pred(O), Succ(O))
 
         //Destination Detour
-        score += _graph->getShortestSAEVPath(destinationPredKP->getNodeIndex(), destinationKP.getNodeIndex()) //T(Pred(D), D))
-                + _graph->getShortestSAEVPath(destinationKP.getNodeIndex(), destinationSuccKP->getNodeIndex()) //T(D, Succ(D)))
+        score += _graph->getShortestSAEVPath(destinationPredKP->getNodeIndex(), destinationKP->getNodeIndex()) //T(Pred(D), D))
+                + _graph->getShortestSAEVPath(destinationKP->getNodeIndex(), destinationSuccKP->getNodeIndex()) //T(D, Succ(D)))
                 - _graph->getShortestSAEVPath(destinationPredKP->getNodeIndex(), destinationSuccKP->getNodeIndex()); //T(Pred(D), Succ(D)))
     } else {
         score = _graph->getShortestSAEVPath(originRequestPredecessorKP->getNodeIndex(), originKP.getNodeIndex()) //T(Pred(O), O)
-                + _graph->getShortestSAEVPath(originKP.getNodeIndex(), destinationKP.getNodeIndex()) //T(O, D)
-                + _graph->getShortestSAEVPath(destinationKP.getNodeIndex(), destinationSuccKP->getNodeIndex()) //T(D, Succ(D))
+                + _graph->getShortestSAEVPath(originKP.getNodeIndex(), destinationKP->getNodeIndex()) //T(O, D)
+                + _graph->getShortestSAEVPath(destinationKP->getNodeIndex(), destinationSuccKP->getNodeIndex()) //T(D, Succ(D))
                 - _graph->getShortestSAEVPath(originRequestPredecessorKP->getNodeIndex(), destinationSuccKP->getNodeIndex()); //T(Pred(O), Succ(D))
     }
     return score;
@@ -369,12 +359,12 @@ bool SAEVRoute::checkRouteTimeWindows(size_t vehicleId) {
 
 /** TODO: move to BestInsertionQueue class with a route parameter ?
  * Initializes a BestInsertionQueue to guide the best insertion heuristic
- * @param requestId
- * @param vehicleId
- * @return
+ * @param requestOriginKeyPoint Reference to the origin key point
+ * @param vehicleId The ID of the vehicle in which we look for new best insertions
+ * @return The created BestInsertionQueue filled with the best insertions for the given request and vehicle IDs
  */
-BestInsertionQueue SAEVRoute::getBestInsertionsQueue(size_t requestId, size_t vehicleId) {
-    BestInsertionQueue bestInsertionQueue(requestId, vehicleId, _nbRequest^2);
+BestInsertionQueue SAEVRoute::getBestInsertionsQueue(const SAEVKeyPoint &originKP, size_t vehicleId) {
+    BestInsertionQueue bestInsertionQueue(originKP, vehicleId, _nbRequest ^ 2);
 
     //Init variables used during iteration
     double score;
@@ -384,7 +374,7 @@ BestInsertionQueue SAEVRoute::getBestInsertionsQueue(size_t requestId, size_t ve
     //iterate over possible origin/destination pairs for the given vehicle
     while(originInsertionKeyPoint->getSuccessor() != nullptr) {
         while(destinationInsertionKeyPoint->getSuccessor() != nullptr) {
-            score = getDetourScore(requestId, originInsertionKeyPoint, destinationInsertionKeyPoint);
+            score = getDetourScore(originKP, originInsertionKeyPoint, destinationInsertionKeyPoint);
             bestInsertionQueue.emplace(originInsertionKeyPoint, destinationInsertionKeyPoint, score);
             destinationInsertionKeyPoint = destinationInsertionKeyPoint->getSuccessor();
         }
@@ -399,23 +389,23 @@ BestInsertionQueue SAEVRoute::getBestInsertionsQueue(size_t requestId, size_t ve
 
 /**
  * Initializes a BestInsertionQueue to guide the best insertion heuristic while checking neighbouring TW checks
- * @param requestId The ID of the request for which we search best insertions
+ * @param requestOriginKeyPoint Reference to the origin key point of the request for which we search best insertions
  * @param vehicleId The ID of the vehicle in which we look for new best insertions
  * @return The created BestInsertionQueue filled with the best insertions for the given request and vehicle IDs
  */
-BestInsertionQueue SAEVRoute::getBestFeasibleInsertionsQueue(size_t requestId, size_t vehicleId) {
-    BestInsertionQueue bestInsertionQueue(requestId, vehicleId, _nbRequest^2);
-    getBestFeasibleInsertionsQueue(bestInsertionQueue, requestId, vehicleId);
+BestInsertionQueue SAEVRoute::getBestFeasibleInsertionsQueue(const SAEVKeyPoint &originKP, size_t vehicleId) {
+    BestInsertionQueue bestInsertionQueue(originKP, vehicleId, _nbRequest ^ 2);
+    getBestFeasibleInsertionsQueue(bestInsertionQueue, originKP, vehicleId);
     return bestInsertionQueue;
 }
 
 /**
  * Search for new best insertions to add into the given best insertion queue for a given request and vehicle
  * @param bestInsertionQueue The queue we wish to add the new feasible best insertions to
- * @param requestId The ID of the request for which we search best insertions
+ * @param requestOriginKeyPoint Reference to the origin key point of the request for which we search best insertions
  * @param vehicleId The ID of the vehicle in which we look for new best insertions
  */
-void SAEVRoute::getBestFeasibleInsertionsQueue(BestInsertionQueue& bestInsertionQueue, size_t requestId, size_t vehicleId) {
+void SAEVRoute::getBestFeasibleInsertionsQueue(BestInsertionQueue& bestInsertionQueue, const SAEVKeyPoint &requestOriginKeyPoint, size_t vehicleId) {
     //Init variables used during iteration
     double score;
     SAEVKeyPoint * originInsertionKeyPoint = &getOriginDepot(vehicleId);
@@ -424,8 +414,8 @@ void SAEVRoute::getBestFeasibleInsertionsQueue(BestInsertionQueue& bestInsertion
     //iterate over possible origin/destination pairs for the given vehicle
     while(originInsertionKeyPoint->getSuccessor() != nullptr) {
         while(destinationInsertionKeyPoint->getSuccessor() != nullptr) {
-            if(doNeighbouringTWChecks(requestId,originInsertionKeyPoint, destinationInsertionKeyPoint)) {
-                score = getDetourScore(requestId, originInsertionKeyPoint, destinationInsertionKeyPoint);
+            if(doNeighbouringTWChecks(requestOriginKeyPoint, originInsertionKeyPoint, destinationInsertionKeyPoint)) {
+                score = getDetourScore(requestOriginKeyPoint, originInsertionKeyPoint, destinationInsertionKeyPoint);
                 bestInsertionQueue.emplace(originInsertionKeyPoint, destinationInsertionKeyPoint, score);
             }
             destinationInsertionKeyPoint = destinationInsertionKeyPoint->getSuccessor();
@@ -437,25 +427,25 @@ void SAEVRoute::getBestFeasibleInsertionsQueue(BestInsertionQueue& bestInsertion
     }
 }
 
-void SAEVRoute::addRequestWeightToRoute(size_t requestId) {
-    SAEVKeyPoint* currentKP = &getRequestOrigin(requestId);
-    int requestWeight = currentKP->getRequest()->getWeight();
+void SAEVRoute::addRequestWeightToRoute(SAEVKeyPoint &requestOriginKeyPoint) {
+    SAEVKeyPoint* currentKP = &requestOriginKeyPoint;
+    uint requestWeight = currentKP->getRequest()->getWeight();
     currentKP->setCurrentOccupation(currentKP->getPredecessor()->getCurrentOccupation() + requestWeight); //O.Weight = Prec(O).Weight + R.Weight (request enters the vehicle=)
     do {
         currentKP = currentKP->getSuccessor();
         currentKP->setCurrentOccupation(currentKP->getCurrentOccupation() + requestWeight);
-    } while (currentKP != &getRequestDestination(requestId));
+    } while (currentKP != requestOriginKeyPoint.getCounterpart());
     currentKP->setCurrentOccupation(currentKP->getPredecessor()->getCurrentOccupation() - requestWeight); //D.Weight = Prec(D).Weight - R.Weight (request leaves the vehicle)
 }
 
-void SAEVRoute::removeRequestWeightFromRoute(size_t requestId) {
-    SAEVKeyPoint* currentKP = &getRequestOrigin(requestId);
-    int requestWeight = currentKP->getRequest()->getWeight();
+void SAEVRoute::removeRequestWeightFromRoute(SAEVKeyPoint& requestOriginKeyPoint) {
+    SAEVKeyPoint* currentKP = &requestOriginKeyPoint;
+    uint requestWeight = currentKP->getRequest()->getWeight();
     currentKP->setCurrentOccupation(0); //reset request weight on origin KP
     do {
         currentKP = currentKP->getSuccessor();
         currentKP->setCurrentOccupation(currentKP->getCurrentOccupation() - requestWeight);
-    } while (currentKP != &getRequestDestination(requestId));
+    } while (currentKP != requestOriginKeyPoint.getCounterpart());
     currentKP->setCurrentOccupation(0); //reset request weight on destination KP
 }
 
diff --git a/src/routes/vehicle/SAEVRoute.h b/src/routes/vehicle/SAEVRoute.h
index dacaf12..2b560cd 100644
--- a/src/routes/vehicle/SAEVRoute.h
+++ b/src/routes/vehicle/SAEVRoute.h
@@ -35,30 +35,30 @@ public:
 
     /**
      * Raw request route insertion method. Public for debug purposes, but should effectively never be called by an outside member
-     * @param requestId index of the request we want to insert in the route
+     * @param originKp Reference to the origin key point of the request we want to insert in the route
      * @param originRequestPredecessorKP Identifier/index in the route key point vector for the request origin or destination that will precede the origin of the request we want to insert
      * @param destinationRequestPredecessorKP Identifier/index in the route key point vector for the request origin or destination that will precede the destination of the request we want to insert
      */
-    void insertRequest(size_t requestId, SAEVKeyPoint * originRequestPredecessorKP, SAEVKeyPoint * destinationRequestPredecessorKP);
+    void insertRequest(SAEVKeyPoint &originKp, SAEVKeyPoint * originRequestPredecessorKP, SAEVKeyPoint * destinationRequestPredecessorKP);
 
     /**
      * Raw request removal method. Public for debug purposes, but should effectively never be called by an outside member
-     * @param requestId index of the request we want to remove from the route
+     * @param originKp Reference to the origin key point of the request we want to remove from the route
      */
-    void removeRequest(size_t requestId);
+    void removeRequest(SAEVKeyPoint &originKp);
 
     /**
      * Updates weight in-between request's Origin/Destination (both included) to account for the given request's weight
      * ⚠️ Execute this function *after* adding the request to the route, as it assumes the request is part of the route
-     * @param requestId ID of the request that serves as basis for iteration and weight to add
+     * @param requestOriginKeyPoint reference to the origin keypoint of the request for which we wish to remove the weight to the route
      */
-    void addRequestWeightToRoute(size_t requestId);
+    void addRequestWeightToRoute(SAEVKeyPoint &requestOriginKeyPoint);
     /**
      * Resets current weight to 0 on the request Origin/Destination key points and decreases weight on the nodes in-between by the request's weight
      * ⚠️ Execute this function *before* removing the request from the route, as it assumes the request is still part of the route
-     * @param requestId ID of the request that serves as basis for iteration and weight to remove
+     * @param requestOriginKeyPoint reference to the origin keypoint of the request for which we wish to remove the weight to the route
      */
-    void removeRequestWeightFromRoute(size_t requestId);
+    void removeRequestWeightFromRoute(SAEVKeyPoint& requestOriginKeyPoint);
 
     /**
      * Tries to insert the request origin and destination next to the given origin/destination predecessors. \n \n
@@ -70,48 +70,61 @@ public:
      * @param destinationRequestPredecessorKP Identifier/index in the route key point vector for the request origin or destination that will precede our request's destination in the route
      * @return A change list with every min/max bound change made during the tryAdd procedure and a score estimating insertion quality (lower is better)
      */
-    SAEVRouteChangelist tryAddRequest(const size_t requestId, SAEVKeyPoint * originRequestPredecessorKP, SAEVKeyPoint * destinationRequestPredecessorKP);
+    SAEVRouteChangelist tryAddRequest(size_t requestId, SAEVKeyPoint * originRequestPredecessorKP, SAEVKeyPoint * destinationRequestPredecessorKP);
+
+    /**
+     * Tries to insert the request origin and destination next to the given origin/destination predecessors. \n \n
+     * First we verify multiple constraints that don't require actually inserting the request or doing constraint propagation. \n
+     * Then we propagate our min/max bounds, iteratively rippling through every modification induced by min/max neighbour constraints or delta constraints. \n
+     * ⚠️ In case of infeasibility, tryAdd automatically reverts changes and the change list will be effectively empty, but otherwise it's the caller's responsibility to revert changes if necessary
+     * @param requestOriginKeyPoint KeyPoint reference pointing to the origin KP of the request we wish to insert
+     * @param originRequestPredecessorKP Identifier/index in the route key point vector for the request origin or destination that will precede our request's origin in the route
+     * @param destinationRequestPredecessorKP Identifier/index in the route key point vector for the request origin or destination that will precede our request's destination in the route
+     * @return A change list with every min/max bound change made during the tryAdd procedure and a score estimating insertion quality (lower is better)
+     */
+    SAEVRouteChangelist tryAddRequest(SAEVKeyPoint &requestOriginKeyPoint, SAEVKeyPoint * originRequestPredecessorKP, SAEVKeyPoint * destinationRequestPredecessorKP);
 
     /**
      * Verifies time window constraints on our request's origin/destination's projected neighbour, aka originPredecessor/destinationPredecessor and their successor.
      * There is a special case taken into account if originPredecessor and destinationPredecessor are the same KeyPoint, since then, Origin's successor would be Destination
      * ⚠️ Weight constraints are checked separately
      * ⚠️ Those checks don't modify the route => no rollback is needed at this point
-     * @param requestId Index of our request, necessary to retrieve the appropriate key points
+     * @param originKP Reference to the origin key point of our request, necessary to retrieve the appropriate key points
      * @param originNodeIndex The request's origin node index, necessary to compute travel times
      * @param destinationNodeIndex The request's destination node index, necessary to compute travel times
      * @param originPredecessor The origin's expected predecessor, aka the point after which we wish to insert our origin
      * @param destinationPredecessor The destination's expected predecessor, aka the point after which we wish to insert our destination
      * @return true iff all neighbouring time window conditions are valid at our insertion points, false otherwise
      */
-    bool doNeighbouringTWChecks(const size_t requestId, const SAEVKeyPoint *originPredecessor,
-                                const SAEVKeyPoint *destinationPredecessor);
+    bool doNeighbouringTWChecks(const SAEVKeyPoint &originKP, const SAEVKeyPoint *originPredecessor,
+                                const SAEVKeyPoint *destinationPredecessor) const;
 
     /**
      * Method called after having validated conditions not requiring request insertion. \n
      * This will effectively insert our procedure and ripple through bound changes. \n
      * If the bounds become infeasible (min > max), then the propagation stops with a changelist with score= +Infinity and changes will be immediately reverted.
      * Otherwise, it's the responsibility of this method's callers to revert changes if wanted (or to defer this responsibility to its caller)
-     * @param requestId Identifier/index in the instance's request vector for the request we wish to insert
+     * @param originKP Reference to the origin key point for the request we wish to insert
      * @param originRequestPredecessorKP Identifier/index in the route key point vector for the request origin or destination that will precede our request's origin in the route
      * @param destinationRequestPredecessorKP Identifier/index in the route key point vector for the request origin or destination that will precede our request's destination in the route
      * @return A change list with every min/max bound change made during the insert procedure and a score estimating insertion quality (lower is better)
      */
-    SAEVRouteChangelist insertRequestWithPropagation(const size_t requestId, SAEVKeyPoint * originRequestPredecessorKP, SAEVKeyPoint * destinationRequestPredecessorKP);
+    SAEVRouteChangelist insertRequestWithPropagation(SAEVKeyPoint &originKP, SAEVKeyPoint * originRequestPredecessorKP, SAEVKeyPoint * destinationRequestPredecessorKP);
 
     /**
      * Returns a score value equivalent to the detour implied by insertion of a request after the two given key point indexes.
      * The specific case of origin/destination being inserted one after another is taken into account
-     * @param requestId Identifier/index in the instance's request vector for the request we wish to insert
+     * ⚠️ This method assumes the insertion hasn't been done yet, so compute detour scores before inserting your request ⚠️
+     * @param originKP Reference to the origin key point for the request we wish to insert
      * @param originRequestPredecessorKP Identifier/index in the route key point vector for the request origin or destination that will precede our request's origin in the route
      * @param destinationRequestPredecessorKP Identifier/index in the route key point vector for the request origin or destination that will precede our request's destination in the route
      * @return
      */
-    double getDetourScore(const size_t requestId, const SAEVKeyPoint * originRequestPredecessorKP, const SAEVKeyPoint * destinationRequestPredecessorKP);
+    double getDetourScore(const SAEVKeyPoint &originKP, const SAEVKeyPoint * originRequestPredecessorKP, const SAEVKeyPoint * destinationRequestPredecessorKP);
 
-    BestInsertionQueue getBestInsertionsQueue(size_t requestId, size_t vehicleId);
-    BestInsertionQueue getBestFeasibleInsertionsQueue(size_t requestId, size_t vehicleId);
-    void getBestFeasibleInsertionsQueue(BestInsertionQueue& bestInsertionQueue, size_t requestId, size_t vehicleId);
+    BestInsertionQueue getBestInsertionsQueue(const SAEVKeyPoint &originKP, size_t vehicleId);
+    BestInsertionQueue getBestFeasibleInsertionsQueue(const SAEVKeyPoint &originKP, size_t vehicleId);
+    void getBestFeasibleInsertionsQueue(BestInsertionQueue& bestInsertionQueue, const SAEVKeyPoint &requestOriginKeyPoint, size_t vehicleId);
 
     SAEVKeyPoint& getRequestOrigin(const size_t requestId) { return _route[getRequestOriginRouteIdx(requestId)];}
     SAEVKeyPoint& getRequestDestination(const size_t requestId) { return _route[getRequestDestinationRouteIdx(requestId)];}
@@ -141,6 +154,11 @@ public:
 
     std::string to_string(size_t vehicleId);
     void exportToFile();
+
+    /**
+     * Extends the existing route to add 4*NbRequests keypoints to represent entry/exit sub-requests Origin/Destination
+     */
+    void initMultimodalKeyPoints();
 };
 
 #include "propagation/SAEVRouteChangelist.h"
diff --git a/src/routes/vehicle/propagation/SAEVRouteChangelist.cpp b/src/routes/vehicle/propagation/SAEVRouteChangelist.cpp
index 1e47d54..d2e0885 100644
--- a/src/routes/vehicle/propagation/SAEVRouteChangelist.cpp
+++ b/src/routes/vehicle/propagation/SAEVRouteChangelist.cpp
@@ -16,13 +16,13 @@ void SAEVRouteChangelist::emplace_back(SAEVRouteChange change) {
     _changelist.emplace_back(change);
 }
 
-void SAEVRouteChangelist::emplace_back(SAEVKeyPoint &kp, Bound bound, int value) {
+void SAEVRouteChangelist::emplace_back(SAEVKeyPoint &kp, Bound bound, uint value) {
     _changelist.emplace_back(kp, bound, value);
 }
 
 void SAEVRouteChangelist::applyChanges() {
     if(_status < InsertionStatus::FAILURE_PRECONDITION_TW) {
-        _routePtr->insertRequest(_requestId, _originPredecessorKP, _destinationPredecessorKP);
+        _routePtr->insertRequest(*_requestOriginKeyPoint, _originPredecessorKP, _destinationPredecessorKP);
     }
     for(SAEVRouteChange change : _changelist) {
         change.applyChange();
@@ -32,7 +32,7 @@ void SAEVRouteChangelist::applyChanges() {
 
 void SAEVRouteChangelist::revertChanges() {
     if(_status < InsertionStatus::FAILURE_PRECONDITION_TW) {
-        _routePtr->removeRequest(_requestId);
+        _routePtr->removeRequest(*_requestOriginKeyPoint);
     }
     for(SAEVRouteChange change : _changelist) {
         change.revertChange();
@@ -40,8 +40,8 @@ void SAEVRouteChangelist::revertChanges() {
     _currentStatus = InsertionStatus::CHANGELIST_REVERTED;
 }
 
-size_t SAEVRouteChangelist::getRequestId() const {
-    return _requestId;
+SAEVKeyPoint *SAEVRouteChangelist::getRequestOriginKeyPoint() const {
+    return _requestOriginKeyPoint;
 }
 
 const SAEVKeyPoint * SAEVRouteChangelist::getOriginPredecessorKP() const {
diff --git a/src/routes/vehicle/propagation/SAEVRouteChangelist.h b/src/routes/vehicle/propagation/SAEVRouteChangelist.h
index b9eae10..4541e85 100644
--- a/src/routes/vehicle/propagation/SAEVRouteChangelist.h
+++ b/src/routes/vehicle/propagation/SAEVRouteChangelist.h
@@ -29,7 +29,7 @@ public:
 private:
     //Change target info
     SAEVRoute * _routePtr{};
-    size_t _requestId{};
+    SAEVKeyPoint* _requestOriginKeyPoint{};
     size_t _vehicleId{};
     SAEVKeyPoint* _originPredecessorKP{};
     SAEVKeyPoint* _destinationPredecessorKP{};
@@ -43,17 +43,17 @@ private:
 
 public:
 
-    SAEVRouteChangelist(SAEVRoute * routePtr, size_t requestId) : _routePtr(routePtr), _requestId(requestId) {}
+    SAEVRouteChangelist(SAEVRoute * routePtr, SAEVKeyPoint *requestOriginKeyPoint) : _routePtr(routePtr), _requestOriginKeyPoint(requestOriginKeyPoint) {}
 
     /**
      * Initializes a change list to memorize every iterative modification made during constraint propagation
      * @param routePtr a pointer to the route the constraint propagation was applied on. revert/apply operations will be done on this route
-     * @param requestId The index of the request in the global request list
-     * @param originPredecessorKP The index of the request our origin will be inserted after
-     * @param destinationPredecessorKP The index of the request our destination will be inserted after
+     * @param requestOriginKeyPoint Reference to the request origin key point in the route
+     * @param originPredecessorKP Reference to the request KP our origin will be inserted after
+     * @param destinationPredecessorKP Reference to the request KP our destination will be inserted after
      */
-    explicit SAEVRouteChangelist(SAEVRoute * const routePtr, const size_t requestId, SAEVKeyPoint* originPredecessorKP, SAEVKeyPoint* destinationPredecessorKP, InsertionStatus status)
-    : _routePtr(routePtr), _requestId(requestId), _originPredecessorKP(originPredecessorKP), _destinationPredecessorKP(destinationPredecessorKP), _status(status), _currentStatus(status) {};
+    explicit SAEVRouteChangelist(SAEVRoute * const routePtr, SAEVKeyPoint *requestOriginKeyPoint, SAEVKeyPoint* originPredecessorKP, SAEVKeyPoint* destinationPredecessorKP, InsertionStatus status)
+    : _routePtr(routePtr), _requestOriginKeyPoint(requestOriginKeyPoint), _originPredecessorKP(originPredecessorKP), _destinationPredecessorKP(destinationPredecessorKP), _status(status), _currentStatus(status) {};
 
 
     /**
@@ -62,10 +62,8 @@ public:
     [[nodiscard]] SAEVRoute * getRoutePtr() const;
 
     [[nodiscard]] const std::vector<SAEVRouteChange> &getChangelist() const;
-    /**
-     * @return The index of the request that we want to insert to a route
-     */
-    [[nodiscard]] size_t getRequestId() const;
+
+    SAEVKeyPoint *getRequestOriginKeyPoint() const;
 
     [[nodiscard]] size_t getVehicleId() const;
     void setVehicleId(size_t vehicleId);
@@ -99,7 +97,7 @@ public:
 
     void push_back(SAEVRouteChange change);
     void emplace_back(SAEVRouteChange change);
-    void emplace_back(SAEVKeyPoint& kp, Bound bound, int value);
+    void emplace_back(SAEVKeyPoint& kp, Bound bound, uint value);
 
     /**
      * Inserts the request associated to this changelist to the given route and iteratively applies every change memorized in this changelist.
-- 
GitLab


From 1e1d3abbc4e2253feedb9aad6b8c084de196b30a Mon Sep 17 00:00:00 2001
From: Romain BERNARD <romain.bernard@uca.fr>
Date: Fri, 23 Aug 2024 11:57:06 +0200
Subject: [PATCH 196/327] clang/sonarlint issue fixes

---
 src/instance/requests/Request.h           | 1 +
 src/routes/vehicle/BestRequestInsertion.h | 2 +-
 src/routes/vehicle/SAEVKeyPoint.cpp       | 6 +++---
 src/routes/vehicle/SAEVKeyPoint.h         | 6 +++---
 4 files changed, 8 insertions(+), 7 deletions(-)

diff --git a/src/instance/requests/Request.h b/src/instance/requests/Request.h
index 51db4fd..0dab0c7 100644
--- a/src/instance/requests/Request.h
+++ b/src/instance/requests/Request.h
@@ -43,6 +43,7 @@ private:
      */
     double _transitTravelTimeRatio{Constants::BASE_TRANSIT_TRAVEL_TIME_RATIO};
 public:
+    Request() = default;
     Request(const size_t departureNodeIndex, const size_t arrivalNodeIndex,
             const TimeWindow &arrivalTw, const uint deltaTime, const uint weight);
     Request(const size_t departureNodeIndex, const size_t arrivalNodeIndex, const TimeWindow &arrivalTw,
diff --git a/src/routes/vehicle/BestRequestInsertion.h b/src/routes/vehicle/BestRequestInsertion.h
index 1af540c..02184d0 100644
--- a/src/routes/vehicle/BestRequestInsertion.h
+++ b/src/routes/vehicle/BestRequestInsertion.h
@@ -21,7 +21,7 @@ public:
     /**
      * Default constructor to allow pre-sizing containers
      */
-    BestRequestInsertion() {};
+    BestRequestInsertion() = default;
     /**
      * Constructs a BestRequestInsertion object, containing Origin/Destination insertion indexes and the score associated
      * @param originInsertionKP Index of insertion for the origin of the request in the route
diff --git a/src/routes/vehicle/SAEVKeyPoint.cpp b/src/routes/vehicle/SAEVKeyPoint.cpp
index fff28f4..c9f7696 100644
--- a/src/routes/vehicle/SAEVKeyPoint.cpp
+++ b/src/routes/vehicle/SAEVKeyPoint.cpp
@@ -24,11 +24,11 @@ void SAEVKeyPoint::setSuccessor(SAEVKeyPoint *successor) {
     _successor = successor;
 }
 
-int SAEVKeyPoint::getCurrentOccupation() const {
+uint SAEVKeyPoint::getCurrentOccupation() const {
     return _currentOccupation;
 }
 
-void SAEVKeyPoint::setCurrentOccupation(int currentCapacity) {
+void SAEVKeyPoint::setCurrentOccupation(uint currentCapacity) {
     _currentOccupation = currentCapacity;
 }
 
@@ -105,7 +105,7 @@ void SAEVKeyPoint::setCounterpart(SAEVKeyPoint *counterpart) {
     _counterpart = counterpart;
 }
 
-SAEVKeyPoint::SAEVKeyPoint(int depotNodeIdx) : KeyPoint(depotNodeIdx) {
+SAEVKeyPoint::SAEVKeyPoint(size_t depotNodeIdx) : KeyPoint(depotNodeIdx) {
     _isDepot = true;
     setNodeIndex(depotNodeIdx);
 }
diff --git a/src/routes/vehicle/SAEVKeyPoint.h b/src/routes/vehicle/SAEVKeyPoint.h
index 8725687..394444f 100644
--- a/src/routes/vehicle/SAEVKeyPoint.h
+++ b/src/routes/vehicle/SAEVKeyPoint.h
@@ -30,7 +30,7 @@ public:
     /**
      * Depot KP initialization with [0;max] time windows and a depot node index
      */
-    explicit SAEVKeyPoint(int depotNodeIdx);
+    explicit SAEVKeyPoint(size_t depotNodeIdx);
     /**
      * SAEV KP initialization
      * @param graph the instance's graph, used to get shortest path and estimate start time windows relative to distances
@@ -45,8 +45,8 @@ public:
     [[nodiscard]] SAEVKeyPoint *getSuccessor() const;
     void setSuccessor(SAEVKeyPoint *successor);
 
-    [[nodiscard]] int getCurrentOccupation() const;
-    void setCurrentOccupation(int currentCapacity);
+    [[nodiscard]] uint getCurrentOccupation() const;
+    void setCurrentOccupation(uint currentCapacity);
 
     [[nodiscard]] uint getMinTw() const;
     void setMinTw(uint minTw);
-- 
GitLab


From 943e078e854b760461429f5b40ad19916fc1995e Mon Sep 17 00:00:00 2001
From: Romain BERNARD <romain.bernard@uca.fr>
Date: Fri, 23 Aug 2024 12:03:41 +0200
Subject: [PATCH 197/327] add functions to create and access entry/exit
 subrequests from a given baseRequestId (TODO: allow access to entry/exit KP
 from the base request KP ?)

---
 src/routes/vehicle/SAEVRoute.cpp | 13 +++++++++++++
 src/routes/vehicle/SAEVRoute.h   | 14 ++++++++++++++
 2 files changed, 27 insertions(+)

diff --git a/src/routes/vehicle/SAEVRoute.cpp b/src/routes/vehicle/SAEVRoute.cpp
index 07356ce..bd7a128 100644
--- a/src/routes/vehicle/SAEVRoute.cpp
+++ b/src/routes/vehicle/SAEVRoute.cpp
@@ -37,6 +37,19 @@ SAEVRoute::SAEVRoute(const Graph& graph, const std::vector<Request>& requestList
     }
 }
 
+void SAEVRoute::initMultimodalKeyPoints() {
+    _route.resize(_nbRequest * 8); // 2*NbRequests O/D Keypoints, 2*NbRequests O/D vehicle depot Keypoints
+                                            // 2*NbRequests O/D Bus entry Keypoints, 2*NbRequests O/D Bus exit Keypoints
+
+    for (size_t i = 0; i < _nbRequest; ++i) {
+        //Link Origins and Destinations for entry/exit subrequests
+        getEntrySubRequestOrigin(i).setCounterpart(&getEntrySubRequestDestination(i));
+        getEntrySubRequestDestination(i).setCounterpart(&getEntrySubRequestOrigin(i));
+        getExitSubRequestOrigin(i).setCounterpart(&getExitSubRequestDestination(i));
+        getExitSubRequestDestination(i).setCounterpart(&getExitSubRequestOrigin(i));
+    }
+}
+
 void SAEVRoute::insertRequest(SAEVKeyPoint &originKp, SAEVKeyPoint * originRequestPredecessorKP, SAEVKeyPoint * destinationRequestPredecessorKP) {
     SAEVKeyPoint* destinationKp = originKp.getCounterpart();
 
diff --git a/src/routes/vehicle/SAEVRoute.h b/src/routes/vehicle/SAEVRoute.h
index 2b560cd..65fb5bd 100644
--- a/src/routes/vehicle/SAEVRoute.h
+++ b/src/routes/vehicle/SAEVRoute.h
@@ -142,6 +142,20 @@ public:
     [[nodiscard]] size_t getOriginDepotNodeIdx(const size_t vehicleId) const { return _route[getOriginDepotRouteIdx(vehicleId)].getNodeIndex();}
     [[nodiscard]] size_t getDestinationDepotNodeIdx(const size_t vehicleId) const { return _route[getDestinationDepotRouteIdx(vehicleId)].getNodeIndex();}
 
+    [[nodiscard]] size_t getEntrySubRequestOriginRouteIdx(const size_t requestId) const { return _nbRequest * 3 + requestId * 2;}
+    [[nodiscard]] size_t getEntrySubRequestDestinationRouteIdx(const size_t requestId) const { return _nbRequest * 3 + requestId * 2 + 1;}
+    [[nodiscard]] SAEVKeyPoint& getEntrySubRequestOrigin(const size_t requestId) { return _route[getEntrySubRequestOriginRouteIdx(requestId)];}
+    [[nodiscard]] SAEVKeyPoint& getEntrySubRequestDestination(const size_t requestId) { return _route[getEntrySubRequestDestinationRouteIdx(requestId)];}
+    [[nodiscard]] size_t getEntrySubRequestOriginNodeIdx(const size_t requestId) const { return _route[getEntrySubRequestOriginRouteIdx(requestId)].getNodeIndex();}
+    [[nodiscard]] size_t getEntrySubRequestDestinationNodeIdx(const size_t requestId) const { return _route[getEntrySubRequestDestinationRouteIdx(requestId)].getNodeIndex();}
+
+    [[nodiscard]] size_t getExitSubRequestOriginRouteIdx(const size_t requestId) const { return _nbRequest * 4 + requestId * 2;}
+    [[nodiscard]] size_t getExitSubRequestDestinationRouteIdx(const size_t requestId) const { return _nbRequest * 4 + requestId * 2 + 1;}
+    [[nodiscard]] SAEVKeyPoint& getExitSubRequestOrigin(const size_t requestId) { return _route[getExitSubRequestOriginRouteIdx(requestId)];}
+    [[nodiscard]] SAEVKeyPoint& getExitSubRequestDestination(const size_t requestId) { return _route[getExitSubRequestDestinationRouteIdx(requestId)];}
+    [[nodiscard]] size_t getExitSubRequestOriginNodeIdx(const size_t requestId) const { return _route[getExitSubRequestOriginRouteIdx(requestId)].getNodeIndex();}
+    [[nodiscard]] size_t getExitSubRequestDestinationNodeIdx(const size_t requestId) const { return _route[getExitSubRequestDestinationRouteIdx(requestId)].getNodeIndex();}
+
     [[nodiscard]] size_t getLastActiveVehicleId() const { return _lastActiveVehicleId; }
     void setLastActiveVehicleId(size_t lastActiveVehicleId) { _lastActiveVehicleId = lastActiveVehicleId; }
 
-- 
GitLab


From 85ac4f9b37d10a85b13ffe5060ca0468b25b6022 Mon Sep 17 00:00:00 2001
From: Romain BERNARD <romain.bernard@uca.fr>
Date: Fri, 23 Aug 2024 12:04:51 +0200
Subject: [PATCH 198/327] rebase fix duplicate constructor

---
 src/algorithm/Multimodal/Heuristics/SimpleModularHeuristic.h | 2 --
 1 file changed, 2 deletions(-)

diff --git a/src/algorithm/Multimodal/Heuristics/SimpleModularHeuristic.h b/src/algorithm/Multimodal/Heuristics/SimpleModularHeuristic.h
index c2bebe2..4334493 100644
--- a/src/algorithm/Multimodal/Heuristics/SimpleModularHeuristic.h
+++ b/src/algorithm/Multimodal/Heuristics/SimpleModularHeuristic.h
@@ -16,8 +16,6 @@ class SimpleModularHeuristic {
 private:
     const Graph* _graph{nullptr};
     SAEVRoute* _route{nullptr};
-public:
-    SimpleModularHeuristic(const Graph *graph, SAEVRoute *route) : _graph(graph), _route(route) {}
 
 //Public interface to interact with the modular heuristic
 public:
-- 
GitLab


From 904da47962ff85d061219f667a1e56374e633e4f Mon Sep 17 00:00:00 2001
From: Romain BERNARD <romain.bernard@uca.fr>
Date: Fri, 23 Aug 2024 12:05:05 +0200
Subject: [PATCH 199/327] update googletest

---
 test/lib/googletest | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/test/lib/googletest b/test/lib/googletest
index a7f443b..ff233bd 160000
--- a/test/lib/googletest
+++ b/test/lib/googletest
@@ -1 +1 @@
-Subproject commit a7f443b80b105f940225332ed3c31f2790092f47
+Subproject commit ff233bdd4cac0a0bf6e5cd45bda3406814cb2796
-- 
GitLab


From 494767921bcf841a34d6c2e32638962e479b6903 Mon Sep 17 00:00:00 2001
From: Romain BERNARD <romain.bernard@uca.fr>
Date: Fri, 23 Aug 2024 12:05:40 +0200
Subject: [PATCH 200/327] update constraint propagation debug test to have more
 cases handled

---
 test/src/ConstraintPropagationDebug.cpp | 7 +++++--
 1 file changed, 5 insertions(+), 2 deletions(-)

diff --git a/test/src/ConstraintPropagationDebug.cpp b/test/src/ConstraintPropagationDebug.cpp
index 9ee6338..6a76639 100644
--- a/test/src/ConstraintPropagationDebug.cpp
+++ b/test/src/ConstraintPropagationDebug.cpp
@@ -9,6 +9,7 @@
 #include "../../src/instance/Instance.h"
 #include "../../src/routes/vehicle/SAEVRoute.h"
 #include "../../src/utils/Instance Generation/Requests/RequestsGenerator.h"
+#include "../../src/ShortestPath/Vehicle/VehicleShortestPathCalculation.h"
 
 TEST(ConstraintPropagationDebug, DebugBaseInstance) {
     std::string instancesPath = "../../resources/test/instances/Constraint Propagation/";
@@ -74,7 +75,7 @@ TEST(ConstraintPropagationDebug, DebugInstanceAlain) {
     //Parse graph
     Graph graphFromSingleFile(instancesPath + instanceFolder + graphDatFile);
     std::vector<Request> requests = Request::getRequestsFromFile(instancesPath + instanceFolder + requestsDatFile, graphFromSingleFile);
-
+    VehicleShortestPathCalculation::computeAndUpdateShortestPathsForGraph(graphFromSingleFile);
     //Init instance
     Instance instance(requests,graphFromSingleFile,4);
     SAEVRoute routesContainer(graphFromSingleFile, requests);
@@ -82,8 +83,10 @@ TEST(ConstraintPropagationDebug, DebugInstanceAlain) {
     //Vehicle 1 insertions
     routesContainer.tryAddRequest(0,&routesContainer.getOriginDepot(0),&routesContainer.getOriginDepot(0));
     routesContainer.tryAddRequest(1, &routesContainer.getRequestOrigin(0), &routesContainer.getRequestOrigin(0));
-    SAEVRouteChangelist cl = routesContainer.tryAddRequest(2, &routesContainer.getRequestOrigin(1),
+    SAEVRouteChangelist clFailPrecondition = routesContainer.tryAddRequest(2, &routesContainer.getRequestOrigin(1),
                                                            &routesContainer.getRequestDestination(1));
+    SAEVRouteChangelist clSuccess = routesContainer.tryAddRequest(2, &routesContainer.getRequestOrigin(1),
+                                                           &routesContainer.getRequestDestination(0));
 
     //Vehicle 2 insertions
     routesContainer.tryAddRequest(5,&routesContainer.getOriginDepot(1),&routesContainer.getOriginDepot(1));
-- 
GitLab


From 7b13c03a833418b5ba27b7af43dcf8243be15239 Mon Sep 17 00:00:00 2001
From: Romain BERNARD <romain.bernard@uca.fr>
Date: Fri, 23 Aug 2024 14:12:16 +0200
Subject: [PATCH 201/327] fix best insertions heuristic post refactor

---
 .../Heuristics/BestInsertionHeuristic.cpp     | 22 +++++++++----------
 .../DARP/Heuristics/BestInsertionHeuristic.h  | 14 ++++++------
 2 files changed, 18 insertions(+), 18 deletions(-)

diff --git a/src/algorithm/DARP/Heuristics/BestInsertionHeuristic.cpp b/src/algorithm/DARP/Heuristics/BestInsertionHeuristic.cpp
index 3ed37a6..ae24c0a 100644
--- a/src/algorithm/DARP/Heuristics/BestInsertionHeuristic.cpp
+++ b/src/algorithm/DARP/Heuristics/BestInsertionHeuristic.cpp
@@ -11,22 +11,22 @@
 #define DEBUG_MSG(str) do { } while ( false )
 #endif
 
-SAEVRouteChangelist BestInsertionHeuristic::tryVehicleBestInsertion(size_t requestId, size_t vehicleId, SAEVRoute& route) {
-    BestInsertionQueue bestInsertionsQueue = route.getBestFeasibleInsertionsQueue(requestId, vehicleId);
+SAEVRouteChangelist BestInsertionHeuristic::tryVehicleBestInsertion(SAEVKeyPoint &requestKp, size_t vehicleId, SAEVRoute& route) {
+    BestInsertionQueue bestInsertionsQueue = route.getBestFeasibleInsertionsQueue(requestKp, vehicleId);
     return tryVehicleBestInsertion(bestInsertionsQueue, route);
 }
 
 SAEVRouteChangelist BestInsertionHeuristic::tryVehicleBestInsertion(BestInsertionQueue& bestInsertionsQueue, SAEVRoute& route) {
     bool bestInsertionFound = false;
     BestRequestInsertion currentBestInsertion;
-    size_t requestId = bestInsertionsQueue.getRequestId();
-    SAEVRouteChangelist lastInsertionChangelist(&route, requestId);
+    SAEVKeyPoint & requestKp = bestInsertionsQueue.getOriginKp();
+    SAEVRouteChangelist lastInsertionChangelist(&route, &requestKp);
 
     DEBUG_MSG("Trying to insert request " + std::to_string(requestId) + " in vehicle " + std::to_string(vehicleId) + " queue size : " + std::to_string(bestInsertionsQueue.size()));
     while(!bestInsertionsQueue.empty() && !bestInsertionFound) {
         currentBestInsertion = bestInsertionsQueue.topAndPop();
         DEBUG_MSG("Trying insertion " + currentBestInsertion.to_string() + ", remaining : " + std::to_string(bestInsertionsQueue.size()));
-        lastInsertionChangelist = route.tryAddRequest(requestId,currentBestInsertion.getOriginInsertionKp(),currentBestInsertion.getDestinationInsertionKp());
+        lastInsertionChangelist = route.tryAddRequest(requestKp,currentBestInsertion.getOriginInsertionKp(),currentBestInsertion.getDestinationInsertionKp());
         //If insertion worked, signal it, otherwise revert changes
         if(lastInsertionChangelist.getStatus() == SAEVRouteChangelist::InsertionStatus::SUCCESS) {
             DEBUG_MSG("\tBest valid insertion found !\n\t\t" + currentBestInsertion.to_string());
@@ -40,12 +40,12 @@ SAEVRouteChangelist BestInsertionHeuristic::tryVehicleBestInsertion(BestInsertio
     return lastInsertionChangelist;
 }
 
-size_t BestInsertionHeuristic::doBestRequestInsertionForRoute(size_t requestId, SAEVRoute& route) {
+size_t BestInsertionHeuristic::doBestRequestInsertionForRoute(SAEVKeyPoint &requestKp, SAEVRoute& route) {
     size_t vehicleId = 0;
     bool insertionSuccess{false};
     //Iteratively try inserting in every active vehicle and the first inactive vehicle
     do {
-        insertionSuccess = tryVehicleBestInsertion(requestId, vehicleId, route).success();
+        insertionSuccess = tryVehicleBestInsertion(requestKp, vehicleId, route).success();
     } while(!insertionSuccess && ++vehicleId <= route.getLastActiveVehicleId() + 1);
 
     //Update last active vehicle ID
@@ -57,13 +57,13 @@ size_t BestInsertionHeuristic::doBestRequestInsertionForRoute(size_t requestId,
     return vehicleId;
 }
 
-SAEVRouteChangelist BestInsertionHeuristic::tryBestRequestInsertionInActiveVehicle(size_t requestId, SAEVRoute &route) {
+SAEVRouteChangelist BestInsertionHeuristic::tryBestRequestInsertionInActiveVehicle(SAEVKeyPoint &requestKp, SAEVRoute &route) {
     size_t vehicleId = 0;
-    BestInsertionQueue bestInsertions{requestId};
+    BestInsertionQueue bestInsertions{requestKp};
     //Iteratively try inserting in every active vehicle and the first inactive vehicle
     while(++vehicleId <= route.getLastActiveVehicleId() + 1) {
-        route.getBestFeasibleInsertionsQueue(bestInsertions, requestId, vehicleId);
+        route.getBestFeasibleInsertionsQueue(bestInsertions, requestKp, vehicleId);
     }
 
-    return tryVehicleBestInsertion(requestId, vehicleId, route);
+    return tryVehicleBestInsertion(requestKp, vehicleId, route);
 }
diff --git a/src/algorithm/DARP/Heuristics/BestInsertionHeuristic.h b/src/algorithm/DARP/Heuristics/BestInsertionHeuristic.h
index 95001b7..05d4a23 100644
--- a/src/algorithm/DARP/Heuristics/BestInsertionHeuristic.h
+++ b/src/algorithm/DARP/Heuristics/BestInsertionHeuristic.h
@@ -13,29 +13,29 @@ class BestInsertionHeuristic {
 public:
     /**
      * Automatically inserts the given request in a vehicle, potentially creating a new one if no active vehicle works
-     * @param requestId ID of the request to insert in the route
+     * @param requestKp ID of the request to insert in the route
      * @param route the route structure in which the request will be inserted
      * @return ID of the vehicle in which the request has been
      */
-    static size_t doBestRequestInsertionForRoute(size_t requestId, SAEVRoute& route);
+    static size_t doBestRequestInsertionForRoute(SAEVKeyPoint &requestKp, SAEVRoute& route);
     /**
      * Iteratively attempts insertions in the currently active vehicles in two steps :
      * 1) creates a global best insertion list for all active vehicles
      * 2) tries every insertions from best to worst
      * 3) return the ID of the vehicle in which the request was inserted if an active vehicle was viable, return the most favourable inactive vehicle's ID otherwise
-     * @param requestId ID of the request to insert in the route
+     * @param requestKp ID of the request to insert in the route
      * @param route the route structure in which the request will be inserted
      * @return The ID of the active vehicle in which our request was inserted, or the ID of the most favourable inactive vehicle
      */
-    static SAEVRouteChangelist tryBestRequestInsertionInActiveVehicle(size_t requestId, SAEVRoute& route);
+    static SAEVRouteChangelist tryBestRequestInsertionInActiveVehicle(SAEVKeyPoint &requestKp, SAEVRoute& route);
     /**
      * Iteratively tests best insertions wrt scoring function (detour) in the given vehicle and route
-     * @param requestId ID of the request to insert in the vehicle
-     * @param requestId ID of the vehicle in which to insert the vehicle
+     * @param requestKp ID of the request to insert in the vehicle
+     * @param requestKp ID of the vehicle in which to insert the vehicle
      * @param route
      * @return true iff the request was inserted in the vehicle, false if no best insertion yielded a possible insertion
      */
-    static SAEVRouteChangelist tryVehicleBestInsertion(size_t requestId, size_t vehicleId, SAEVRoute& route);
+    static SAEVRouteChangelist tryVehicleBestInsertion(SAEVKeyPoint &requestKp, size_t vehicleId, SAEVRoute& route);
     /**
      * Tries the best insertions
      * @param bestInsertionsQueue
-- 
GitLab


From 729857ba5ae6377556b0f8a9cbdda362cf42330a Mon Sep 17 00:00:00 2001
From: Romain BERNARD <romain.bernard@uca.fr>
Date: Fri, 23 Aug 2024 17:34:35 +0200
Subject: [PATCH 202/327] best insertions fixes from testing

---
 .../Heuristics/BestInsertionHeuristic.cpp     |  2 +-
 src/routes/vehicle/BestInsertionQueue.h       | 10 ++++----
 src/routes/vehicle/SAEVRoute.cpp              | 24 +++++++++++++++++--
 src/routes/vehicle/SAEVRoute.h                |  6 +++--
 4 files changed, 32 insertions(+), 10 deletions(-)

diff --git a/src/algorithm/DARP/Heuristics/BestInsertionHeuristic.cpp b/src/algorithm/DARP/Heuristics/BestInsertionHeuristic.cpp
index ae24c0a..22d25b4 100644
--- a/src/algorithm/DARP/Heuristics/BestInsertionHeuristic.cpp
+++ b/src/algorithm/DARP/Heuristics/BestInsertionHeuristic.cpp
@@ -36,7 +36,7 @@ SAEVRouteChangelist BestInsertionHeuristic::tryVehicleBestInsertion(BestInsertio
             lastInsertionChangelist.revertChanges();
         }
     }
-    //FIXME : use a pointer and return it via dereferencing ? Create a dummy constructor ? (I think I'll go with the latter)
+
     return lastInsertionChangelist;
 }
 
diff --git a/src/routes/vehicle/BestInsertionQueue.h b/src/routes/vehicle/BestInsertionQueue.h
index 9c42242..e28bb71 100644
--- a/src/routes/vehicle/BestInsertionQueue.h
+++ b/src/routes/vehicle/BestInsertionQueue.h
@@ -11,15 +11,15 @@
 
 class BestInsertionQueue : public std::priority_queue<BestRequestInsertion, std::vector<BestRequestInsertion>, std::greater<>> {
 private:
-    const SAEVKeyPoint &_originKP;
+    SAEVKeyPoint &_originKP;
     size_t _vehicleId{std::numeric_limits<size_t>::max()};
 
 public:
-    explicit BestInsertionQueue(const SAEVKeyPoint &originKP) : _originKP(originKP) {}
+    explicit BestInsertionQueue(SAEVKeyPoint &originKP) : _originKP(originKP) {}
 
-    BestInsertionQueue(const SAEVKeyPoint &originKP, size_t vehicleId) : _originKP(originKP), _vehicleId(vehicleId) {}
+    BestInsertionQueue(SAEVKeyPoint &originKP, size_t vehicleId) : _originKP(originKP), _vehicleId(vehicleId) {}
 
-    BestInsertionQueue(const SAEVKeyPoint &originKP, size_t vehicleId, size_t nbRequests) : BestInsertionQueue(originKP, vehicleId) {
+    BestInsertionQueue(SAEVKeyPoint &originKP, size_t vehicleId, size_t nbRequests) : BestInsertionQueue(originKP, vehicleId) {
         c.reserve(nbRequests^2);
     }
 
@@ -27,7 +27,7 @@ public:
         return _vehicleId;
     }
 
-    [[nodiscard]] const SAEVKeyPoint &getOriginKp() const {
+    [[nodiscard]] SAEVKeyPoint &getOriginKp() const {
         return _originKP;
     }
 
diff --git a/src/routes/vehicle/SAEVRoute.cpp b/src/routes/vehicle/SAEVRoute.cpp
index bd7a128..59b7ba0 100644
--- a/src/routes/vehicle/SAEVRoute.cpp
+++ b/src/routes/vehicle/SAEVRoute.cpp
@@ -376,7 +376,17 @@ bool SAEVRoute::checkRouteTimeWindows(size_t vehicleId) {
  * @param vehicleId The ID of the vehicle in which we look for new best insertions
  * @return The created BestInsertionQueue filled with the best insertions for the given request and vehicle IDs
  */
-BestInsertionQueue SAEVRoute::getBestInsertionsQueue(const SAEVKeyPoint &originKP, size_t vehicleId) {
+BestInsertionQueue SAEVRoute::getBestInsertionsQueue(size_t requestId, size_t vehicleId) {
+    return getBestInsertionsQueue(getRequestOrigin(requestId), vehicleId);
+}
+
+/** TODO: move to BestInsertionQueue class with a route parameter ?
+ * Initializes a BestInsertionQueue to guide the best insertion heuristic
+ * @param requestOriginKeyPoint Reference to the origin key point
+ * @param vehicleId The ID of the vehicle in which we look for new best insertions
+ * @return The created BestInsertionQueue filled with the best insertions for the given request and vehicle IDs
+ */
+BestInsertionQueue SAEVRoute::getBestInsertionsQueue(SAEVKeyPoint &originKP, size_t vehicleId) {
     BestInsertionQueue bestInsertionQueue(originKP, vehicleId, _nbRequest ^ 2);
 
     //Init variables used during iteration
@@ -400,13 +410,23 @@ BestInsertionQueue SAEVRoute::getBestInsertionsQueue(const SAEVKeyPoint &originK
     return bestInsertionQueue;
 }
 
+/**
+ * Initializes a BestInsertionQueue to guide the best insertion heuristic while checking neighbouring TW checks
+ * @param requestId The ID of the base request for which we search best insertions
+ * @param vehicleId The ID of the vehicle in which we look for new best insertions
+ * @return The created BestInsertionQueue filled with the best insertions for the given request and vehicle IDs
+ */
+BestInsertionQueue SAEVRoute::getBestFeasibleInsertionsQueue(size_t requestId, size_t vehicleId) {
+    return getBestFeasibleInsertionsQueue(getRequestOrigin(requestId), vehicleId);
+}
+
 /**
  * Initializes a BestInsertionQueue to guide the best insertion heuristic while checking neighbouring TW checks
  * @param requestOriginKeyPoint Reference to the origin key point of the request for which we search best insertions
  * @param vehicleId The ID of the vehicle in which we look for new best insertions
  * @return The created BestInsertionQueue filled with the best insertions for the given request and vehicle IDs
  */
-BestInsertionQueue SAEVRoute::getBestFeasibleInsertionsQueue(const SAEVKeyPoint &originKP, size_t vehicleId) {
+BestInsertionQueue SAEVRoute::getBestFeasibleInsertionsQueue(SAEVKeyPoint &originKP, size_t vehicleId) {
     BestInsertionQueue bestInsertionQueue(originKP, vehicleId, _nbRequest ^ 2);
     getBestFeasibleInsertionsQueue(bestInsertionQueue, originKP, vehicleId);
     return bestInsertionQueue;
diff --git a/src/routes/vehicle/SAEVRoute.h b/src/routes/vehicle/SAEVRoute.h
index 65fb5bd..1d4abe1 100644
--- a/src/routes/vehicle/SAEVRoute.h
+++ b/src/routes/vehicle/SAEVRoute.h
@@ -122,8 +122,10 @@ public:
      */
     double getDetourScore(const SAEVKeyPoint &originKP, const SAEVKeyPoint * originRequestPredecessorKP, const SAEVKeyPoint * destinationRequestPredecessorKP);
 
-    BestInsertionQueue getBestInsertionsQueue(const SAEVKeyPoint &originKP, size_t vehicleId);
-    BestInsertionQueue getBestFeasibleInsertionsQueue(const SAEVKeyPoint &originKP, size_t vehicleId);
+    BestInsertionQueue getBestInsertionsQueue(size_t requestId, size_t vehicleId);
+    BestInsertionQueue getBestInsertionsQueue(SAEVKeyPoint &originKP, size_t vehicleId);
+    BestInsertionQueue getBestFeasibleInsertionsQueue(size_t requestId, size_t vehicleId);
+    BestInsertionQueue getBestFeasibleInsertionsQueue(SAEVKeyPoint &originKP, size_t vehicleId);
     void getBestFeasibleInsertionsQueue(BestInsertionQueue& bestInsertionQueue, const SAEVKeyPoint &requestOriginKeyPoint, size_t vehicleId);
 
     SAEVKeyPoint& getRequestOrigin(const size_t requestId) { return _route[getRequestOriginRouteIdx(requestId)];}
-- 
GitLab


From d87946c366bcb8d298f8713a17f4140ce2bdc07b Mon Sep 17 00:00:00 2001
From: Romain BERNARD <romain.bernard@uca.fr>
Date: Fri, 23 Aug 2024 17:40:16 +0200
Subject: [PATCH 203/327] fix test to stop using copy constructors due to using
 a reference in insertion queues

---
 test/src/BestInsertionHeuristicDebug.cpp | 18 +++++++++---------
 1 file changed, 9 insertions(+), 9 deletions(-)

diff --git a/test/src/BestInsertionHeuristicDebug.cpp b/test/src/BestInsertionHeuristicDebug.cpp
index e06145d..9090967 100644
--- a/test/src/BestInsertionHeuristicDebug.cpp
+++ b/test/src/BestInsertionHeuristicDebug.cpp
@@ -61,23 +61,23 @@ TEST(BestInsertionQueueDebug, DebugInstanceAlain) {
     //Vehicle 1 insertions
     BestInsertionQueue biQueue = routesContainer.getBestInsertionsQueue(0,0);
     routesContainer.tryAddRequest(0,&routesContainer.getOriginDepot(0),&routesContainer.getOriginDepot(0));
-    biQueue = routesContainer.getBestFeasibleInsertionsQueue(1,0);
+    routesContainer.getBestFeasibleInsertionsQueue(1,0);
     routesContainer.tryAddRequest(1, &routesContainer.getRequestOrigin(0), &routesContainer.getRequestOrigin(0));
-    biQueue = routesContainer.getBestFeasibleInsertionsQueue(2,0);
+    routesContainer.getBestFeasibleInsertionsQueue(2,0);
     SAEVRouteChangelist cl = routesContainer.tryAddRequest(2, &routesContainer.getRequestOrigin(1),
                                                            &routesContainer.getRequestDestination(1));
-    biQueue = routesContainer.getBestFeasibleInsertionsQueue(3,0);
+    routesContainer.getBestFeasibleInsertionsQueue(3,0);
 
     //Vehicle 2 insertions
-    biQueue = routesContainer.getBestFeasibleInsertionsQueue(5,1);
+    routesContainer.getBestFeasibleInsertionsQueue(5,1);
     routesContainer.tryAddRequest(5,&routesContainer.getOriginDepot(1),&routesContainer.getOriginDepot(1));
-    biQueue = routesContainer.getBestFeasibleInsertionsQueue(4,1);
+    routesContainer.getBestFeasibleInsertionsQueue(4,1);
     routesContainer.tryAddRequest(4,&routesContainer.getOriginDepot(1), &routesContainer.getRequestDestination(5));
-    biQueue = routesContainer.getBestFeasibleInsertionsQueue(3,1);
+    routesContainer.getBestFeasibleInsertionsQueue(3,1);
     routesContainer.tryAddRequest(3,&routesContainer.getOriginDepot(1), &routesContainer.getRequestOrigin(4));
-    biQueue = routesContainer.getBestFeasibleInsertionsQueue(0,1);
-    biQueue = routesContainer.getBestFeasibleInsertionsQueue(1,1);
-    biQueue = routesContainer.getBestFeasibleInsertionsQueue(2,1);
+    routesContainer.getBestFeasibleInsertionsQueue(0,1);
+    routesContainer.getBestFeasibleInsertionsQueue(1,1);
+    routesContainer.getBestFeasibleInsertionsQueue(2,1);
 }
 
 TEST(BestInsertionPerVehicleHeuristicDebug, DebugInstanceAlain) {
-- 
GitLab


From cb8cba6bc66498ae802c0ea3af39d73b75797f2e Mon Sep 17 00:00:00 2001
From: Romain BERNARD <romain.bernard@uca.fr>
Date: Fri, 23 Aug 2024 18:11:47 +0200
Subject: [PATCH 204/327] fix insertion in case of new vehicle creation

---
 src/algorithm/DARP/Heuristics/BestInsertionHeuristic.cpp | 1 +
 1 file changed, 1 insertion(+)

diff --git a/src/algorithm/DARP/Heuristics/BestInsertionHeuristic.cpp b/src/algorithm/DARP/Heuristics/BestInsertionHeuristic.cpp
index 22d25b4..99fe933 100644
--- a/src/algorithm/DARP/Heuristics/BestInsertionHeuristic.cpp
+++ b/src/algorithm/DARP/Heuristics/BestInsertionHeuristic.cpp
@@ -51,6 +51,7 @@ size_t BestInsertionHeuristic::doBestRequestInsertionForRoute(SAEVKeyPoint &requ
     //Update last active vehicle ID
     if(vehicleId > route.getLastActiveVehicleId()) {
         route.setLastActiveVehicleId(vehicleId);
+        tryVehicleBestInsertion(requestKp, vehicleId, route);
         DEBUG_MSG("NEW VEHICLE CREATED, ID :" + std::to_string(vehicleId));
     }
 
-- 
GitLab


From 5ae9c40380272857e72e3893940d9c745884f1ff Mon Sep 17 00:00:00 2001
From: Romain BERNARD <romain.bernard@uca.fr>
Date: Fri, 23 Aug 2024 18:12:23 +0200
Subject: [PATCH 205/327] add new vehicle insertion to API

---
 src/routes/vehicle/SAEVRoute.cpp | 8 ++++++++
 src/routes/vehicle/SAEVRoute.h   | 5 +++++
 2 files changed, 13 insertions(+)

diff --git a/src/routes/vehicle/SAEVRoute.cpp b/src/routes/vehicle/SAEVRoute.cpp
index 59b7ba0..1220ab8 100644
--- a/src/routes/vehicle/SAEVRoute.cpp
+++ b/src/routes/vehicle/SAEVRoute.cpp
@@ -482,3 +482,11 @@ void SAEVRoute::removeRequestWeightFromRoute(SAEVKeyPoint& requestOriginKeyPoint
     currentKP->setCurrentOccupation(0); //reset request weight on destination KP
 }
 
+void SAEVRoute::insertRequestInNewVehicle(SAEVKeyPoint &originKp) {
+    size_t vehicleId = getLastActiveVehicleId() + 1;
+    setLastActiveVehicleId(vehicleId);
+    DEBUG_MSG("NEW VEHICLE CREATED, ID :" + std::to_string(vehicleId));
+
+    tryAddRequest(originKp, &getOriginDepot(vehicleId), &getOriginDepot(vehicleId));
+}
+
diff --git a/src/routes/vehicle/SAEVRoute.h b/src/routes/vehicle/SAEVRoute.h
index 1d4abe1..83a3713 100644
--- a/src/routes/vehicle/SAEVRoute.h
+++ b/src/routes/vehicle/SAEVRoute.h
@@ -40,6 +40,11 @@ public:
      * @param destinationRequestPredecessorKP Identifier/index in the route key point vector for the request origin or destination that will precede the destination of the request we want to insert
      */
     void insertRequest(SAEVKeyPoint &originKp, SAEVKeyPoint * originRequestPredecessorKP, SAEVKeyPoint * destinationRequestPredecessorKP);
+    /**
+     * Inserts a request with propagation in a new vehicle while updating last active vehicle ID (since the vehicle is new, no need to tell where to insert)
+     * @param originKp Reference to the origin key point of the request we want to insert in the route
+     */
+    void insertRequestInNewVehicle(SAEVKeyPoint &originKp);
 
     /**
      * Raw request removal method. Public for debug purposes, but should effectively never be called by an outside member
-- 
GitLab


From 6dcd2da9511d0c61bcb35c4db8d0421085d0da47 Mon Sep 17 00:00:00 2001
From: Romain BERNARD <romain.bernard@uca.fr>
Date: Fri, 23 Aug 2024 18:13:47 +0200
Subject: [PATCH 206/327] use function from route API to insert in new vehicle

---
 src/algorithm/DARP/Heuristics/BestInsertionHeuristic.cpp | 4 +---
 1 file changed, 1 insertion(+), 3 deletions(-)

diff --git a/src/algorithm/DARP/Heuristics/BestInsertionHeuristic.cpp b/src/algorithm/DARP/Heuristics/BestInsertionHeuristic.cpp
index 99fe933..4b5e2c0 100644
--- a/src/algorithm/DARP/Heuristics/BestInsertionHeuristic.cpp
+++ b/src/algorithm/DARP/Heuristics/BestInsertionHeuristic.cpp
@@ -50,9 +50,7 @@ size_t BestInsertionHeuristic::doBestRequestInsertionForRoute(SAEVKeyPoint &requ
 
     //Update last active vehicle ID
     if(vehicleId > route.getLastActiveVehicleId()) {
-        route.setLastActiveVehicleId(vehicleId);
-        tryVehicleBestInsertion(requestKp, vehicleId, route);
-        DEBUG_MSG("NEW VEHICLE CREATED, ID :" + std::to_string(vehicleId));
+        route.insertRequestInNewVehicle(requestKp);
     }
 
     return vehicleId;
-- 
GitLab


From 9d0ebb3cf2b8a161bc8316e0ad38e9899d5824d0 Mon Sep 17 00:00:00 2001
From: Romain BERNARD <romain.bernard@uca.fr>
Date: Fri, 23 Aug 2024 18:14:43 +0200
Subject: [PATCH 207/327] WIP entry sub-request insertion to the modular
 heuristic API

---
 .../Heuristics/SimpleModularHeuristic.cpp     | 34 +++++++++++++++++++
 .../Heuristics/SimpleModularHeuristic.h       |  5 +++
 2 files changed, 39 insertions(+)

diff --git a/src/algorithm/Multimodal/Heuristics/SimpleModularHeuristic.cpp b/src/algorithm/Multimodal/Heuristics/SimpleModularHeuristic.cpp
index 886037e..8ea14c2 100644
--- a/src/algorithm/Multimodal/Heuristics/SimpleModularHeuristic.cpp
+++ b/src/algorithm/Multimodal/Heuristics/SimpleModularHeuristic.cpp
@@ -42,6 +42,40 @@ uint SimpleModularHeuristic::getMaxEntryConstraint(const Request &request, size_
     return (uint) std::floor(request.getMaxArrivalTw() - _graph->getShortestSAEVPath(ptEntryNodeIdx, request.getDestinationNodeIndex()) * request.getTransitTravelTimeRatio());
 }
 
+std::vector<Request>
+SimpleModularHeuristic::generateAndInsertBestEntries(const std::vector<Request> &baseRequestsList) {
+    std::vector<Request> entrySubRequestsList{baseRequestsList.size()}; //Init entry subrequests list
+    for(size_t i = 0; i < baseRequestsList.size(); ++i) {
+        const Request& baseRequest = baseRequestsList[i];
+        entrySubRequestsList.push_back(insertBestTransitEntryInRoute(baseRequest, i));
+    }
+
+    return entrySubRequestsList;
+}
+
+Request SimpleModularHeuristic::insertBestTransitEntryInRoute(const Request &baseRequest, size_t requestId) {
+    std::vector<Request> entrySubRequestsList{Constants::MAX_TRANSIT_ENTRY_CANDIDATES}; //Init entry subrequests list
+    std::vector<TransitAccess> entriesAccessList = getBestTransitEntriesList(baseRequest);
+    for(auto const& access : entriesAccessList) {
+        entrySubRequestsList.emplace_back(*_graph, baseRequest, access, true);
+    }
+
+    for(const auto& subreq : entrySubRequestsList) {
+        _route->getEntrySubRequestOrigin(requestId).setRequest(&subreq);
+        _route->getEntrySubRequestDestination(requestId).setRequest(&subreq);
+        SAEVRouteChangelist changeList = BestInsertionHeuristic::tryBestRequestInsertionInActiveVehicle(_route->getEntrySubRequestOrigin(requestId), *_route);
+        if(changeList.success()) {
+            //TODO: add subreq to the global requests list here ?
+            return subreq;
+        }
+
+    }
+
+    //If no active vehicle insertion worked, do best insertion on a new vehicle
+    _route->insertRequestInNewVehicle(_route->getEntrySubRequestOrigin(requestId));
+    return entrySubRequestsList[0];
+}
+
 const Graph *SimpleModularHeuristic::getGraph() const {
     return _graph;
 }
diff --git a/src/algorithm/Multimodal/Heuristics/SimpleModularHeuristic.h b/src/algorithm/Multimodal/Heuristics/SimpleModularHeuristic.h
index 4334493..bb08759 100644
--- a/src/algorithm/Multimodal/Heuristics/SimpleModularHeuristic.h
+++ b/src/algorithm/Multimodal/Heuristics/SimpleModularHeuristic.h
@@ -11,6 +11,7 @@
 #include "../../../instance/requests/Request.h"
 #include "../../../routes/vehicle/SAEVRoute.h"
 #include "TransitAccess.h"
+#include "../../DARP/Heuristics/BestInsertionHeuristic.h"
 
 class SimpleModularHeuristic {
 private:
@@ -26,6 +27,10 @@ public:
 //Private members for heuristic internal functions we don't wish to see overriden
 private:
 
+    Request insertBestTransitEntryInRoute(const Request &baseRequest, size_t requestId);
+    std::vector<Request> generateAndInsertBestEntries(const std::vector<Request> &baseRequestsList);
+    void insertBestTransitExitsInRoute(const std::vector<Request>& baseRequestsList, const std::vector<TransitAccess>& transitEntriesList);
+
     //Best candidates function
     /**
      * Creates and returns a vector of TransitAccess objects representing possible
-- 
GitLab


From 6a939222eea17f0ec1dd6a34241b978dd0e57367 Mon Sep 17 00:00:00 2001
From: Romain BERNARD <romain.bernard@uca.fr>
Date: Mon, 26 Aug 2024 11:26:21 +0200
Subject: [PATCH 208/327] appropriately update subrequest in route before
 inserting it in a new vehicle

---
 .../Multimodal/Heuristics/SimpleModularHeuristic.cpp       | 7 ++++---
 1 file changed, 4 insertions(+), 3 deletions(-)

diff --git a/src/algorithm/Multimodal/Heuristics/SimpleModularHeuristic.cpp b/src/algorithm/Multimodal/Heuristics/SimpleModularHeuristic.cpp
index 8ea14c2..17a0c7b 100644
--- a/src/algorithm/Multimodal/Heuristics/SimpleModularHeuristic.cpp
+++ b/src/algorithm/Multimodal/Heuristics/SimpleModularHeuristic.cpp
@@ -64,14 +64,15 @@ Request SimpleModularHeuristic::insertBestTransitEntryInRoute(const Request &bas
         _route->getEntrySubRequestOrigin(requestId).setRequest(&subreq);
         _route->getEntrySubRequestDestination(requestId).setRequest(&subreq);
         SAEVRouteChangelist changeList = BestInsertionHeuristic::tryBestRequestInsertionInActiveVehicle(_route->getEntrySubRequestOrigin(requestId), *_route);
+        //If we've found an insertion that doesn't create a vehicle, stop there
         if(changeList.success()) {
-            //TODO: add subreq to the global requests list here ?
             return subreq;
         }
-
     }
 
-    //If no active vehicle insertion worked, do best insertion on a new vehicle
+    //If no active vehicle insertion worked, do best insertion on a new vehicle with the first subrequest (supposedly it's the most advantageous)
+    _route->getEntrySubRequestOrigin(requestId).setRequest(&entrySubRequestsList[0]);
+    _route->getEntrySubRequestDestination(requestId).setRequest(&entrySubRequestsList[0]);
     _route->insertRequestInNewVehicle(_route->getEntrySubRequestOrigin(requestId));
     return entrySubRequestsList[0];
 }
-- 
GitLab


From 60f03b057eaec177564dd9957ecb6a4dd1e9bfdf Mon Sep 17 00:00:00 2001
From: Romain BERNARD <romain.bernard@uca.fr>
Date: Mon, 26 Aug 2024 11:27:57 +0200
Subject: [PATCH 209/327] rename constant to be more in line with other max
 candidates constants

---
 src/ShortestPath/Vehicle/VehicleShortestPathCalculation.cpp | 2 +-
 src/utils/Constants.h                                       | 2 +-
 2 files changed, 2 insertions(+), 2 deletions(-)

diff --git a/src/ShortestPath/Vehicle/VehicleShortestPathCalculation.cpp b/src/ShortestPath/Vehicle/VehicleShortestPathCalculation.cpp
index 234dc24..e9fd2a2 100644
--- a/src/ShortestPath/Vehicle/VehicleShortestPathCalculation.cpp
+++ b/src/ShortestPath/Vehicle/VehicleShortestPathCalculation.cpp
@@ -27,7 +27,7 @@ VehicleShortestPathCalculation::computeShortestPathsFromNode(Graph &graph, size_
             mark[currentState.getNodeIndex()] = true;
 
             //Considering order of iteration is by shortest path to starting node, it's fair to add the current state node as a closest station
-            if(graph.getNbPTLines(currentState.getNodeIndex()) > 0 && graph.getNbClosestStations(startingNodeIdx) < Constants::CLOSEST_STATIONS_LIST_SIZE) {
+            if(graph.getNbPTLines(currentState.getNodeIndex()) > 0 && graph.getNbClosestStations(startingNodeIdx) < Constants::MAX_CLOSEST_STATIONS_CANDIDATES) {
                 graph.emplaceBackClosestStation(startingNodeIdx, currentState.getNodeIndex());
             }
 
diff --git a/src/utils/Constants.h b/src/utils/Constants.h
index 9c2dcdd..917db25 100644
--- a/src/utils/Constants.h
+++ b/src/utils/Constants.h
@@ -13,7 +13,7 @@ public:
     /**
      * The max amount of closest stations we preprocess for a given node (namely request origin nodes)
      */
-    static constexpr size_t CLOSEST_STATIONS_LIST_SIZE = 30;
+    static constexpr size_t MAX_CLOSEST_STATIONS_CANDIDATES = 30;
     /**
      * The maximum amount of transit entry stations checked during our heuristic algorithm
      */
-- 
GitLab


From 23d67faded3fb993a02986a755d3cf780a78eff7 Mon Sep 17 00:00:00 2001
From: Romain BERNARD <romain.bernard@uca.fr>
Date: Mon, 26 Aug 2024 12:47:36 +0200
Subject: [PATCH 210/327] push the inserted subrequest to the requests vector

---
 .../Multimodal/Heuristics/SimpleModularHeuristic.cpp          | 4 +++-
 src/algorithm/Multimodal/Heuristics/SimpleModularHeuristic.h  | 3 ++-
 2 files changed, 5 insertions(+), 2 deletions(-)

diff --git a/src/algorithm/Multimodal/Heuristics/SimpleModularHeuristic.cpp b/src/algorithm/Multimodal/Heuristics/SimpleModularHeuristic.cpp
index 17a0c7b..5251872 100644
--- a/src/algorithm/Multimodal/Heuristics/SimpleModularHeuristic.cpp
+++ b/src/algorithm/Multimodal/Heuristics/SimpleModularHeuristic.cpp
@@ -47,7 +47,9 @@ SimpleModularHeuristic::generateAndInsertBestEntries(const std::vector<Request>
     std::vector<Request> entrySubRequestsList{baseRequestsList.size()}; //Init entry subrequests list
     for(size_t i = 0; i < baseRequestsList.size(); ++i) {
         const Request& baseRequest = baseRequestsList[i];
-        entrySubRequestsList.push_back(insertBestTransitEntryInRoute(baseRequest, i));
+        const Request subreq = insertBestTransitEntryInRoute(baseRequest, i);
+        _requestsVect->push_back(subreq);
+        entrySubRequestsList.push_back(subreq);
     }
 
     return entrySubRequestsList;
diff --git a/src/algorithm/Multimodal/Heuristics/SimpleModularHeuristic.h b/src/algorithm/Multimodal/Heuristics/SimpleModularHeuristic.h
index bb08759..71fad54 100644
--- a/src/algorithm/Multimodal/Heuristics/SimpleModularHeuristic.h
+++ b/src/algorithm/Multimodal/Heuristics/SimpleModularHeuristic.h
@@ -17,10 +17,11 @@ class SimpleModularHeuristic {
 private:
     const Graph* _graph{nullptr};
     SAEVRoute* _route{nullptr};
+    std::vector<Request>* _requestsVect{nullptr};
 
 //Public interface to interact with the modular heuristic
 public:
-    SimpleModularHeuristic(const Graph *graph, SAEVRoute *route) : _graph(graph), _route(route) {}
+    SimpleModularHeuristic(const Graph *graph, SAEVRoute *route, std::vector<Request>* requestsVect) : _graph(graph), _route(route), _requestsVect(requestsVect) {}
 
     void multimodalRequestsInsertion(const std::vector<Request>& requestsToInsert);
 
-- 
GitLab


From 1842679df62121792583fac63784296987d3ed71 Mon Sep 17 00:00:00 2001
From: Romain BERNARD <romain.bernard@uca.fr>
Date: Mon, 26 Aug 2024 12:48:54 +0200
Subject: [PATCH 211/327] shatter best entry insertion in three for easier
 tests, overriding and performance management

---
 .../Heuristics/SimpleModularHeuristic.cpp     | 35 ++++++++++++++++++-
 .../Heuristics/SimpleModularHeuristic.h       |  3 ++
 2 files changed, 37 insertions(+), 1 deletion(-)

diff --git a/src/algorithm/Multimodal/Heuristics/SimpleModularHeuristic.cpp b/src/algorithm/Multimodal/Heuristics/SimpleModularHeuristic.cpp
index 5251872..f6d6b15 100644
--- a/src/algorithm/Multimodal/Heuristics/SimpleModularHeuristic.cpp
+++ b/src/algorithm/Multimodal/Heuristics/SimpleModularHeuristic.cpp
@@ -55,13 +55,46 @@ SimpleModularHeuristic::generateAndInsertBestEntries(const std::vector<Request>
     return entrySubRequestsList;
 }
 
+/**
+ * Generates the best entries list (ordered by an implementation-dependant ,
+ * then generates a vector of requests from these entries before starting the entry subrequest insertion process <br>
+ * The insertion process first tries best insertions without creating a new vehicles in order of the best entries list.
+ * If none result in a valid insertion, we insert the first subrequest (supposedly the better one) in a new vehicle
+ * @param baseRequest const ref to the request we use as our base to get the best entries list
+ * @param requestId ID/index in the request vector for our base request
+ * @return The subrequest successfully inserted in our route. This method's caller needs to add this request to its main request vector
+ */
 Request SimpleModularHeuristic::insertBestTransitEntryInRoute(const Request &baseRequest, size_t requestId) {
-    std::vector<Request> entrySubRequestsList{Constants::MAX_TRANSIT_ENTRY_CANDIDATES}; //Init entry subrequests list
     std::vector<TransitAccess> entriesAccessList = getBestTransitEntriesList(baseRequest);
+    return insertBestTransitEntryInRoute(baseRequest, entriesAccessList, requestId);
+}
+
+/**
+ * Generates a vector of requests from the given entries list before starting the entry subrequest insertion process <br>
+ * The insertion process first tries best insertions without creating a new vehicles in order of the best entries list.
+ * If none result in a valid insertion, we insert the first subrequest (supposedly the better one) in a new vehicle
+ * @param baseRequest const ref to the request we use as our base to generate subrequest frm the best entries list
+ * @param entriesAccessList A list of best entries, preferably ordered from best to worst and sized according to the max number of candidates we want to try inserting
+ * @param requestId ID/index in the request vector for our base request
+ * @return The subrequest successfully inserted in our route. This method's caller needs to add this request to its main request vector
+ */
+Request SimpleModularHeuristic::insertBestTransitEntryInRoute(const Request &baseRequest, const std::vector<TransitAccess>& entriesAccessList, size_t requestId) {
+    std::vector<Request> entrySubRequestsList{Constants::MAX_TRANSIT_ENTRY_CANDIDATES}; //Init entry subrequests list to the appropriate size
+    //Generate subrequests from best transit entries
     for(auto const& access : entriesAccessList) {
         entrySubRequestsList.emplace_back(*_graph, baseRequest, access, true);
     }
+    return insertBestTransitEntryInRoute(entrySubRequestsList, requestId);
+}
 
+/**
+ * The insertion process first tries best insertions without creating a new vehicles in order of the best entries list.
+ * If none result in a valid insertion, we insert the first subrequest (supposedly the better one) in a new vehicle
+ * @param entrySubRequestsList A list of entry subrequest candidates, preferably ordered from best to worst candidate, but the list order is implementation dependant
+ * @param requestId ID/index in the request vector for our base request
+ * @return The subrequest successfully inserted in our route. This method's caller needs to add this request to its main request vector
+ */
+Request SimpleModularHeuristic::insertBestTransitEntryInRoute(const std::vector<Request>& entrySubRequestsList, size_t requestId) {
     for(const auto& subreq : entrySubRequestsList) {
         _route->getEntrySubRequestOrigin(requestId).setRequest(&subreq);
         _route->getEntrySubRequestDestination(requestId).setRequest(&subreq);
diff --git a/src/algorithm/Multimodal/Heuristics/SimpleModularHeuristic.h b/src/algorithm/Multimodal/Heuristics/SimpleModularHeuristic.h
index 71fad54..ffb0bef 100644
--- a/src/algorithm/Multimodal/Heuristics/SimpleModularHeuristic.h
+++ b/src/algorithm/Multimodal/Heuristics/SimpleModularHeuristic.h
@@ -29,6 +29,9 @@ public:
 private:
 
     Request insertBestTransitEntryInRoute(const Request &baseRequest, size_t requestId);
+    Request insertBestTransitEntryInRoute(const Request &baseRequest, const std::vector<TransitAccess>& entriesAccessList, size_t requestId);
+    Request insertBestTransitEntryInRoute(const std::vector<Request>& entrySubRequestsList, size_t requestId);
+
     std::vector<Request> generateAndInsertBestEntries(const std::vector<Request> &baseRequestsList);
     void insertBestTransitExitsInRoute(const std::vector<Request>& baseRequestsList, const std::vector<TransitAccess>& transitEntriesList);
 
-- 
GitLab


From b5710044e5710c18c43b0ce59f7331617b9753dc Mon Sep 17 00:00:00 2001
From: Romain BERNARD <romain.bernard@uca.fr>
Date: Mon, 26 Aug 2024 17:52:51 +0200
Subject: [PATCH 212/327] expand the graph and node API for easier use of the
 precomputing algorithms

---
 src/instance/graph/Graph.cpp | 28 ++++++++++++++++++++++++++++
 src/instance/graph/Graph.h   | 14 ++++++++++++++
 src/instance/graph/Node.cpp  |  4 ++++
 src/instance/graph/Node.h    |  2 ++
 4 files changed, 48 insertions(+)

diff --git a/src/instance/graph/Graph.cpp b/src/instance/graph/Graph.cpp
index a705d4a..febc131 100644
--- a/src/instance/graph/Graph.cpp
+++ b/src/instance/graph/Graph.cpp
@@ -343,3 +343,31 @@ void Graph::emplaceBackClosestStation(size_t nodeIdx, size_t stationNodeIdx) {
 const size_t Graph::getNbClosestStations(size_t nodeIdx) {
     return nodesVector[nodeIdx].getBestStationsNodeIdxVector().size();
 }
+
+void Graph::computeAndUpdateClosestStationsForNode(size_t nodeIdx) {
+    ClosestDestinationsContainer closestPTNodes = VehicleShortestPathCalculation::getClosestPTNodesFromX(*this, nodeIdx);
+    for(const VehicleDestination& closestDestination : closestPTNodes.getOrderedDestinations()) {
+        nodesVector[nodeIdx].emplaceBackClosestStation(closestDestination.getDestinationNodeIdx());
+        if(nodesVector[nodeIdx].getBestStationsNodeIdxVector().size() == Constants::MAX_CLOSEST_STATIONS_CANDIDATES) {
+            break;
+        }
+    }
+}
+
+void Graph::computeAndUpdateClosestStations() {
+    for(size_t i = 0; i < nodesVector.size(); ++i)
+        computeAndUpdateClosestStationsForNode(i);
+}
+
+void Graph::computeAndUpdateShortestTransitPaths() {
+    TransitShortestPathContainer shortestPathsContainer(getNbNodes());
+    for(auto& ptLine : getPTLines()) {
+        for(size_t i = 0; i < ptLine.size(); ++i) {
+            for (auto& startingTime: ptLine.getTimetable(i)) {
+                const TransitStateContainer &results = TransitShortestPathPrecompute::executeAlgorithm(*this,ptLine.getNode(i),startingTime);
+                shortestPathsContainer.addShortestPathCollection(i, startingTime, getNbNodes(), results);
+            }
+        }
+    }
+    transitShortestPaths = shortestPathsContainer;
+}
diff --git a/src/instance/graph/Graph.h b/src/instance/graph/Graph.h
index 61c4627..2801e08 100644
--- a/src/instance/graph/Graph.h
+++ b/src/instance/graph/Graph.h
@@ -13,6 +13,10 @@
 
 #include "Node.h"
 #include "Edge.h"
+#include "../../ShortestPath/Vehicle/VehicleShortestPathCalculation.h"
+#include "../../utils/Constants.h"
+#include "../../ShortestPath/Transit/TransitShortestPathContainer.h"
+#include "../../ShortestPath/Transit/TransitShortestPathPrecompute.h"
 
 class DATRow;
 class Graph {
@@ -21,6 +25,7 @@ private:
     std::vector<Edge> edgesVector;
     std::vector<Line> transitLines;
     std::vector<std::vector<uint>> shortestSAEVPaths;
+    TransitShortestPathContainer transitShortestPaths;
     size_t _depotNodeIdx{0}; //Index of the depot node, defaults to 0, the first node created in the graph
 
     /**
@@ -162,6 +167,15 @@ public:
     void emplaceBackClosestStation(size_t nodeIdx, size_t stationNodeIdx);
 
     const size_t getNbClosestStations(size_t nodeIdx);
+
+    void computeAndUpdateShortestPathsMatrix() {
+        VehicleShortestPathCalculation::computeAndUpdateShortestPathsForGraph(*this);
+    }
+
+    void computeAndUpdateClosestStationsForNode(size_t nodeIdx);
+    void computeAndUpdateClosestStations();
+    void computeAndUpdateShortestTransitPaths();
+
 };
 
 
diff --git a/src/instance/graph/Node.cpp b/src/instance/graph/Node.cpp
index b31ab04..83f0593 100644
--- a/src/instance/graph/Node.cpp
+++ b/src/instance/graph/Node.cpp
@@ -55,3 +55,7 @@ void Node::emplaceBackClosestStation(size_t closestStationIdx) {
 const std::vector<size_t> & Node::getBestStationsNodeIdxVector() const {
     return _bestStationsNodeIdxVector;
 }
+
+void Node::setBestStationsNodeIdxVector(const std::vector<size_t> &bestStationsOrderedVector) {
+    _bestStationsNodeIdxVector = bestStationsOrderedVector;
+}
diff --git a/src/instance/graph/Node.h b/src/instance/graph/Node.h
index 7861acf..a18eea5 100644
--- a/src/instance/graph/Node.h
+++ b/src/instance/graph/Node.h
@@ -10,6 +10,7 @@
 #include <set>
 #include <unordered_map>
 #include <vector>
+#include "../../ShortestPath/Vehicle/ClosestDestinationsContainer.h"
 
 /**
  * Status used to qualify nodes as places with different goals (work, leisure, residential)
@@ -93,6 +94,7 @@ public:
     void emplaceBackClosestStation(size_t closestStationIdx);
 
     [[nodiscard]] const std::vector<size_t>& getBestStationsNodeIdxVector() const;
+    void setBestStationsNodeIdxVector(const std::vector<size_t> &bestStationsOrderedVector);
 };
 #include "Line.h"
 #include "LineStop.h"
-- 
GitLab


From 01db8033e845eaec46c4a7989f4f36ec8ea4e6b2 Mon Sep 17 00:00:00 2001
From: Romain BERNARD <romain.bernard@uca.fr>
Date: Mon, 26 Aug 2024 17:53:40 +0200
Subject: [PATCH 213/327] use appropriate index types in transit shortest paths
 containers

---
 .../Transit/TransitShortestPathContainer.cpp     | 16 ++++++++--------
 .../Transit/TransitShortestPathContainer.h       | 10 +++++-----
 2 files changed, 13 insertions(+), 13 deletions(-)

diff --git a/src/ShortestPath/Transit/TransitShortestPathContainer.cpp b/src/ShortestPath/Transit/TransitShortestPathContainer.cpp
index 10dfb98..fd33bc8 100644
--- a/src/ShortestPath/Transit/TransitShortestPathContainer.cpp
+++ b/src/ShortestPath/Transit/TransitShortestPathContainer.cpp
@@ -6,18 +6,18 @@
 #include "TransitShortestPathContainer.h"
 #include "TransitStateContainer.h"
 
-void TransitShortestPathContainer::addShortestPathCollection(int startNodeIndex,
-                                                             const std::pair<int, std::vector<TransitShortestPath>>& shortestPathList) {
+void TransitShortestPathContainer::addShortestPathCollection(size_t startNodeIndex,
+                                                             const std::pair<size_t , std::vector<TransitShortestPath>>& shortestPathList) {
     container[startNodeIndex].emplace_back(shortestPathList);
 }
 
-void TransitShortestPathContainer::addShortestPathCollection(int startNodeIndex, int startingInstant, int graphSize,
+void TransitShortestPathContainer::addShortestPathCollection(size_t startNodeIndex, uint startingInstant, size_t graphSize,
                                                              const TransitStateContainer& algorithmResultStates) {
     std::vector<TransitShortestPath> shortestPathList;
     shortestPathList.reserve(graphSize);
 
     //Convert states to shortest paths and add to collection
-    for(int i = 0; i < graphSize; ++i) {
+    for(size_t i = 0; i < graphSize; ++i) {
         shortestPathList.emplace_back(algorithmResultStates.getBestSolution(i));
     }
 
@@ -25,16 +25,16 @@ void TransitShortestPathContainer::addShortestPathCollection(int startNodeIndex,
     container[startNodeIndex].emplace_back(startingInstant, shortestPathList);
 }
 
-std::pair<int, std::vector<TransitShortestPath>> *
-TransitShortestPathContainer::getShortestPathsFrom(int startNodeIndex, int earliestStartInstant) {
+std::pair<size_t, std::vector<TransitShortestPath>> *
+TransitShortestPathContainer::getShortestPathsFrom(size_t startNodeIndex, uint earliestStartInstant) {
     const auto& iterator = std::ranges::lower_bound(container[startNodeIndex],
-                                            std::pair<int, std::vector<TransitShortestPath>>(earliestStartInstant, {}));
+                                            std::pair<size_t , std::vector<TransitShortestPath>>(earliestStartInstant, {}));
 
     return iterator.base();
 }
 
 TransitShortestPath
-TransitShortestPathContainer::getShortestPathToYFromTime(int startNodeIndex, int earliestStartInstant, int goalNode) {
+TransitShortestPathContainer::getShortestPathToYFromTime(size_t startNodeIndex, uint earliestStartInstant, size_t goalNode) {
     auto [startNode, shortestPathsVector] = *getShortestPathsFrom(startNodeIndex, earliestStartInstant);
     for(const auto& shortestPath : shortestPathsVector) {
         if(shortestPath.getArrivalNode() == goalNode) {
diff --git a/src/ShortestPath/Transit/TransitShortestPathContainer.h b/src/ShortestPath/Transit/TransitShortestPathContainer.h
index 14e26db..3030b45 100644
--- a/src/ShortestPath/Transit/TransitShortestPathContainer.h
+++ b/src/ShortestPath/Transit/TransitShortestPathContainer.h
@@ -12,15 +12,15 @@
 
 class TransitShortestPathContainer {
 private:
-    std::vector<std::vector<std::pair<int, std::vector<TransitShortestPath>>>> container; //NodeVector< PairVector<Pair<Instant, NodeVector<ShortestPath> >> >
+    std::vector<std::vector<std::pair<size_t, std::vector<TransitShortestPath>>>> container; //NodeVector< PairVector<Pair<Instant, NodeVector<ShortestPath> >> >
 
 public:
     explicit TransitShortestPathContainer(int size) { container.resize(size); }
     explicit TransitShortestPathContainer(size_t size) { container.resize(size); }
-    void addShortestPathCollection(int startNodeIndex, const std::pair<int, std::vector<TransitShortestPath>>& shortestPathList);
-    void addShortestPathCollection(int startNodeIndex, int startingInstant, int graphSize, const TransitStateContainer& algorithmResultStates);
-    std::pair<int, std::vector<TransitShortestPath>> * getShortestPathsFrom(int startNodeIndex, int earliestStartInstant);
-    TransitShortestPath getShortestPathToYFromTime(int startNodeIndex, int earliestStartInstant, int goalNode);
+    void addShortestPathCollection(size_t startNodeIndex, const std::pair<size_t , std::vector<TransitShortestPath>>& shortestPathList);
+    void addShortestPathCollection(size_t startNodeIndex, uint startingInstant, size_t graphSize, const TransitStateContainer& algorithmResultStates);
+    std::pair<size_t, std::vector<TransitShortestPath>> * getShortestPathsFrom(size_t startNodeIndex, uint earliestStartInstant);
+    TransitShortestPath getShortestPathToYFromTime(size_t startNodeIndex, uint earliestStartInstant, size_t goalNode);
 };
 
 
-- 
GitLab


From e740059671a1d7c4f28a3d5339c1b14670e3dd5e Mon Sep 17 00:00:00 2001
From: Romain BERNARD <romain.bernard@uca.fr>
Date: Mon, 26 Aug 2024 17:54:18 +0200
Subject: [PATCH 214/327] fix dependencies

---
 src/ShortestPath/Vehicle/VehicleShortestPathCalculation.h | 3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)

diff --git a/src/ShortestPath/Vehicle/VehicleShortestPathCalculation.h b/src/ShortestPath/Vehicle/VehicleShortestPathCalculation.h
index c2ab0e9..11f9b4c 100644
--- a/src/ShortestPath/Vehicle/VehicleShortestPathCalculation.h
+++ b/src/ShortestPath/Vehicle/VehicleShortestPathCalculation.h
@@ -7,10 +7,10 @@
 
 
 #include "MatrixShortestPathContainer.h"
-#include "../../instance/graph/Graph.h"
 #include "ClosestDestinationsContainer.h"
 #include "VehiclePathState.h"
 
+class Graph;
 class VehicleShortestPathCalculation {
 public:
     /**
@@ -46,6 +46,7 @@ private:
     static void expandStatesViaMatrix(const VehiclePathState& currentState, std::vector<uint> &results,
                                       std::priority_queue<VehiclePathState, std::vector<VehiclePathState>, std::greater<>> &stateQueue, const Graph& graph);
 };
+#include "../../instance/graph/Graph.h"
 
 
 #endif //GREEDYALGORITHM_VEHICLESHORTESTPATHCALCULATION_H
-- 
GitLab


From 8f61fbe9a49875964d403e493df74ac048884fa1 Mon Sep 17 00:00:00 2001
From: Romain BERNARD <romain.bernard@uca.fr>
Date: Mon, 26 Aug 2024 17:54:55 +0200
Subject: [PATCH 215/327] clang/sonar fixes

---
 .../Multimodal/Heuristics/SimpleModularHeuristic.cpp        | 2 +-
 .../Multimodal/Heuristics/SimpleModularHeuristic.h          | 6 +++---
 src/utils/Globals.h                                         | 4 ++--
 3 files changed, 6 insertions(+), 6 deletions(-)

diff --git a/src/algorithm/Multimodal/Heuristics/SimpleModularHeuristic.cpp b/src/algorithm/Multimodal/Heuristics/SimpleModularHeuristic.cpp
index f6d6b15..c93d593 100644
--- a/src/algorithm/Multimodal/Heuristics/SimpleModularHeuristic.cpp
+++ b/src/algorithm/Multimodal/Heuristics/SimpleModularHeuristic.cpp
@@ -4,7 +4,7 @@
 
 #include "SimpleModularHeuristic.h"
 
-std::vector<TransitAccess> SimpleModularHeuristic::getBestTransitEntriesList(const Request &baseRequest) {
+std::vector<TransitAccess> SimpleModularHeuristic::getBestTransitEntriesList(const Request &baseRequest) const {
     const auto& bestStationsIndexVector = _graph->getNode(
             baseRequest.getOriginNodeIndex()).getBestStationsNodeIdxVector();
     std::vector<TransitAccess> results{bestStationsIndexVector.size()}; //init results vector to the appropriate size
diff --git a/src/algorithm/Multimodal/Heuristics/SimpleModularHeuristic.h b/src/algorithm/Multimodal/Heuristics/SimpleModularHeuristic.h
index ffb0bef..c792f16 100644
--- a/src/algorithm/Multimodal/Heuristics/SimpleModularHeuristic.h
+++ b/src/algorithm/Multimodal/Heuristics/SimpleModularHeuristic.h
@@ -49,7 +49,7 @@ private:
      * @return A vector consisting of all valid TransitAccess objects wrt the base request
      * and the min/max exit constraints. If no valid access is found, we return an empty vector.
      */
-    std::vector<TransitAccess> getBestTransitEntriesList(const Request &baseRequest);
+    [[nodiscard]] std::vector<TransitAccess> getBestTransitEntriesList(const Request &baseRequest) const;
 
     /**
      * Creates and returns a vector of TransitAccess objects representing possible
@@ -76,10 +76,10 @@ protected:
     uint getMinExitConstraint(const Request &request, size_t exitNodeIndex);
     uint getMaxExitConstraint(const Request &request, size_t exitNodeIndex);
 
-    const Graph *getGraph() const;
+    [[nodiscard]] const Graph *getGraph() const;
     void setGraph(const Graph *graph);
 
-    SAEVRoute *getRoute() const;
+    [[nodiscard]] SAEVRoute *getRoute() const;
     void setRoute(SAEVRoute *route);
 };
 
diff --git a/src/utils/Globals.h b/src/utils/Globals.h
index 43b8f61..34cd27e 100644
--- a/src/utils/Globals.h
+++ b/src/utils/Globals.h
@@ -5,7 +5,7 @@
 #ifndef GREEDYALGORITHM_GLOBALS_H
 #define GREEDYALGORITHM_GLOBALS_H
 
-typedef unsigned int uint;
-typedef unsigned long ulong;
+using uint = unsigned int;
+using ulong = unsigned long;
 
 #endif //GREEDYALGORITHM_GLOBALS_H
-- 
GitLab


From 0dd3eef24305f06417974cece73ebac904ce0bb2 Mon Sep 17 00:00:00 2001
From: Romain BERNARD <romain.bernard@uca.fr>
Date: Mon, 26 Aug 2024 18:39:43 +0200
Subject: [PATCH 216/327] init empty transit shortest paths container

---
 src/instance/graph/Graph.h | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/src/instance/graph/Graph.h b/src/instance/graph/Graph.h
index 2801e08..0520351 100644
--- a/src/instance/graph/Graph.h
+++ b/src/instance/graph/Graph.h
@@ -25,7 +25,7 @@ private:
     std::vector<Edge> edgesVector;
     std::vector<Line> transitLines;
     std::vector<std::vector<uint>> shortestSAEVPaths;
-    TransitShortestPathContainer transitShortestPaths;
+    TransitShortestPathContainer transitShortestPaths = TransitShortestPathContainer(0);
     size_t _depotNodeIdx{0}; //Index of the depot node, defaults to 0, the first node created in the graph
 
     /**
-- 
GitLab


From c0da136034ee2fb32f09651b27f16131eb2d2ef7 Mon Sep 17 00:00:00 2001
From: Romain BERNARD <romain.bernard@uca.fr>
Date: Mon, 26 Aug 2024 18:43:10 +0200
Subject: [PATCH 217/327] add timing macros for algorithm tests

---
 src/utils/Timing.h | 24 ++++++++++++++++++++++++
 1 file changed, 24 insertions(+)
 create mode 100644 src/utils/Timing.h

diff --git a/src/utils/Timing.h b/src/utils/Timing.h
new file mode 100644
index 0000000..5e72068
--- /dev/null
+++ b/src/utils/Timing.h
@@ -0,0 +1,24 @@
+//
+// Created by romain on 26/08/24.
+//
+
+#ifndef GREEDYALGORITHM_TIMING_H
+#define GREEDYALGORITHM_TIMING_H
+
+#include <chrono>
+#define TIMING
+
+#ifdef TIMING
+#define INIT_TIMER auto start = std::chrono::high_resolution_clock::now();
+#define START_TIMER  start = std::chrono::high_resolution_clock::now();
+#define STOP_TIMER(name)  std::cout << "RUNTIME of " << name << ": " << \
+    std::chrono::duration_cast<std::chrono::milliseconds>( \
+            std::chrono::high_resolution_clock::now()-start \
+    ).count() << " ms " << std::endl;
+#else
+#define INIT_TIMER
+#define START_TIMER
+#define STOP_TIMER(name)
+#endif
+
+#endif //GREEDYALGORITHM_TIMING_H
-- 
GitLab


From a2d12f780d8451c96ec93c07345a4369b7eee836 Mon Sep 17 00:00:00 2001
From: Romain BERNARD <romain.bernard@uca.fr>
Date: Mon, 26 Aug 2024 18:44:17 +0200
Subject: [PATCH 218/327] Init multimodal heuristic tests (TODO: Work on the
 instance to go farther than instance parsing (probably a wrong request file))

---
 .../Heuristics/SimpleModularHeuristic.h       |  4 ++
 test/CMakeLists.txt                           | 46 ++++++++++++++++++-
 .../src/MultimodalInsertionHeuristicDebug.cpp | 45 ++++++++++++++++++
 3 files changed, 94 insertions(+), 1 deletion(-)
 create mode 100644 test/src/MultimodalInsertionHeuristicDebug.cpp

diff --git a/src/algorithm/Multimodal/Heuristics/SimpleModularHeuristic.h b/src/algorithm/Multimodal/Heuristics/SimpleModularHeuristic.h
index c792f16..a0567e4 100644
--- a/src/algorithm/Multimodal/Heuristics/SimpleModularHeuristic.h
+++ b/src/algorithm/Multimodal/Heuristics/SimpleModularHeuristic.h
@@ -12,6 +12,7 @@
 #include "../../../routes/vehicle/SAEVRoute.h"
 #include "TransitAccess.h"
 #include "../../DARP/Heuristics/BestInsertionHeuristic.h"
+#include "../../../../test/lib/googletest/googletest/include/gtest/gtest_prod.h"
 
 class SimpleModularHeuristic {
 private:
@@ -19,6 +20,9 @@ private:
     SAEVRoute* _route{nullptr};
     std::vector<Request>* _requestsVect{nullptr};
 
+    //Add friend test classes to test inner workings without making the whole API public
+    FRIEND_TEST(MultimodalInsertionHeuristicDebug, DebugBaseInstance);
+
 //Public interface to interact with the modular heuristic
 public:
     SimpleModularHeuristic(const Graph *graph, SAEVRoute *route, std::vector<Request>* requestsVect) : _graph(graph), _route(route), _requestsVect(requestsVect) {}
diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt
index b1a13fb..b74b502 100644
--- a/test/CMakeLists.txt
+++ b/test/CMakeLists.txt
@@ -148,8 +148,52 @@ add_executable(GraphPreprocess_DEB
         ../src/utils/Constants.h
 )
 
+add_executable(MultimodalInsertionHeuristic_DEB
+        ../src/TimeWindow.cpp
+        ../src/TimeWindow.h
+        ../src/instance/graph/Node.cpp
+        ../src/instance/graph/Node.h
+        ../src/instance/graph/Edge.cpp
+        ../src/instance/graph/Edge.h
+        ../src/instance/graph/Graph.cpp
+        ../src/instance/graph/Graph.h
+        ../src/instance/graph/Line.cpp
+        ../src/instance/graph/Line.h
+        ../src/instance/requests/Request.cpp
+        ../src/instance/requests/Request.h
+        ../src/routes/vehicle/SAEVRoute.cpp
+        ../src/routes/vehicle/SAEVRoute.h
+        ../src/routes/vehicle/propagation/SAEVRouteChange.cpp
+        ../src/routes/vehicle/propagation/SAEVRouteChange.h
+        ../src/routes/vehicle/propagation/SAEVRouteChangelist.cpp
+        ../src/routes/vehicle/propagation/SAEVRouteChangelist.h
+        ../src/routes/vehicle/SAEVKeyPoint.cpp
+        ../src/routes/vehicle/SAEVKeyPoint.h
+        ../src/routes/KeyPoint.cpp
+        ../src/routes/KeyPoint.h
+        ../src/routes/requests/RequestKeyPoint.cpp
+        ../src/routes/requests/RequestKeyPoint.h
+        ../src/routes/requests/RequestRoute.cpp
+        ../src/routes/requests/RequestRoute.h
+        ../src/ShortestPath/Vehicle/VehicleShortestPathCalculation.h
+        ../src/ShortestPath/Vehicle/VehicleShortestPathCalculation.cpp
+        ../src/ShortestPath/Transit/TransitShortestPathContainer.cpp
+        ../src/ShortestPath/Transit/TransitShortestPathContainer.h
+        ../src/ShortestPath/Transit/TransitShortestPathPrecompute.cpp
+        ../src/ShortestPath/Transit/TransitShortestPathPrecompute.h
+        ../src/algorithm/Multimodal/Heuristics/SimpleModularHeuristic.cpp
+        ../src/algorithm/Multimodal/Heuristics/SimpleModularHeuristic.h
+        ../src/algorithm/Multimodal/Heuristics/TransitAccess.h
+        ../src/algorithm/DARP/Heuristics/BestInsertionHeuristic.cpp
+        ../src/algorithm/DARP/Heuristics/BestInsertionHeuristic.h
+        ../src/utils/Constants.h
+        src/MultimodalInsertionHeuristicDebug.cpp
+        ../src/utils/Timing.h
+)
+
 target_link_libraries(Line_UT gtest gtest_main)
 target_link_libraries(Transit_Preprocess_DEB gtest gtest_main)
 target_link_libraries(Constraint_Propag_DEB gtest gtest_main)
 target_link_libraries(BestInsertionHeuristic_DEB gtest gtest_main)
-target_link_libraries(GraphPreprocess_DEB gtest gtest_main)
\ No newline at end of file
+target_link_libraries(GraphPreprocess_DEB gtest gtest_main)
+target_link_libraries(MultimodalInsertionHeuristic_DEB gtest gtest_main)
\ No newline at end of file
diff --git a/test/src/MultimodalInsertionHeuristicDebug.cpp b/test/src/MultimodalInsertionHeuristicDebug.cpp
new file mode 100644
index 0000000..44e3d0b
--- /dev/null
+++ b/test/src/MultimodalInsertionHeuristicDebug.cpp
@@ -0,0 +1,45 @@
+//
+// Created by romain on 20/03/24.
+//
+
+#include "../lib/googletest/googletest/include/gtest/gtest.h"
+#include "../../src/instance/graph/Graph.h"
+#include "../../src/instance/Instance.h"
+#include "../../src/routes/vehicle/SAEVRoute.h"
+#include "../../src/utils/Timing.h"
+#include "../../src/algorithm/Multimodal/Heuristics/SimpleModularHeuristic.h"
+
+TEST(MultimodalInsertionHeuristicDebug, DebugBaseInstance) {
+    std::string instancesPath = "../../resources/test/instances/Constraint Propagation/";
+    std::string instanceFolder = "basic_debug_instance/";
+    std::string graphDatFile = "graph.dat";
+    std::string requestsDatFile = "requests.dat";
+
+    //Parse graph
+    INIT_TIMER
+    Graph graphFromSingleFile(instancesPath + instanceFolder + graphDatFile);
+    std::vector<Request> requests = Request::getRequestsFromFile(instancesPath + instanceFolder + requestsDatFile, graphFromSingleFile);
+
+    //Init instance
+    Instance instance(requests,graphFromSingleFile,4);
+    SAEVRoute routesContainer(graphFromSingleFile, requests);
+    SimpleModularHeuristic multimodalHeuristic(&graphFromSingleFile, &routesContainer, &requests);
+    STOP_TIMER("Parsing and init")
+    std::cout << "------------------Fin parsing instance et route-------------------" << std::endl << std::endl;
+
+    std::cout << "------------------Start preprocessings-------------------" << std::endl << std::endl;
+    START_TIMER
+    routesContainer.initMultimodalKeyPoints();
+    graphFromSingleFile.computeAndUpdateShortestPathsMatrix();
+    graphFromSingleFile.computeAndUpdateShortestTransitPaths();
+    STOP_TIMER("Preprocess")
+    std::cout << "------------------End preprocessings-------------------" << std::endl << std::endl;
+    for(size_t i = 0; i < requests.size(); ++i) {
+        multimodalHeuristic.insertBestTransitEntryInRoute(requests[i], i);
+    }
+}
+
+int main(int argc, char* argv[]) {
+    testing::InitGoogleTest(&argc, argv);
+    return RUN_ALL_TESTS();
+}
\ No newline at end of file
-- 
GitLab


From 0cafba53746628947fe1c0fc2a09d4cd0eea8c29 Mon Sep 17 00:00:00 2001
From: Romain BERNARD <romain.bernard@uca.fr>
Date: Thu, 29 Aug 2024 17:07:15 +0200
Subject: [PATCH 219/327] fix lower_bound results not properly passed down the
 different levels of abstraction due to a temp copy vector

---
 src/instance/graph/Line.h     | 2 +-
 src/instance/graph/LineStop.h | 4 ++--
 src/utils/SearchAlgorithms.h  | 6 +++---
 3 files changed, 6 insertions(+), 6 deletions(-)

diff --git a/src/instance/graph/Line.h b/src/instance/graph/Line.h
index 8174ed2..a262c1a 100644
--- a/src/instance/graph/Line.h
+++ b/src/instance/graph/Line.h
@@ -38,7 +38,7 @@ public:
      * @param instant The instant of arrival at the station, hence we look for the value itself or the first greater instant
      * @return a vector index corresponding to the next valid passage at the given station and after or at the given instant
      */
-    [[nodiscard]] auto findNextScheduledPassage(size_t stationIdx, uint instant) const {
+    [[nodiscard]] std::vector<int>::const_iterator findNextScheduledPassage(size_t stationIdx, uint instant) const {
         return SearchAlgorithms<int>::findNextSortedValue(_timetables[stationIdx], instant);
     }
     /**
diff --git a/src/instance/graph/LineStop.h b/src/instance/graph/LineStop.h
index 1c0eed2..a98f078 100644
--- a/src/instance/graph/LineStop.h
+++ b/src/instance/graph/LineStop.h
@@ -30,10 +30,10 @@ public:
     [[nodiscard]] size_t findNextScheduledPassageIdx(size_t stationIdx, uint instant) const {
         return _lineRef.findNextScheduledPassageIdx(stationIdx, instant);
     }
-    [[nodiscard]] auto findNextScheduledPassage(uint instant) const {
+    [[nodiscard]] std::vector<int>::const_iterator findNextScheduledPassage(uint instant) const {
         return _lineRef.findNextScheduledPassage(_stopIndex, instant);
     }
-    [[nodiscard]] auto findNextScheduledPassage(size_t stationIdx, uint instant) const {
+    [[nodiscard]] std::vector<int>::const_iterator findNextScheduledPassage(size_t stationIdx, uint instant) const {
         return _lineRef.findNextScheduledPassage(stationIdx, instant);
     }
 
diff --git a/src/utils/SearchAlgorithms.h b/src/utils/SearchAlgorithms.h
index 239ee0e..a3c5b72 100644
--- a/src/utils/SearchAlgorithms.h
+++ b/src/utils/SearchAlgorithms.h
@@ -18,7 +18,7 @@ public:
      * @param value the comparable value we are looking for in the vector
      * @return an iterator to the first item higher or equal than the comparable value given
      */
-    static std::vector<Comparable>::iterator findNextSortedValue(std::vector<Comparable> sortedVector, Comparable value) {
+    static std::vector<Comparable>::const_iterator findNextSortedValue(const std::vector<Comparable>& sortedVector, Comparable value) {
         return std::ranges::lower_bound(sortedVector, value);
     }
     /**
@@ -27,7 +27,7 @@ public:
      * @param value the comparable value we are looking for in the vector
      * @return the size of the vector if all vector values are lower than our search, the index of the first larger or equal value otherwise
      */
-    static size_t findNextSortedValueIdx(std::vector<Comparable> sortedVector, Comparable value) {
+    static size_t findNextSortedValueIdx(const std::vector<Comparable>& sortedVector, Comparable value) {
         auto iterator = std::ranges::lower_bound(sortedVector, value);
         return std::distance(sortedVector.begin(), iterator);
     }
@@ -38,7 +38,7 @@ public:
      * @param value the comparable value we are looking for in the vector
      * @return -1 if the exact value hasn't been found or the index of the value if it's been found
      */
-    static size_t vectorBinarySearch(std::vector<Comparable> sortedVector, Comparable value) {
+    static size_t vectorBinarySearch(const std::vector<Comparable>& sortedVector, Comparable value) {
         auto iterator = std::ranges::lower_bound(sortedVector, value);
         if (iterator == sortedVector.end() || *iterator != value) {
             return -1;
-- 
GitLab


From bda5476ffd0e0edca3be4a4dd3bb75ab18d672d6 Mon Sep 17 00:00:00 2001
From: Romain BERNARD <romain.bernard@uca.fr>
Date: Thu, 29 Aug 2024 17:10:17 +0200
Subject: [PATCH 220/327] return a direct ref instead of a raw pointer

---
 src/ShortestPath/Transit/TransitShortestPathContainer.cpp | 6 +++---
 src/ShortestPath/Transit/TransitShortestPathContainer.h   | 2 +-
 2 files changed, 4 insertions(+), 4 deletions(-)

diff --git a/src/ShortestPath/Transit/TransitShortestPathContainer.cpp b/src/ShortestPath/Transit/TransitShortestPathContainer.cpp
index fd33bc8..a3700e7 100644
--- a/src/ShortestPath/Transit/TransitShortestPathContainer.cpp
+++ b/src/ShortestPath/Transit/TransitShortestPathContainer.cpp
@@ -25,17 +25,17 @@ void TransitShortestPathContainer::addShortestPathCollection(size_t startNodeInd
     container[startNodeIndex].emplace_back(startingInstant, shortestPathList);
 }
 
-std::pair<size_t, std::vector<TransitShortestPath>> *
+std::pair<size_t, std::vector<TransitShortestPath>>&
 TransitShortestPathContainer::getShortestPathsFrom(size_t startNodeIndex, uint earliestStartInstant) {
     const auto& iterator = std::ranges::lower_bound(container[startNodeIndex],
                                             std::pair<size_t , std::vector<TransitShortestPath>>(earliestStartInstant, {}));
 
-    return iterator.base();
+    return *iterator;
 }
 
 TransitShortestPath
 TransitShortestPathContainer::getShortestPathToYFromTime(size_t startNodeIndex, uint earliestStartInstant, size_t goalNode) {
-    auto [startNode, shortestPathsVector] = *getShortestPathsFrom(startNodeIndex, earliestStartInstant);
+    auto [startNode, shortestPathsVector] = getShortestPathsFrom(startNodeIndex, earliestStartInstant);
     for(const auto& shortestPath : shortestPathsVector) {
         if(shortestPath.getArrivalNode() == goalNode) {
             return shortestPath;
diff --git a/src/ShortestPath/Transit/TransitShortestPathContainer.h b/src/ShortestPath/Transit/TransitShortestPathContainer.h
index 3030b45..90c09da 100644
--- a/src/ShortestPath/Transit/TransitShortestPathContainer.h
+++ b/src/ShortestPath/Transit/TransitShortestPathContainer.h
@@ -19,7 +19,7 @@ public:
     explicit TransitShortestPathContainer(size_t size) { container.resize(size); }
     void addShortestPathCollection(size_t startNodeIndex, const std::pair<size_t , std::vector<TransitShortestPath>>& shortestPathList);
     void addShortestPathCollection(size_t startNodeIndex, uint startingInstant, size_t graphSize, const TransitStateContainer& algorithmResultStates);
-    std::pair<size_t, std::vector<TransitShortestPath>> * getShortestPathsFrom(size_t startNodeIndex, uint earliestStartInstant);
+    std::pair<size_t, std::vector<TransitShortestPath>>& getShortestPathsFrom(size_t startNodeIndex, uint earliestStartInstant);
     TransitShortestPath getShortestPathToYFromTime(size_t startNodeIndex, uint earliestStartInstant, size_t goalNode);
 };
 
-- 
GitLab


From 34025488060a83f68ab91fa317c3cea0e6285299 Mon Sep 17 00:00:00 2001
From: Romain BERNARD <romain.bernard@uca.fr>
Date: Thu, 29 Aug 2024 17:12:46 +0200
Subject: [PATCH 221/327] reserve array instead of initiating default objects

---
 .../Multimodal/Heuristics/SimpleModularHeuristic.cpp        | 6 ++++--
 1 file changed, 4 insertions(+), 2 deletions(-)

diff --git a/src/algorithm/Multimodal/Heuristics/SimpleModularHeuristic.cpp b/src/algorithm/Multimodal/Heuristics/SimpleModularHeuristic.cpp
index c93d593..ca3cea5 100644
--- a/src/algorithm/Multimodal/Heuristics/SimpleModularHeuristic.cpp
+++ b/src/algorithm/Multimodal/Heuristics/SimpleModularHeuristic.cpp
@@ -7,7 +7,8 @@
 std::vector<TransitAccess> SimpleModularHeuristic::getBestTransitEntriesList(const Request &baseRequest) const {
     const auto& bestStationsIndexVector = _graph->getNode(
             baseRequest.getOriginNodeIndex()).getBestStationsNodeIdxVector();
-    std::vector<TransitAccess> results{bestStationsIndexVector.size()}; //init results vector to the appropriate size
+    std::vector<TransitAccess> results; //init results vector to the appropriate size
+    results.reserve(std::min(Constants::MAX_TRANSIT_ENTRY_CANDIDATES, bestStationsIndexVector.size()));
     //Iterate over the best stations saved prior
     for(const auto& bestStationNodeIdx : bestStationsIndexVector) {
         int maxDepartureTime = -1;
@@ -79,7 +80,8 @@ Request SimpleModularHeuristic::insertBestTransitEntryInRoute(const Request &bas
  * @return The subrequest successfully inserted in our route. This method's caller needs to add this request to its main request vector
  */
 Request SimpleModularHeuristic::insertBestTransitEntryInRoute(const Request &baseRequest, const std::vector<TransitAccess>& entriesAccessList, size_t requestId) {
-    std::vector<Request> entrySubRequestsList{Constants::MAX_TRANSIT_ENTRY_CANDIDATES}; //Init entry subrequests list to the appropriate size
+    std::vector<Request> entrySubRequestsList;
+    entrySubRequestsList.reserve(Constants::MAX_TRANSIT_ENTRY_CANDIDATES); //Init entry subrequests list to the appropriate size
     //Generate subrequests from best transit entries
     for(auto const& access : entriesAccessList) {
         entrySubRequestsList.emplace_back(*_graph, baseRequest, access, true);
-- 
GitLab


From c1a52f0fbc56f595d00321b7f9afc7257a515e85 Mon Sep 17 00:00:00 2001
From: Romain BERNARD <romain.bernard@uca.fr>
Date: Thu, 29 Aug 2024 17:48:18 +0200
Subject: [PATCH 222/327] add retro-compat format to request parsing

---
 src/instance/requests/Request.cpp | 31 +++++++++++++++++++++----------
 1 file changed, 21 insertions(+), 10 deletions(-)

diff --git a/src/instance/requests/Request.cpp b/src/instance/requests/Request.cpp
index 4c98afd..e812dd2 100644
--- a/src/instance/requests/Request.cpp
+++ b/src/instance/requests/Request.cpp
@@ -25,24 +25,35 @@ Request::Request(const DATRow& currentRow, const Graph& graph) {
     std::from_chars(currentRow[0].data(), currentRow[0].data() + currentRow[0].size(), _originNodeIndex);
     std::from_chars(currentRow[1].data(), currentRow[1].data() + currentRow[1].size(), _destinationNodeIndex);
 
-    int twMin, twMax;
+    uint twMin, twMax;
     bool setDepartureTW{false};
     bool setArrivalTW{false};
-    if(!currentRow[2].empty() && !currentRow[3].empty()) { //Departure TW
+    if(currentRow.size() == 8) { //More flexible 8 arguments initialization where we can set either origin or destination TW or both
+        if (!currentRow[2].empty() && !currentRow[3].empty()) { //Departure TW
+            std::from_chars(currentRow[2].data(), currentRow[2].data() + currentRow[2].size(), twMin);
+            std::from_chars(currentRow[3].data(), currentRow[3].data() + currentRow[3].size(), twMax);
+            _departureTW = TimeWindow(twMin, twMax);
+            setDepartureTW = true;
+        }
+        if (!currentRow[4].empty() && !currentRow[5].empty()) { //Arrival TW
+            std::from_chars(currentRow[4].data(), currentRow[4].data() + currentRow[4].size(), twMin);
+            std::from_chars(currentRow[5].data(), currentRow[5].data() + currentRow[5].size(), twMax);
+            _arrivalTW = TimeWindow(twMin, twMax);
+            setArrivalTW = true;
+        }
+
+        std::from_chars(currentRow[6].data(), currentRow[6].data() + currentRow[6].size(), _deltaTime);
+        std::from_chars(currentRow[7].data(), currentRow[7].data() + currentRow[7].size(), _weight);
+    } else if (currentRow.size() == 6) { //Original 6 inputs request creation, setting a destination time window (needed for compatibility)
         std::from_chars(currentRow[2].data(), currentRow[2].data() + currentRow[2].size(), twMin);
         std::from_chars(currentRow[3].data(), currentRow[3].data() + currentRow[3].size(), twMax);
-        _departureTW = TimeWindow(twMin, twMax);
-        setDepartureTW = true;
-    }
-    if(!currentRow[4].empty() && !currentRow[5].empty()) { //Arrival TW
-        std::from_chars(currentRow[4].data(), currentRow[4].data() + currentRow[4].size(), twMin);
-        std::from_chars(currentRow[5].data(), currentRow[5].data() + currentRow[5].size(), twMax);
         _arrivalTW = TimeWindow(twMin, twMax);
         setArrivalTW = true;
+
+        std::from_chars(currentRow[4].data(), currentRow[4].data() + currentRow[4].size(), _deltaTime);
+        std::from_chars(currentRow[5].data(), currentRow[5].data() + currentRow[5].size(), _weight);
     }
 
-    std::from_chars(currentRow[6].data(), currentRow[6].data() + currentRow[6].size(), _deltaTime);
-    std::from_chars(currentRow[7].data(), currentRow[7].data() + currentRow[7].size(), _weight);
 
     if(!setDepartureTW) {
         _departureTW.min = _arrivalTW.min - _deltaTime;
-- 
GitLab


From 5b8f42b8b7b5fb4f4797c1ffb96ee86ea33fcdfc Mon Sep 17 00:00:00 2001
From: Romain BERNARD <romain.bernard@uca.fr>
Date: Thu, 29 Aug 2024 17:49:44 +0200
Subject: [PATCH 223/327] link transit lines to nodes after they're all parsed
 to prevent stale refs

---
 src/instance/graph/Graph.cpp | 25 +++++++++++++++++++------
 src/instance/graph/Graph.h   |  3 ++-
 2 files changed, 21 insertions(+), 7 deletions(-)

diff --git a/src/instance/graph/Graph.cpp b/src/instance/graph/Graph.cpp
index febc131..f6e2dca 100644
--- a/src/instance/graph/Graph.cpp
+++ b/src/instance/graph/Graph.cpp
@@ -16,12 +16,7 @@
 #include "../../services/CSV/CSVRange.h"
 #include "Graph.h"
 
-std::vector<Line> Graph::addLine(Line& line) {
-    //Add line stops to nodes
-    for(int i = 0; i < line.size(); ++i)
-    {
-        nodesVector[line.getNode(i)].addBusLine(line, i);
-    }
+const std::vector<Line>& Graph::addLine(const Line &line) {
     //Add transit line to transit lines vector
     transitLines.push_back(line);
     return transitLines;
@@ -62,6 +57,7 @@ Graph::Graph(const std::string& nodesFilePath, const std::string& edgesFilePath,
         {
             parseLineRandomizedSchedule(row, rng, uint_dist10, uint_dist60);
         }
+        linkAllPTNodes();
     }
     std::cout << "test is done" << std::endl;
 }
@@ -115,6 +111,8 @@ Graph::Graph(const std::string& datFilePath) {
     while(infile >> currentRow && !currentRow[0].starts_with('#')) {
         this->parseLineRandomizedSchedule(currentRow, rng, uint_dist10, uint_dist60);
     }
+    //Make links once all lines are created to prevent stale refs
+    this->linkAllPTNodes();
 }
 
 namespace fs = std::filesystem;
@@ -371,3 +369,18 @@ void Graph::computeAndUpdateShortestTransitPaths() {
     }
     transitShortestPaths = shortestPathsContainer;
 }
+
+/**
+ * Clears every node's set of lines (to remove any eventual stale reference)
+ * then links every line's station to its referred node
+ */
+void Graph::linkAllPTNodes() {
+    for(auto& node : nodesVector) {
+        node.clearPTLineSet();
+    }
+    for(auto& line : getPTLines()) {
+        for(size_t i = 0; i < line.size(); ++i) {
+            nodesVector[line.getNode(i)].addBusLine(line, i);
+        }
+    }
+}
diff --git a/src/instance/graph/Graph.h b/src/instance/graph/Graph.h
index 0520351..8be160f 100644
--- a/src/instance/graph/Graph.h
+++ b/src/instance/graph/Graph.h
@@ -134,7 +134,7 @@ public:
      * @param line The Line to add. It's expected to be fully filled with its nodes schedules before adding to the graph
      * @return The updated vector containing all lines of the graph
      */
-    std::vector<Line> addLine(Line& line);
+    const std::vector<Line>& addLine(const Line &line);
     /**
      * Export graph data (nodes, edges, transit lines) to files to plot graph data with Python
      * The function creates the folders if need be, and will overwrite existing files if data has been outputted to this folder before
@@ -176,6 +176,7 @@ public:
     void computeAndUpdateClosestStations();
     void computeAndUpdateShortestTransitPaths();
 
+    void linkAllPTNodes();
 };
 
 
-- 
GitLab


From fb1936942198e3b824e43209deacf7e6f41df499 Mon Sep 17 00:00:00 2001
From: Romain BERNARD <romain.bernard@uca.fr>
Date: Thu, 29 Aug 2024 17:53:22 +0200
Subject: [PATCH 224/327] use refs in transit shortest paths/states via a
 reference wrapper instead of copies

---
 src/ShortestPath/ShortestPath.h               |  8 +++---
 .../Transit/TransitAlgorithmState.h           | 26 +++++++++----------
 .../Transit/TransitShortestPath.h             | 17 ++++++------
 .../Vehicle/VehicleShortestPath.h             |  8 +++---
 4 files changed, 30 insertions(+), 29 deletions(-)

diff --git a/src/ShortestPath/ShortestPath.h b/src/ShortestPath/ShortestPath.h
index f73bb23..713c797 100644
--- a/src/ShortestPath/ShortestPath.h
+++ b/src/ShortestPath/ShortestPath.h
@@ -20,12 +20,12 @@ public:
         return _keyPoints;
     }
 
-    virtual const KeyPoint* getDeparture() const {
-        return _keyPoints.cbegin().base();
+    virtual KeyPoint getDeparture() const {
+        return *_keyPoints.cbegin();
     }
 
-    virtual const KeyPoint* getArrival() const {
-        return (_keyPoints.cend() - 1).base();
+    virtual KeyPoint getArrival() const {
+        return *(_keyPoints.cend() - 1);
     }
 
     void replaceKeyPoint(int keyPointIndex, KeyPoint& value) {
diff --git a/src/ShortestPath/Transit/TransitAlgorithmState.h b/src/ShortestPath/Transit/TransitAlgorithmState.h
index d50da64..d9e463b 100644
--- a/src/ShortestPath/Transit/TransitAlgorithmState.h
+++ b/src/ShortestPath/Transit/TransitAlgorithmState.h
@@ -16,14 +16,14 @@ private:
     int _nodeIndex;
     int _instant{INT16_MAX};
     int _passageIndex{-1};
-    std::vector<LineStop> _connections{Constants::MAX_TRANSIT_CONNECTIONS};
+    std::vector<std::reference_wrapper<const LineStop>> _connections;//{Constants::MAX_TRANSIT_CONNECTIONS};
     int _precedingNodeIndex{-1};
 
 public:
     TransitAlgorithmState(int currentNode, int currentInstant, int currentPassageIndex, int precedingNodeIndex) :
             _nodeIndex(currentNode), _instant(currentInstant),
             _passageIndex(currentPassageIndex), _precedingNodeIndex(precedingNodeIndex) {
-        _connections.resize(Constants::MAX_TRANSIT_CONNECTIONS);
+        _connections.reserve(Constants::MAX_TRANSIT_CONNECTIONS);
     }
 
     TransitAlgorithmState(TransitAlgorithmState const& baseState) :
@@ -31,8 +31,8 @@ public:
     _passageIndex(baseState.getPassageIndex()), _precedingNodeIndex(baseState.getPrecedingNodeIndex()) {
         //Copy old connections
         _connections.clear();
-        _connections.resize(Constants::MAX_TRANSIT_CONNECTIONS);
-        for(auto& lineStop : baseState.getConnections()) {
+        _connections.reserve(Constants::MAX_TRANSIT_CONNECTIONS);
+        for(const auto& lineStop : baseState.getConnections()) {
             _connections.emplace_back(lineStop);
         }
     }
@@ -44,8 +44,8 @@ public:
     _passageIndex(baseState.getPassageIndex()), _precedingNodeIndex(baseState.getPrecedingNodeIndex()) {
         //Copy old connections
         _connections.clear();
-        _connections.resize(Constants::MAX_TRANSIT_CONNECTIONS);
-        for(auto& lineStop : baseState.getConnections()) {
+        _connections.reserve(Constants::MAX_TRANSIT_CONNECTIONS);
+        for(const auto& lineStop : baseState.getConnections()) {
             _connections.emplace_back(lineStop);
         }
 
@@ -53,11 +53,11 @@ public:
     }
 
     explicit TransitAlgorithmState(int nodeIndex) : _nodeIndex(nodeIndex) {
-        _connections.resize(Constants::MAX_TRANSIT_CONNECTIONS);
+        _connections.reserve(Constants::MAX_TRANSIT_CONNECTIONS);
     }
 
     explicit TransitAlgorithmState() : _nodeIndex(-1) {
-        _connections.resize(Constants::MAX_TRANSIT_CONNECTIONS);
+        _connections.reserve(Constants::MAX_TRANSIT_CONNECTIONS);
     }
 
     [[nodiscard]] int getNodeIndex() const {
@@ -72,7 +72,7 @@ public:
         return _passageIndex;
     }
 
-    [[nodiscard]] const std::vector<LineStop> &getConnections() const {
+    [[nodiscard]] const std::vector<std::reference_wrapper<const LineStop>> &getConnections() const {
         return _connections;
     }
 
@@ -88,7 +88,7 @@ public:
         return _connections.size();
     }
 
-    [[nodiscard]] LineStop getLastConnectionLineStop() const {
+    [[nodiscard]] const LineStop& getLastConnectionLineStop() const {
         return _connections.back();
     }
 
@@ -105,7 +105,7 @@ public:
     }
 
     [[nodiscard]] int getNextNodeIndex() const {
-        return _connections.back().getNextNodeIndex();
+        return _connections.back().get().getNextNodeIndex();
     }
 
     void setNodeIndex(int nodeIndex) {
@@ -192,11 +192,11 @@ public:
             res += ", Connections: ";
             if(_connections.size() > 1) {
                 for(int i = 0; i < _connections.size() - 1; ++i) {
-                    res += _connections[i].getLineRef().getLineId() + " -> ";
+                    res += _connections[i].get().getLineRef().getLineId() + " -> ";
                 }
             }
 
-            res += _connections[_connections.size() - 1].getLineRef().getLineId();
+            res += _connections[_connections.size() - 1].get().getLineRef().getLineId();
 
         }
 
diff --git a/src/ShortestPath/Transit/TransitShortestPath.h b/src/ShortestPath/Transit/TransitShortestPath.h
index ccbf88b..cf22868 100644
--- a/src/ShortestPath/Transit/TransitShortestPath.h
+++ b/src/ShortestPath/Transit/TransitShortestPath.h
@@ -9,14 +9,15 @@
 #include "../../instance/graph/LineStop.h"
 #include "TransitAlgorithmState.h"
 
-class TransitShortestPath : public ShortestPath<LineStop> {
+class TransitShortestPath : public ShortestPath<std::reference_wrapper<const LineStop>> {
 private:
     int _arrivalTime{-1};
 public:
     TransitShortestPath() = default;
 
     explicit TransitShortestPath(const TransitAlgorithmState& state) : _arrivalTime(state.getInstant()) {
-        std::move(state.getConnections().begin(), state.getConnections().end() - 1,_keyPoints.begin());
+        if(state.getNbConnections() > 0)
+            _keyPoints = state.getConnections();
     }
 
     /**
@@ -39,20 +40,20 @@ public:
                (this->getArrivalTime() == rhs.getArrivalTime() && this->getKeyPoints().size() > rhs.getKeyPoints().size());
     }
 
-    [[nodiscard]] const LineStop* getDeparture() const override {
-        return _keyPoints.cbegin().base();
+    [[nodiscard]] std::reference_wrapper<const LineStop> getDeparture() const override {
+        return *_keyPoints.cbegin();
     }
 
-    [[nodiscard]] const LineStop* getArrival() const override {
-        return (_keyPoints.cend() - 1).base();
+    [[nodiscard]] std::reference_wrapper<const LineStop> getArrival() const override {
+        return *(_keyPoints.cend() - 1);
     }
 
     [[nodiscard]] size_t getDepartureNode() const {
-        return getDeparture()->getNodeIndex();
+        return getDeparture().get().getNodeIndex();
     }
 
     [[nodiscard]] size_t getArrivalNode() const {
-        return getArrival()->getNodeIndex();
+        return getArrival().get().getNodeIndex();
     }
 
     [[nodiscard]] int getArrivalTime() const { return _arrivalTime; }
diff --git a/src/ShortestPath/Vehicle/VehicleShortestPath.h b/src/ShortestPath/Vehicle/VehicleShortestPath.h
index c756172..068b184 100644
--- a/src/ShortestPath/Vehicle/VehicleShortestPath.h
+++ b/src/ShortestPath/Vehicle/VehicleShortestPath.h
@@ -24,12 +24,12 @@ public:
         _duration = duration;
     }
 
-    [[nodiscard]] const size_t* getDeparture() const override {
-        return _keyPoints.cbegin().base();
+    [[nodiscard]] size_t getDeparture() const override {
+        return *_keyPoints.cbegin();
     }
 
-    [[nodiscard]] const size_t* getArrival() const override {
-        return (_keyPoints.cend() - 1).base();
+    [[nodiscard]] size_t getArrival() const override {
+        return *(_keyPoints.cend() - 1);
     }
 
     auto operator<=>(const VehicleShortestPath &rhs) const {
-- 
GitLab


From 6ddc77eeac4feb923c0aa52d9b5e15dccff5189e Mon Sep 17 00:00:00 2001
From: Romain BERNARD <romain.bernard@uca.fr>
Date: Thu, 29 Aug 2024 17:58:05 +0200
Subject: [PATCH 225/327] return const refs where appropriate to prevent errors
 and modifications via other objects

---
 src/instance/graph/Graph.cpp | 12 ++++++------
 src/instance/graph/Graph.h   |  6 +++---
 src/instance/graph/Line.h    |  4 ++--
 src/instance/graph/Node.cpp  | 12 ++++++++++++
 src/instance/graph/Node.h    | 10 +++++++---
 5 files changed, 30 insertions(+), 14 deletions(-)

diff --git a/src/instance/graph/Graph.cpp b/src/instance/graph/Graph.cpp
index f6e2dca..c802f9f 100644
--- a/src/instance/graph/Graph.cpp
+++ b/src/instance/graph/Graph.cpp
@@ -130,7 +130,7 @@ void Graph::exportGraphToFile(const fs::path& exportFolderPath) {
     //Edges
     if(!edgesVector.empty()) {
         outfileGraph << "#Edges format : node_in,node_out,length" << std::endl;
-        for (auto &edge: this->edgesVector) {
+        for (auto const &edge: this->edgesVector) {
             outfileGraph << edge.getStartNodeIdx() << "," << edge.getEndNodeIdx() << "," << edge.getLength() << std::endl;
         }
     }
@@ -283,9 +283,9 @@ void Graph::parseLineRandomizedSchedule(const DATRow& row, std::mt19937 rng,
         int travelTime = travelTimeDistribution(rng); //FIXME travel time is randomized for now, we should get edge length if it exists I guess
         std::vector<int> precedingTimeTable = newLine.getTimetable(i - 1);
         std::vector<int> newTimetable;
-        for(auto it = precedingTimeTable.begin(); it != precedingTimeTable.end(); ++it)
-        {
-            newTimetable.emplace_back(*it.base() + travelTime);
+        newTimetable.reserve(precedingTimeTable.size()); //Reserve to improve foreach efficiency
+        for(int const & it : precedingTimeTable) {
+            newTimetable.emplace_back(it + travelTime);
         }
         newLine.addTimetable(newTimetable);
         newTimetable.clear();
@@ -301,10 +301,10 @@ void Graph::createAndAddEdge(size_t edgeStartNodeIndex, size_t edgeEndNodeIndex,
     edgesVector.emplace_back(edgeStartNodeIndex, edgeEndNodeIndex, length);
 
     Node entryNode = nodesVector[edgeStartNodeIndex];
-    entryNode.getOutgoingEdges().emplace_back(edgesVector.size() - 1);
+    entryNode.emplaceBackOutgoingEdge(edgesVector.size() - 1);
 
     Node exitNode = nodesVector[edgeEndNodeIndex];
-    exitNode.getIncomingEdges().emplace_back(edgesVector.size() - 1);
+    exitNode.emplaceBackIncomingEdge(edgesVector.size() - 1);
 }
 
 void Graph::parseDistanceMatrix(std::ifstream &infile, DATRow currentRow) {
diff --git a/src/instance/graph/Graph.h b/src/instance/graph/Graph.h
index 8be160f..8ba9f58 100644
--- a/src/instance/graph/Graph.h
+++ b/src/instance/graph/Graph.h
@@ -53,7 +53,7 @@ public:
         return nodesVector.size();
     }
 
-    [[nodiscard]] std::vector<LineStop> getPTLinesSet(size_t nodeIndex) const {
+    [[nodiscard]] const std::vector<LineStop> & getPTLinesSet(size_t nodeIndex) const {
         return nodesVector[nodeIndex].getPTLinesSet();
     }
 
@@ -97,7 +97,7 @@ public:
      * @param edge The edge to push in the graph's edge vector
      * @return The edge vector after having added the edge
      */
-    std::vector<Edge> addEdge(Edge const& edge) {
+    const std::vector<Edge>& addEdge(Edge const& edge) {
         edgesVector.push_back(edge);
         return edgesVector;
     }
@@ -107,7 +107,7 @@ public:
      * @param node The node to push in the graph's node vector
      * @return The node vector after having added the node
      */
-    std::vector<Node> addNode(Node const& node) {
+    const std::vector<Node>& addNode(Node const& node) {
         nodesVector.push_back(node);
         return nodesVector;
     }
diff --git a/src/instance/graph/Line.h b/src/instance/graph/Line.h
index a262c1a..fb2c54b 100644
--- a/src/instance/graph/Line.h
+++ b/src/instance/graph/Line.h
@@ -22,13 +22,13 @@ public:
 
     [[nodiscard]] const std::string &getLineId() const;
     void setLineId(const std::string &lineId);
-    [[nodiscard]] std::vector<int> getNodes() const { return _nodes;};
+    [[nodiscard]] const std::vector<int>& getNodes() const { return _nodes;};
     [[nodiscard]] int getNode(size_t index) const { return _nodes[index];};
     void addNode(const int node){this->_nodes.emplace_back(node);};
     [[nodiscard]] bool isEmpty() const{return this->_nodes.empty() || _timetables.empty();}
 
     [[nodiscard]] const std::vector<int>& getTimetable(size_t pos) const{ return _timetables[pos];};
-    [[nodiscard]] std::vector<std::vector<int>> getTimetables() const{ return _timetables;};
+    [[nodiscard]] const std::vector<std::vector<int>>& getTimetables() const{ return _timetables;};
     void addTimetable(const std::vector<int>& timetable) { _timetables.push_back(timetable);};
     void setTimetable(size_t pos, const std::vector<int>& timetable) { _timetables.insert(_timetables.begin() + pos, timetable);};
 
diff --git a/src/instance/graph/Node.cpp b/src/instance/graph/Node.cpp
index 83f0593..0d8ead6 100644
--- a/src/instance/graph/Node.cpp
+++ b/src/instance/graph/Node.cpp
@@ -59,3 +59,15 @@ const std::vector<size_t> & Node::getBestStationsNodeIdxVector() const {
 void Node::setBestStationsNodeIdxVector(const std::vector<size_t> &bestStationsOrderedVector) {
     _bestStationsNodeIdxVector = bestStationsOrderedVector;
 }
+
+void Node::clearPTLineSet() {
+    _ptLines.clear();
+}
+
+void Node::emplaceBackOutgoingEdge(size_t outgoingEdgeIndex) {
+    _outgoingEdgesIndex.emplace_back(outgoingEdgeIndex);
+}
+
+void Node::emplaceBackIncomingEdge(size_t incomingEdgeIndex) {
+    _incomingEdgesIndex.emplace_back(incomingEdgeIndex);
+}
diff --git a/src/instance/graph/Node.h b/src/instance/graph/Node.h
index a18eea5..7285f81 100644
--- a/src/instance/graph/Node.h
+++ b/src/instance/graph/Node.h
@@ -74,9 +74,9 @@ public:
     [[nodiscard]] double getX() const {return _x;}
     [[nodiscard]] double getY() const {return _y;}
     [[nodiscard]] Status getStatus() const {return _status;}
-    [[nodiscard]] std::vector<int> getIncomingEdges() const {return _incomingEdgesIndex;}
-    [[nodiscard]] std::vector<int> getOutgoingEdges() const {return _outgoingEdgesIndex;}
-    [[nodiscard]] std::vector<LineStop> getPTLinesSet() const {return _ptLines;}
+    [[nodiscard]] const std::vector<int> & getIncomingEdges() const {return _incomingEdgesIndex;}
+    [[nodiscard]] const std::vector<int> & getOutgoingEdges() const {return _outgoingEdgesIndex;}
+    [[nodiscard]] const std::vector<LineStop> & getPTLinesSet() const {return _ptLines;}
 
     /**
      * Verify if _x, _y and _status are equal to check for node equality
@@ -92,9 +92,13 @@ public:
     bool operator!=(const Node& rhs) const;
 
     void emplaceBackClosestStation(size_t closestStationIdx);
+    void emplaceBackOutgoingEdge(size_t outgoingEdgeIndex);
+    void emplaceBackIncomingEdge(size_t incomingEdgeIndex);
 
     [[nodiscard]] const std::vector<size_t>& getBestStationsNodeIdxVector() const;
     void setBestStationsNodeIdxVector(const std::vector<size_t> &bestStationsOrderedVector);
+
+    void clearPTLineSet();
 };
 #include "Line.h"
 #include "LineStop.h"
-- 
GitLab


From e1f8dfbd569a06df96a5cf4f68b20b58a8d02305 Mon Sep 17 00:00:00 2001
From: Romain BERNARD <romain.bernard@uca.fr>
Date: Thu, 29 Aug 2024 17:59:23 +0200
Subject: [PATCH 226/327] fix transit shortest path updating

---
 src/instance/graph/Graph.cpp | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/src/instance/graph/Graph.cpp b/src/instance/graph/Graph.cpp
index c802f9f..18bf4a9 100644
--- a/src/instance/graph/Graph.cpp
+++ b/src/instance/graph/Graph.cpp
@@ -363,7 +363,7 @@ void Graph::computeAndUpdateShortestTransitPaths() {
         for(size_t i = 0; i < ptLine.size(); ++i) {
             for (auto& startingTime: ptLine.getTimetable(i)) {
                 const TransitStateContainer &results = TransitShortestPathPrecompute::executeAlgorithm(*this,ptLine.getNode(i),startingTime);
-                shortestPathsContainer.addShortestPathCollection(i, startingTime, getNbNodes(), results);
+                shortestPathsContainer.addShortestPathCollection(ptLine.getNode(i), startingTime, getNbNodes(), results);
             }
         }
     }
-- 
GitLab


From af946a5490ebf43f30c74a72736d8348599d0e0d Mon Sep 17 00:00:00 2001
From: Romain BERNARD <romain.bernard@uca.fr>
Date: Thu, 29 Aug 2024 18:03:41 +0200
Subject: [PATCH 227/327] vehicle shortest paths expand API to use edges

---
 .../Vehicle/MatrixShortestPathContainer.h     |  2 +-
 .../VehicleShortestPathCalculation.cpp        | 19 ++++++++++++++++---
 .../Vehicle/VehicleShortestPathCalculation.h  |  8 ++++++--
 src/instance/graph/Graph.h                    |  6 +++++-
 4 files changed, 28 insertions(+), 7 deletions(-)

diff --git a/src/ShortestPath/Vehicle/MatrixShortestPathContainer.h b/src/ShortestPath/Vehicle/MatrixShortestPathContainer.h
index 740102e..ea12887 100644
--- a/src/ShortestPath/Vehicle/MatrixShortestPathContainer.h
+++ b/src/ShortestPath/Vehicle/MatrixShortestPathContainer.h
@@ -21,7 +21,7 @@ public:
      * Moves the given shortestPathsMatrix to initialize the container with the given distances.
      * @param shortestPathsMatrix
      */
-    explicit MatrixShortestPathContainer(std::vector<std::vector<uint>> shortestPathsMatrix) : _distanceMatrix(std::move(shortestPathsMatrix)) {}
+    explicit MatrixShortestPathContainer(std::vector<std::vector<uint>>& shortestPathsMatrix) : _distanceMatrix(std::move(shortestPathsMatrix)) {}
 
     explicit MatrixShortestPathContainer(size_t matrixSize) {
         _distanceMatrix.resize(matrixSize);
diff --git a/src/ShortestPath/Vehicle/VehicleShortestPathCalculation.cpp b/src/ShortestPath/Vehicle/VehicleShortestPathCalculation.cpp
index e9fd2a2..ded39ca 100644
--- a/src/ShortestPath/Vehicle/VehicleShortestPathCalculation.cpp
+++ b/src/ShortestPath/Vehicle/VehicleShortestPathCalculation.cpp
@@ -9,7 +9,12 @@
 
 std::vector<uint>
 VehicleShortestPathCalculation::computeShortestPathsFromNode(Graph &graph, size_t startingNodeIdx, bool useEdges) {
-    std::vector<uint> results{graph.getShortestSaevPaths()[startingNodeIdx]};
+    std::vector<uint> results;
+    results.reserve(graph.getNbNodes());
+
+    if(!useEdges)
+        results = graph.getShortestSaevPaths()[startingNodeIdx];
+
     std::vector<bool> mark(graph.getNbNodes(),false);
     std::priority_queue<VehiclePathState,std::vector<VehiclePathState>, std::greater<>> stateQueue{};
 
@@ -44,18 +49,26 @@ VehicleShortestPathCalculation::computeShortestPathsFromNode(Graph &graph, size_
 }
 
 MatrixShortestPathContainer VehicleShortestPathCalculation::computeShortestPathsForGraph(Graph &graph) {
+    return computeShortestPathsForGraph(graph, false);
+}
+
+MatrixShortestPathContainer VehicleShortestPathCalculation::computeShortestPathsForGraph(Graph &graph, bool useEdges) {
     std::vector<std::vector<uint>> results;
     results.resize(graph.getNbNodes());
     for(size_t i = 0; i < graph.getNbNodes(); ++i) {
         results[i].resize(graph.getNbNodes());
-        std::ranges::move(computeShortestPathsFromNode(graph, i, false), results[i].begin());
+        std::ranges::move(computeShortestPathsFromNode(graph, i, useEdges), results[i].begin());
     }
 
     return MatrixShortestPathContainer(results);
 }
 
 void VehicleShortestPathCalculation::computeAndUpdateShortestPathsForGraph(Graph &graph) {
-    MatrixShortestPathContainer results = computeShortestPathsForGraph(graph);
+    computeAndUpdateShortestPathsForGraph(graph, false);
+}
+
+void VehicleShortestPathCalculation::computeAndUpdateShortestPathsForGraph(Graph &graph, bool useEdges) {
+    MatrixShortestPathContainer results = computeShortestPathsForGraph(graph, useEdges);
     graph.setShortestSaevPaths(results.getDistanceMatrix());
 }
 
diff --git a/src/ShortestPath/Vehicle/VehicleShortestPathCalculation.h b/src/ShortestPath/Vehicle/VehicleShortestPathCalculation.h
index 11f9b4c..b7be764 100644
--- a/src/ShortestPath/Vehicle/VehicleShortestPathCalculation.h
+++ b/src/ShortestPath/Vehicle/VehicleShortestPathCalculation.h
@@ -17,13 +17,13 @@ public:
      * Computes shortest paths from the given graph's distance matrix
      * @param graph
      */
-    static void computeAndUpdateShortestPathsForGraph(Graph& graph);
+    static void computeAndUpdateShortestPathsForGraph(Graph &graph, bool useEdges);
     /**
      * Computes and returns an updated distance matrix from the given graph's distance matrix computed via Dijsktra's algorithm
      * @param graph
      * @return A matrix distances container
      */
-    static MatrixShortestPathContainer computeShortestPathsForGraph(Graph& graph);
+    static MatrixShortestPathContainer computeShortestPathsForGraph(Graph &graph, bool useEdges);
     /**
      * Computes the shortest paths to all the nodes in the graph from the given starting node.
      * If a node is unreachable its default distance is INT32_MAX. Distance from the starting node to itself is 0
@@ -45,6 +45,10 @@ private:
                                      std::priority_queue<VehiclePathState, std::vector<VehiclePathState>, std::greater<>> &stateQueue, const Graph& graph);
     static void expandStatesViaMatrix(const VehiclePathState& currentState, std::vector<uint> &results,
                                       std::priority_queue<VehiclePathState, std::vector<VehiclePathState>, std::greater<>> &stateQueue, const Graph& graph);
+
+    void computeAndUpdateShortestPathsForGraph(Graph &graph);
+
+    MatrixShortestPathContainer computeShortestPathsForGraph(Graph &graph);
 };
 #include "../../instance/graph/Graph.h"
 
diff --git a/src/instance/graph/Graph.h b/src/instance/graph/Graph.h
index 8ba9f58..31bee50 100644
--- a/src/instance/graph/Graph.h
+++ b/src/instance/graph/Graph.h
@@ -169,7 +169,11 @@ public:
     const size_t getNbClosestStations(size_t nodeIdx);
 
     void computeAndUpdateShortestPathsMatrix() {
-        VehicleShortestPathCalculation::computeAndUpdateShortestPathsForGraph(*this);
+        VehicleShortestPathCalculation::computeAndUpdateShortestPathsForGraph(*this, false);
+    }
+
+    void computeAndUpdateShortestPathsMatrix(bool useEdges) {
+        VehicleShortestPathCalculation::computeAndUpdateShortestPathsForGraph(*this, useEdges);
     }
 
     void computeAndUpdateClosestStationsForNode(size_t nodeIdx);
-- 
GitLab


From 78485cac3159e63607fdc914dfb98604ce5984e2 Mon Sep 17 00:00:00 2001
From: Romain BERNARD <romain.bernard@uca.fr>
Date: Thu, 29 Aug 2024 18:06:03 +0200
Subject: [PATCH 228/327] remove useless operator definitions

---
 src/ShortestPath/Transit/TransitAlgorithmState.h           | 6 ------
 src/ShortestPath/Transit/TransitShortestPathPrecompute.cpp | 5 ++---
 2 files changed, 2 insertions(+), 9 deletions(-)

diff --git a/src/ShortestPath/Transit/TransitAlgorithmState.h b/src/ShortestPath/Transit/TransitAlgorithmState.h
index d9e463b..3151442 100644
--- a/src/ShortestPath/Transit/TransitAlgorithmState.h
+++ b/src/ShortestPath/Transit/TransitAlgorithmState.h
@@ -37,8 +37,6 @@ public:
         }
     }
 
-    TransitAlgorithmState(TransitAlgorithmState&& baseStatePointer) = default;
-
     TransitAlgorithmState(TransitAlgorithmState const& baseState, const LineStop& newConnection) :
     _nodeIndex(baseState.getNodeIndex()), _instant(baseState.getInstant()),
     _passageIndex(baseState.getPassageIndex()), _precedingNodeIndex(baseState.getPrecedingNodeIndex()) {
@@ -135,8 +133,6 @@ public:
         }
     }
 
-    bool canAddNewConnection() const {return _connections.size() < _connections.max_size(); }
-
     /**
      * Strict dominance between two transit shortest path states happens if state *this* has :
      * 1) lower amount of connections and same arrival time OR 2) lower arrival time than the state rhs
@@ -182,8 +178,6 @@ public:
                 || this->getConnections().size() != rhs.getConnections().size();
     }
 
-    TransitAlgorithmState& operator=(const TransitAlgorithmState& baseState) = default;
-
     [[nodiscard]] std::string toString() const {
         std::string res = "Node: " + std::to_string(_nodeIndex) + ", Instant: " + std::to_string(_instant);
 
diff --git a/src/ShortestPath/Transit/TransitShortestPathPrecompute.cpp b/src/ShortestPath/Transit/TransitShortestPathPrecompute.cpp
index 70d1208..5f592fb 100644
--- a/src/ShortestPath/Transit/TransitShortestPathPrecompute.cpp
+++ b/src/ShortestPath/Transit/TransitShortestPathPrecompute.cpp
@@ -23,15 +23,14 @@ TransitStateContainer TransitShortestPathPrecompute::executeAlgorithm(const Grap
     std::priority_queue<TransitAlgorithmState> statePriorityQueue;
     statePriorityQueue.emplace(nodeIndex, instant,0, nodeIndex);
 
-    TransitAlgorithmState currentState;
     while(!statePriorityQueue.empty())
     {
         //Extract head from our state priority queue
-        currentState = statePriorityQueue.top();
+        TransitAlgorithmState currentState = statePriorityQueue.top();
         statePriorityQueue.pop();
         if(!solutionsContainer.strictlyDominates(currentState)) {
             DEBUG_MSG("\n\nComparing state " + currentState.toString() + " and " + solutionsContainer.getBestSolution(currentState.getNodeIndex(), currentState.getNbConnections()).toString());
-            for (auto const& lineStop : graph.getPTLinesSet(currentState.getNodeIndex()))
+            for (const auto& lineStop : graph.getPTLinesSet(currentState.getNodeIndex()))
             {
                 int nextNode = lineStop.getNextNodeIndex();
                 //If there is a proper next node and if it's not the same as our last used line stop predecessor
-- 
GitLab


From f8dff41edc57ec0bfc07267b720822d7c6f6cdf8 Mon Sep 17 00:00:00 2001
From: Romain BERNARD <romain.bernard@uca.fr>
Date: Thu, 29 Aug 2024 18:06:50 +0200
Subject: [PATCH 229/327] use line refs in LineStop

---
 src/ShortestPath/Transit/TransitAlgorithmState.h |  4 ++--
 src/instance/graph/LineStop.h                    | 11 ++---------
 2 files changed, 4 insertions(+), 11 deletions(-)

diff --git a/src/ShortestPath/Transit/TransitAlgorithmState.h b/src/ShortestPath/Transit/TransitAlgorithmState.h
index 3151442..cf90ba2 100644
--- a/src/ShortestPath/Transit/TransitAlgorithmState.h
+++ b/src/ShortestPath/Transit/TransitAlgorithmState.h
@@ -90,8 +90,8 @@ public:
         return _connections.back();
     }
 
-    [[nodiscard]] Line getLastConnectionLine() const {
-        return _connections.back().getLineRef();
+    [[nodiscard]] const Line& getLastConnectionLine() const {
+        return _connections.back().get().getLineRef();
     }
 
     [[nodiscard]] int getPrecedingNodeIndex() const {
diff --git a/src/instance/graph/LineStop.h b/src/instance/graph/LineStop.h
index a98f078..44c4093 100644
--- a/src/instance/graph/LineStop.h
+++ b/src/instance/graph/LineStop.h
@@ -12,14 +12,13 @@
 
 class LineStop {
 private:
-    Line _lineRef; //reference to the line
+    const Line& _lineRef; //reference to the line
     int _stopIndex{}; //index for the stop relative to this node in the Line object
 
 public:
-    LineStop() = default;
     LineStop(const Line& lineRef, int stopIndex) : _lineRef(lineRef), _stopIndex(stopIndex) {}
 
-    [[nodiscard]] Line getLineRef() const {
+    [[nodiscard]] const Line& getLineRef() const {
         return _lineRef;
     }
 
@@ -78,12 +77,6 @@ public:
 
     bool operator<(LineStop const& rhs) const {return &this->_lineRef < &rhs._lineRef;} //just check line addresses. Basically we just don't want the exact same line twice
 
-    LineStop& operator=(LineStop const& rhs) {
-        _lineRef = rhs.getLineRef();
-        _stopIndex = rhs.getStopIndex();
-        return *this;
-    }
-
     [[nodiscard]] const std::vector<int>& getSchedule() const {
         return _lineRef.getTimetable(_stopIndex);
     }
-- 
GitLab


From 818ea74a6d66d9e0cc243c36f44ca20cb807787f Mon Sep 17 00:00:00 2001
From: Romain BERNARD <romain.bernard@uca.fr>
Date: Thu, 29 Aug 2024 18:08:38 +0200
Subject: [PATCH 230/327] vehicle shortest paths expand API to use edges

---
 src/ShortestPath/Transit/TransitAlgorithmState.h | 4 ++++
 src/ShortestPath/Transit/TransitStateContainer.h | 2 +-
 2 files changed, 5 insertions(+), 1 deletion(-)

diff --git a/src/ShortestPath/Transit/TransitAlgorithmState.h b/src/ShortestPath/Transit/TransitAlgorithmState.h
index cf90ba2..d3a544e 100644
--- a/src/ShortestPath/Transit/TransitAlgorithmState.h
+++ b/src/ShortestPath/Transit/TransitAlgorithmState.h
@@ -153,6 +153,8 @@ public:
      * @return
      */
     bool operator<(const TransitAlgorithmState& rhs) const {
+        if(this->_nodeIndex != -1 && rhs._nodeIndex == -1)
+            return true;
         return this->_nodeIndex == rhs.getNodeIndex() //same current node
                 && (this->getInstant() < rhs.getInstant() //strictly better time
                 || (this->getInstant() == rhs.getInstant()
@@ -160,6 +162,8 @@ public:
     }
 
     bool operator>(const TransitAlgorithmState& rhs) const {
+        if(this->_nodeIndex != -1 && rhs._nodeIndex == -1)
+            return false;
         return this->_nodeIndex == rhs.getNodeIndex() //same current node
                 && (this->getInstant() > rhs.getInstant()
                 || (this->getInstant() == rhs.getInstant()
diff --git a/src/ShortestPath/Transit/TransitStateContainer.h b/src/ShortestPath/Transit/TransitStateContainer.h
index 048961e..1cfb2a1 100644
--- a/src/ShortestPath/Transit/TransitStateContainer.h
+++ b/src/ShortestPath/Transit/TransitStateContainer.h
@@ -36,7 +36,7 @@ public:
      * @return The first solution of potentially two saved in this array
      */
     [[nodiscard]] const TransitAlgorithmState& getBestSolution(int nodeIndex) const{
-        if(solutionVector[1] < solutionVector[0])
+        if(solutionVector[nodeIndex][1] < solutionVector[nodeIndex][0])
             return solutionVector[nodeIndex][1];
         else
             return solutionVector[nodeIndex][0];
-- 
GitLab


From 7148da730feb5a8c44f215af9d4da06fb54cec1d Mon Sep 17 00:00:00 2001
From: Romain BERNARD <romain.bernard@uca.fr>
Date: Thu, 29 Aug 2024 18:09:37 +0200
Subject: [PATCH 231/327] update the sub request in a better fashion while
 testing candidate insertions

---
 .../Heuristics/SimpleModularHeuristic.cpp     | 40 +++++++++++++++----
 .../Heuristics/SimpleModularHeuristic.h       | 16 +++++++-
 2 files changed, 47 insertions(+), 9 deletions(-)

diff --git a/src/algorithm/Multimodal/Heuristics/SimpleModularHeuristic.cpp b/src/algorithm/Multimodal/Heuristics/SimpleModularHeuristic.cpp
index ca3cea5..074f36c 100644
--- a/src/algorithm/Multimodal/Heuristics/SimpleModularHeuristic.cpp
+++ b/src/algorithm/Multimodal/Heuristics/SimpleModularHeuristic.cpp
@@ -96,22 +96,23 @@ Request SimpleModularHeuristic::insertBestTransitEntryInRoute(const Request &bas
  * @param requestId ID/index in the request vector for our base request
  * @return The subrequest successfully inserted in our route. This method's caller needs to add this request to its main request vector
  */
-Request SimpleModularHeuristic::insertBestTransitEntryInRoute(const std::vector<Request>& entrySubRequestsList, size_t requestId) {
+const Request &
+SimpleModularHeuristic::insertBestTransitEntryInRoute(const std::vector<Request>& entrySubRequestsList, size_t requestId) {
     for(const auto& subreq : entrySubRequestsList) {
-        _route->getEntrySubRequestOrigin(requestId).setRequest(&subreq);
-        _route->getEntrySubRequestDestination(requestId).setRequest(&subreq);
+        updateSubRequest(requestId, subreq, true);
         SAEVRouteChangelist changeList = BestInsertionHeuristic::tryBestRequestInsertionInActiveVehicle(_route->getEntrySubRequestOrigin(requestId), *_route);
         //If we've found an insertion that doesn't create a vehicle, stop there
         if(changeList.success()) {
-            return subreq;
+            return getSubrequest(requestId, true);
+        } else {
+            changeList.revertChanges();
         }
     }
 
     //If no active vehicle insertion worked, do best insertion on a new vehicle with the first subrequest (supposedly it's the most advantageous)
-    _route->getEntrySubRequestOrigin(requestId).setRequest(&entrySubRequestsList[0]);
-    _route->getEntrySubRequestDestination(requestId).setRequest(&entrySubRequestsList[0]);
+    updateSubRequest(requestId, entrySubRequestsList[0], true);
     _route->insertRequestInNewVehicle(_route->getEntrySubRequestOrigin(requestId));
-    return entrySubRequestsList[0];
+    return getSubrequest(requestId, true);
 }
 
 const Graph *SimpleModularHeuristic::getGraph() const {
@@ -129,3 +130,28 @@ SAEVRoute *SimpleModularHeuristic::getRoute() const {
 void SimpleModularHeuristic::setRoute(SAEVRoute *route) {
     _route = route;
 }
+
+void SimpleModularHeuristic::updateSubRequest(size_t requestId, const Request &request, bool isEntry) {
+    size_t subRequestIndex = getSubrequestIndex(requestId, isEntry);
+    if(_requestsVect->size() < subRequestIndex) {
+        _requestsVect->emplace_back(request);
+        assertm(_requestsVect->size() == subRequestIndex,"A request seems to have been missed or doesn't have any subrequest defined");
+    } else {
+        _requestsVect->assign(subRequestIndex, request);
+    }
+
+    std::vector<Request>& requestVectRef = *_requestsVect;
+    _route->getEntrySubRequestOrigin(requestId).setRequest(&requestVectRef[subRequestIndex]);
+    _route->getEntrySubRequestDestination(requestId).setRequest(&requestVectRef[subRequestIndex]);
+}
+
+size_t SimpleModularHeuristic::getSubrequestIndex(size_t requestId, bool isEntry) const {
+    if(isEntry)
+        return _nbBaseRquests + requestId;
+    else
+        return _nbBaseRquests*2 + requestId;
+}
+
+const Request& SimpleModularHeuristic::getSubrequest(size_t requestId, bool isEntry) {
+    return (*_requestsVect)[getSubrequestIndex(requestId, isEntry)];
+}
diff --git a/src/algorithm/Multimodal/Heuristics/SimpleModularHeuristic.h b/src/algorithm/Multimodal/Heuristics/SimpleModularHeuristic.h
index a0567e4..f7c3ceb 100644
--- a/src/algorithm/Multimodal/Heuristics/SimpleModularHeuristic.h
+++ b/src/algorithm/Multimodal/Heuristics/SimpleModularHeuristic.h
@@ -5,6 +5,10 @@
 #ifndef GREEDYALGORITHM_SIMPLEMODULARHEURISTIC_H
 #define GREEDYALGORITHM_SIMPLEMODULARHEURISTIC_H
 
+// uncomment to disable assert()
+// #define NDEBUG
+#include <cassert>
+#define assertm(exp, msg) assert(((void)msg, exp))
 
 #include <cstddef>
 #include <vector>
@@ -19,13 +23,15 @@ private:
     const Graph* _graph{nullptr};
     SAEVRoute* _route{nullptr};
     std::vector<Request>* _requestsVect{nullptr};
+    size_t _nbBaseRquests;
 
     //Add friend test classes to test inner workings without making the whole API public
     FRIEND_TEST(MultimodalInsertionHeuristicDebug, DebugBaseInstance);
 
 //Public interface to interact with the modular heuristic
 public:
-    SimpleModularHeuristic(const Graph *graph, SAEVRoute *route, std::vector<Request>* requestsVect) : _graph(graph), _route(route), _requestsVect(requestsVect) {}
+    SimpleModularHeuristic(const Graph *graph, SAEVRoute *route, std::vector<Request>* requestsVect) : _graph(graph), _route(route),
+    _requestsVect(requestsVect), _nbBaseRquests(requestsVect->size()) {}
 
     void multimodalRequestsInsertion(const std::vector<Request>& requestsToInsert);
 
@@ -34,7 +40,7 @@ private:
 
     Request insertBestTransitEntryInRoute(const Request &baseRequest, size_t requestId);
     Request insertBestTransitEntryInRoute(const Request &baseRequest, const std::vector<TransitAccess>& entriesAccessList, size_t requestId);
-    Request insertBestTransitEntryInRoute(const std::vector<Request>& entrySubRequestsList, size_t requestId);
+    const Request & insertBestTransitEntryInRoute(const std::vector<Request>& entrySubRequestsList, size_t requestId);
 
     std::vector<Request> generateAndInsertBestEntries(const std::vector<Request> &baseRequestsList);
     void insertBestTransitExitsInRoute(const std::vector<Request>& baseRequestsList, const std::vector<TransitAccess>& transitEntriesList);
@@ -85,6 +91,12 @@ protected:
 
     [[nodiscard]] SAEVRoute *getRoute() const;
     void setRoute(SAEVRoute *route);
+
+    void updateSubRequest(size_t requestId, const Request &request, bool isEntry);
+
+    size_t getSubrequestIndex(size_t requestId, bool isEntry) const;
+
+    const Request &getSubrequest(size_t requestId, bool isEntry);
 };
 
 
-- 
GitLab


From 2be19a364f28abefa05c338af8f7576acf88f600 Mon Sep 17 00:00:00 2001
From: Romain BERNARD <romain.bernard@uca.fr>
Date: Thu, 29 Aug 2024 18:11:10 +0200
Subject: [PATCH 232/327] fix tests after refactors

---
 test/CMakeLists.txt                     | 2 ++
 test/src/ConstraintPropagationDebug.cpp | 2 +-
 test/src/GraphPreprocessDebug.cpp       | 2 +-
 3 files changed, 4 insertions(+), 2 deletions(-)

diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt
index b74b502..16ba125 100644
--- a/test/CMakeLists.txt
+++ b/test/CMakeLists.txt
@@ -37,6 +37,8 @@ add_executable(Transit_Preprocess_DEB
         ../src/ShortestPath/Transit/TransitShortestPathPrecompute.cpp
         ../src/ShortestPath/Transit/TransitShortestPathPrecompute.h
         ../src/utils/Globals.h
+        ../src/ShortestPath/Vehicle/VehicleShortestPathCalculation.cpp
+        ../src/ShortestPath/Vehicle/VehicleShortestPathCalculation.h
 )
 
 
diff --git a/test/src/ConstraintPropagationDebug.cpp b/test/src/ConstraintPropagationDebug.cpp
index 6a76639..116ff10 100644
--- a/test/src/ConstraintPropagationDebug.cpp
+++ b/test/src/ConstraintPropagationDebug.cpp
@@ -75,7 +75,7 @@ TEST(ConstraintPropagationDebug, DebugInstanceAlain) {
     //Parse graph
     Graph graphFromSingleFile(instancesPath + instanceFolder + graphDatFile);
     std::vector<Request> requests = Request::getRequestsFromFile(instancesPath + instanceFolder + requestsDatFile, graphFromSingleFile);
-    VehicleShortestPathCalculation::computeAndUpdateShortestPathsForGraph(graphFromSingleFile);
+    VehicleShortestPathCalculation::computeAndUpdateShortestPathsForGraph(graphFromSingleFile, false);
     //Init instance
     Instance instance(requests,graphFromSingleFile,4);
     SAEVRoute routesContainer(graphFromSingleFile, requests);
diff --git a/test/src/GraphPreprocessDebug.cpp b/test/src/GraphPreprocessDebug.cpp
index 40870da..f47e62d 100644
--- a/test/src/GraphPreprocessDebug.cpp
+++ b/test/src/GraphPreprocessDebug.cpp
@@ -13,7 +13,7 @@ TEST(GraphPreprocessDebug, DebugBookInstance) {
 
     //Parse graph
     Graph graph(instancesPath + instanceFolder + graphDatFile);
-    VehicleShortestPathCalculation::computeAndUpdateShortestPathsForGraph(graph);
+    VehicleShortestPathCalculation::computeAndUpdateShortestPathsForGraph(graph, false);
 
     std::string exportFolder = "../../resources/test/outputs/preprocess_debug/";
     graph.exportGraphToFile(exportFolder + instanceFolder);
-- 
GitLab


From 736f3c9d19434ad8937507942123c61d678342d3 Mon Sep 17 00:00:00 2001
From: Romain BERNARD <romain.bernard@uca.fr>
Date: Thu, 29 Aug 2024 18:12:03 +0200
Subject: [PATCH 233/327] fix tests set transit precomputation results in the
 appropriate index

---
 test/src/TransitPreprocessDebug.cpp | 12 ++++--------
 1 file changed, 4 insertions(+), 8 deletions(-)

diff --git a/test/src/TransitPreprocessDebug.cpp b/test/src/TransitPreprocessDebug.cpp
index e263e9d..419efe7 100644
--- a/test/src/TransitPreprocessDebug.cpp
+++ b/test/src/TransitPreprocessDebug.cpp
@@ -18,9 +18,8 @@ TEST(Transit_Preprocess_DEB, DebugFunction) {
     for(auto& ptLine : graphFromSingleFile.getPTLines()) {
         for(int i = 0; i < ptLine.size(); ++i) {
             for (auto& startingTime: ptLine.getTimetable(i)) {
-                contiguousContainer.addShortestPathCollection(i, startingTime, graphFromSingleFile.getNbNodes(),
+                contiguousContainer.addShortestPathCollection(ptLine.getNode(i), startingTime, graphFromSingleFile.getNbNodes(),
                         TransitShortestPathPrecompute::executeAlgorithm(graphFromSingleFile, ptLine.getNode(i),startingTime));
-                contiguousContainer.getShortestPathsFrom(i, startingTime - 1);
             }
         }
     }
@@ -30,9 +29,8 @@ TEST(Transit_Preprocess_DEB, DebugFunction) {
     for(auto& ptLine : crossingLinesGraph.getPTLines()) {
         for(int i = 0; i < ptLine.size(); ++i) {
             for (auto& startingTime: ptLine.getTimetable(i)) {
-                crossingContainer.addShortestPathCollection(i, startingTime, crossingLinesGraph.getNbNodes(),
+                crossingContainer.addShortestPathCollection(ptLine.getNode(i), startingTime, crossingLinesGraph.getNbNodes(),
                         TransitShortestPathPrecompute::executeAlgorithm(crossingLinesGraph, ptLine.getNode(i),startingTime));
-                crossingContainer.getShortestPathsFrom(i, startingTime - 1);
             }
         }
     }
@@ -42,9 +40,8 @@ TEST(Transit_Preprocess_DEB, DebugFunction) {
     for(auto& ptLine : cyclingLineGraph.getPTLines()) {
         for(int i = 0; i < ptLine.size(); ++i) {
             for (auto& startingTime: ptLine.getTimetable(i)) {
-                cycleContainer.addShortestPathCollection(i, startingTime, cyclingLineGraph.getNbNodes(),
+                cycleContainer.addShortestPathCollection(ptLine.getNode(i), startingTime, cyclingLineGraph.getNbNodes(),
                         TransitShortestPathPrecompute::executeAlgorithm(cyclingLineGraph, ptLine.getNode(i),startingTime));
-                cycleContainer.getShortestPathsFrom(i, startingTime - 1);
             }
         }
     }
@@ -55,9 +52,8 @@ TEST(Transit_Preprocess_DEB, DebugFunction) {
     for(auto& ptLine : multipleCyclingLinesGraph.getPTLines()) {
         for(int i = 0; i < ptLine.size(); ++i) {
             for (auto& startingTime: ptLine.getTimetable(i)) {
-                multiCycleContainer.addShortestPathCollection(i, startingTime, multipleCyclingLinesGraph.getNbNodes(),
+                multiCycleContainer.addShortestPathCollection(ptLine.getNode(i), startingTime, multipleCyclingLinesGraph.getNbNodes(),
                         TransitShortestPathPrecompute::executeAlgorithm(multipleCyclingLinesGraph, ptLine.getNode(i),startingTime));
-                multiCycleContainer.getShortestPathsFrom(i, startingTime - 1);
             }
         }
     }
-- 
GitLab


From 39d07091084f8aafc17d4f1261652309ada44a20 Mon Sep 17 00:00:00 2001
From: Romain BERNARD <romain.bernard@uca.fr>
Date: Thu, 29 Aug 2024 18:12:31 +0200
Subject: [PATCH 234/327] WIP multimodal insertion debug

---
 test/CMakeLists.txt                           |  2 ++
 .../src/MultimodalInsertionHeuristicDebug.cpp | 22 ++++++++++++-------
 2 files changed, 16 insertions(+), 8 deletions(-)

diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt
index 16ba125..cccb961 100644
--- a/test/CMakeLists.txt
+++ b/test/CMakeLists.txt
@@ -191,6 +191,8 @@ add_executable(MultimodalInsertionHeuristic_DEB
         ../src/utils/Constants.h
         src/MultimodalInsertionHeuristicDebug.cpp
         ../src/utils/Timing.h
+        "../src/utils/Instance Generation/Requests/RequestsGenerator.cpp"
+        "../src/utils/Instance Generation/Requests/RequestsGenerator.h"
 )
 
 target_link_libraries(Line_UT gtest gtest_main)
diff --git a/test/src/MultimodalInsertionHeuristicDebug.cpp b/test/src/MultimodalInsertionHeuristicDebug.cpp
index 44e3d0b..0834703 100644
--- a/test/src/MultimodalInsertionHeuristicDebug.cpp
+++ b/test/src/MultimodalInsertionHeuristicDebug.cpp
@@ -8,35 +8,41 @@
 #include "../../src/routes/vehicle/SAEVRoute.h"
 #include "../../src/utils/Timing.h"
 #include "../../src/algorithm/Multimodal/Heuristics/SimpleModularHeuristic.h"
+#include "../../src/utils/Instance Generation/Requests/RequestsGenerator.h"
 
 TEST(MultimodalInsertionHeuristicDebug, DebugBaseInstance) {
-    std::string instancesPath = "../../resources/test/instances/Constraint Propagation/";
-    std::string instanceFolder = "basic_debug_instance/";
-    std::string graphDatFile = "graph.dat";
-    std::string requestsDatFile = "requests.dat";
+    std::string instancesPath = "../../resources/test/instances/PT Shortest Path/";
+    std::string instanceFolder = "contiguous_lines_debug_instance/";
+    std::string datFile = "graph.dat";
+
 
     //Parse graph
     INIT_TIMER
-    Graph graphFromSingleFile(instancesPath + instanceFolder + graphDatFile);
-    std::vector<Request> requests = Request::getRequestsFromFile(instancesPath + instanceFolder + requestsDatFile, graphFromSingleFile);
+    Graph graphFromSingleFile(instancesPath + instanceFolder + datFile);
+    graphFromSingleFile.computeAndUpdateShortestPathsMatrix(true);
+    RequestGenerationParameters genParams(1, 1.5, 15,30,240,600,290820241032L);
+    std::vector<Request> requests = RequestsGenerator::generateRequests(graphFromSingleFile, genParams);
 
     //Init instance
     Instance instance(requests,graphFromSingleFile,4);
     SAEVRoute routesContainer(graphFromSingleFile, requests);
     SimpleModularHeuristic multimodalHeuristic(&graphFromSingleFile, &routesContainer, &requests);
-    STOP_TIMER("Parsing and init")
+    STOP_TIMER("Instance parsing and init")
     std::cout << "------------------Fin parsing instance et route-------------------" << std::endl << std::endl;
 
     std::cout << "------------------Start preprocessings-------------------" << std::endl << std::endl;
     START_TIMER
     routesContainer.initMultimodalKeyPoints();
-    graphFromSingleFile.computeAndUpdateShortestPathsMatrix();
     graphFromSingleFile.computeAndUpdateShortestTransitPaths();
     STOP_TIMER("Preprocess")
     std::cout << "------------------End preprocessings-------------------" << std::endl << std::endl;
+    std::cout << "------------------Start multimodal insertion (entry)-------------------" << std::endl << std::endl;
+    START_TIMER
     for(size_t i = 0; i < requests.size(); ++i) {
         multimodalHeuristic.insertBestTransitEntryInRoute(requests[i], i);
     }
+    STOP_TIMER("Multimodal insertion (entry)")
+    std::cout << "------------------End multimodal insertion (entry)-------------------" << std::endl << std::endl;
 }
 
 int main(int argc, char* argv[]) {
-- 
GitLab


From 70eb307166f72a579f6862d3883eb98c19c95368 Mon Sep 17 00:00:00 2001
From: Romain BERNARD <romain.bernard@uca.fr>
Date: Mon, 2 Sep 2024 11:04:00 +0200
Subject: [PATCH 235/327] properly add edges to nodes

---
 src/instance/graph/Graph.cpp | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/src/instance/graph/Graph.cpp b/src/instance/graph/Graph.cpp
index 18bf4a9..4118460 100644
--- a/src/instance/graph/Graph.cpp
+++ b/src/instance/graph/Graph.cpp
@@ -300,10 +300,10 @@ void Graph::parseLineRandomizedSchedule(const DATRow& row, std::mt19937 rng,
 void Graph::createAndAddEdge(size_t edgeStartNodeIndex, size_t edgeEndNodeIndex, double length) {
     edgesVector.emplace_back(edgeStartNodeIndex, edgeEndNodeIndex, length);
 
-    Node entryNode = nodesVector[edgeStartNodeIndex];
+    Node& entryNode = nodesVector[edgeStartNodeIndex];
     entryNode.emplaceBackOutgoingEdge(edgesVector.size() - 1);
 
-    Node exitNode = nodesVector[edgeEndNodeIndex];
+    Node& exitNode = nodesVector[edgeEndNodeIndex];
     exitNode.emplaceBackIncomingEdge(edgesVector.size() - 1);
 }
 
-- 
GitLab


From b0ff9bfcf2ffbc7e8da2fc327112450f75265b3c Mon Sep 17 00:00:00 2001
From: Romain BERNARD <romain.bernard@uca.fr>
Date: Mon, 2 Sep 2024 11:05:43 +0200
Subject: [PATCH 236/327] expand graph API for edges

---
 src/instance/graph/Graph.h | 6 ++++++
 1 file changed, 6 insertions(+)

diff --git a/src/instance/graph/Graph.h b/src/instance/graph/Graph.h
index 31bee50..cdf1951 100644
--- a/src/instance/graph/Graph.h
+++ b/src/instance/graph/Graph.h
@@ -70,6 +70,12 @@ public:
     [[nodiscard]] const std::vector<Edge> &getEdgesVector() const {
         return edgesVector;
     }
+    /**
+     * @return Const ref to the edge at the given index
+     */
+    [[nodiscard]] const Edge &getEdge(size_t edgeIndex) const {
+        return edgesVector[edgeIndex];
+    }
 
     [[nodiscard]] size_t getNbIncomingEdges(size_t nodeIndex) const {
         return nodesVector[nodeIndex].getIncomingEdges().size();
-- 
GitLab


From 488985d520c0a6e5a6abab952f5be1e2dd9e90b9 Mon Sep 17 00:00:00 2001
From: Romain BERNARD <romain.bernard@uca.fr>
Date: Mon, 2 Sep 2024 11:07:03 +0200
Subject: [PATCH 237/327] init results vector properly in shortest paths
 calculation

---
 src/ShortestPath/Vehicle/VehicleShortestPathCalculation.cpp | 5 ++---
 1 file changed, 2 insertions(+), 3 deletions(-)

diff --git a/src/ShortestPath/Vehicle/VehicleShortestPathCalculation.cpp b/src/ShortestPath/Vehicle/VehicleShortestPathCalculation.cpp
index ded39ca..1172306 100644
--- a/src/ShortestPath/Vehicle/VehicleShortestPathCalculation.cpp
+++ b/src/ShortestPath/Vehicle/VehicleShortestPathCalculation.cpp
@@ -10,7 +10,7 @@
 std::vector<uint>
 VehicleShortestPathCalculation::computeShortestPathsFromNode(Graph &graph, size_t startingNodeIdx, bool useEdges) {
     std::vector<uint> results;
-    results.reserve(graph.getNbNodes());
+    results.resize(graph.getNbNodes(), UINT32_MAX);
 
     if(!useEdges)
         results = graph.getShortestSaevPaths()[startingNodeIdx];
@@ -53,8 +53,7 @@ MatrixShortestPathContainer VehicleShortestPathCalculation::computeShortestPaths
 }
 
 MatrixShortestPathContainer VehicleShortestPathCalculation::computeShortestPathsForGraph(Graph &graph, bool useEdges) {
-    std::vector<std::vector<uint>> results;
-    results.resize(graph.getNbNodes());
+    std::vector<std::vector<uint>> results{graph.getNbNodes()};
     for(size_t i = 0; i < graph.getNbNodes(); ++i) {
         results[i].resize(graph.getNbNodes());
         std::ranges::move(computeShortestPathsFromNode(graph, i, useEdges), results[i].begin());
-- 
GitLab


From dfaee71cf745dc7060034c9fc90faa0cc12b93d3 Mon Sep 17 00:00:00 2001
From: Romain BERNARD <romain.bernard@uca.fr>
Date: Mon, 2 Sep 2024 11:08:17 +0200
Subject: [PATCH 238/327] init results vector in the useEdge=true case to fix
 computations

---
 .../Vehicle/VehicleShortestPathCalculation.cpp    | 15 ++++++++++-----
 1 file changed, 10 insertions(+), 5 deletions(-)

diff --git a/src/ShortestPath/Vehicle/VehicleShortestPathCalculation.cpp b/src/ShortestPath/Vehicle/VehicleShortestPathCalculation.cpp
index 1172306..2994844 100644
--- a/src/ShortestPath/Vehicle/VehicleShortestPathCalculation.cpp
+++ b/src/ShortestPath/Vehicle/VehicleShortestPathCalculation.cpp
@@ -12,8 +12,15 @@ VehicleShortestPathCalculation::computeShortestPathsFromNode(Graph &graph, size_
     std::vector<uint> results;
     results.resize(graph.getNbNodes(), UINT32_MAX);
 
-    if(!useEdges)
+    if(!useEdges) {
         results = graph.getShortestSaevPaths()[startingNodeIdx];
+    } else {
+        results[startingNodeIdx] = 0; //Init value to 0 for path from X to X
+        for(const auto& edgeIndex : graph.getNode(startingNodeIdx).getOutgoingEdges()) { //Init  values according to immediate outgoing edges
+            const Edge & edge = graph.getEdge(edgeIndex);
+            results[edge.getEndNodeIdx()] = edge.getLength();
+        }
+    }
 
     std::vector<bool> mark(graph.getNbNodes(),false);
     std::priority_queue<VehiclePathState,std::vector<VehiclePathState>, std::greater<>> stateQueue{};
@@ -23,9 +30,8 @@ VehicleShortestPathCalculation::computeShortestPathsFromNode(Graph &graph, size_
         stateQueue.emplace(i, results[i]);
     }
 
-    VehiclePathState currentState;
     while(!stateQueue.empty()) {
-        currentState = stateQueue.top();
+        VehiclePathState currentState = stateQueue.top();
         stateQueue.pop();
         //Only expand and add
         if(!mark[currentState.getNodeIndex()]) {
@@ -99,10 +105,9 @@ void VehicleShortestPathCalculation::expandStatesViaMatrix(const VehiclePathStat
 void VehicleShortestPathCalculation::expandStatesViaEdges(const VehiclePathState &currentState, std::vector<uint> &results,
                                                           std::priority_queue<VehiclePathState, std::vector<VehiclePathState>, std::greater<>> &stateQueue,
                                                           const Graph& graph) {
-    Edge edge;
     uint newDistance = INT32_MAX;
     for(const auto& edgeIndex : graph.getNode(currentState.getNodeIndex()).getOutgoingEdges()) {
-        edge = graph.getEdgesVector()[edgeIndex];
+        const Edge& edge = graph.getEdge(edgeIndex);
         newDistance = currentState.getInstant() + edge.getLength();
         if(newDistance < results[edge.getEndNodeIdx()]) {
             stateQueue.emplace(edge.getEndNodeIdx(), newDistance);
-- 
GitLab


From 8385f3d0efc26af4e389bfb6dac2939bea27abdc Mon Sep 17 00:00:00 2001
From: Romain BERNARD <romain.bernard@uca.fr>
Date: Mon, 2 Sep 2024 15:18:30 +0200
Subject: [PATCH 239/327] account for indexes starting from 0 :)

---
 .../Multimodal/Heuristics/SimpleModularHeuristic.cpp          | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/src/algorithm/Multimodal/Heuristics/SimpleModularHeuristic.cpp b/src/algorithm/Multimodal/Heuristics/SimpleModularHeuristic.cpp
index 074f36c..b92cfe0 100644
--- a/src/algorithm/Multimodal/Heuristics/SimpleModularHeuristic.cpp
+++ b/src/algorithm/Multimodal/Heuristics/SimpleModularHeuristic.cpp
@@ -133,9 +133,9 @@ void SimpleModularHeuristic::setRoute(SAEVRoute *route) {
 
 void SimpleModularHeuristic::updateSubRequest(size_t requestId, const Request &request, bool isEntry) {
     size_t subRequestIndex = getSubrequestIndex(requestId, isEntry);
-    if(_requestsVect->size() < subRequestIndex) {
+    if((_requestsVect->size() - 1) < subRequestIndex) {
         _requestsVect->emplace_back(request);
-        assertm(_requestsVect->size() == subRequestIndex,"A request seems to have been missed or doesn't have any subrequest defined");
+        assertm((_requestsVect->size() - 1) == subRequestIndex,"A request seems to have been missed or doesn't have any subrequest defined");
     } else {
         _requestsVect->assign(subRequestIndex, request);
     }
-- 
GitLab


From f3544a0e44ed4f04a6bcddf4960206fac906ba15 Mon Sep 17 00:00:00 2001
From: Romain BERNARD <romain.bernard@uca.fr>
Date: Mon, 2 Sep 2024 15:19:35 +0200
Subject: [PATCH 240/327] Fix index interval to add twice _nbRequests for each
 section of the route vector

---
 src/routes/vehicle/SAEVRoute.h | 8 ++++----
 1 file changed, 4 insertions(+), 4 deletions(-)

diff --git a/src/routes/vehicle/SAEVRoute.h b/src/routes/vehicle/SAEVRoute.h
index 83a3713..b3baa80 100644
--- a/src/routes/vehicle/SAEVRoute.h
+++ b/src/routes/vehicle/SAEVRoute.h
@@ -149,15 +149,15 @@ public:
     [[nodiscard]] size_t getOriginDepotNodeIdx(const size_t vehicleId) const { return _route[getOriginDepotRouteIdx(vehicleId)].getNodeIndex();}
     [[nodiscard]] size_t getDestinationDepotNodeIdx(const size_t vehicleId) const { return _route[getDestinationDepotRouteIdx(vehicleId)].getNodeIndex();}
 
-    [[nodiscard]] size_t getEntrySubRequestOriginRouteIdx(const size_t requestId) const { return _nbRequest * 3 + requestId * 2;}
-    [[nodiscard]] size_t getEntrySubRequestDestinationRouteIdx(const size_t requestId) const { return _nbRequest * 3 + requestId * 2 + 1;}
+    [[nodiscard]] size_t getEntrySubRequestOriginRouteIdx(const size_t requestId) const { return _nbRequest * 4 + requestId * 2;}
+    [[nodiscard]] size_t getEntrySubRequestDestinationRouteIdx(const size_t requestId) const { return _nbRequest * 4 + requestId * 2 + 1;}
     [[nodiscard]] SAEVKeyPoint& getEntrySubRequestOrigin(const size_t requestId) { return _route[getEntrySubRequestOriginRouteIdx(requestId)];}
     [[nodiscard]] SAEVKeyPoint& getEntrySubRequestDestination(const size_t requestId) { return _route[getEntrySubRequestDestinationRouteIdx(requestId)];}
     [[nodiscard]] size_t getEntrySubRequestOriginNodeIdx(const size_t requestId) const { return _route[getEntrySubRequestOriginRouteIdx(requestId)].getNodeIndex();}
     [[nodiscard]] size_t getEntrySubRequestDestinationNodeIdx(const size_t requestId) const { return _route[getEntrySubRequestDestinationRouteIdx(requestId)].getNodeIndex();}
 
-    [[nodiscard]] size_t getExitSubRequestOriginRouteIdx(const size_t requestId) const { return _nbRequest * 4 + requestId * 2;}
-    [[nodiscard]] size_t getExitSubRequestDestinationRouteIdx(const size_t requestId) const { return _nbRequest * 4 + requestId * 2 + 1;}
+    [[nodiscard]] size_t getExitSubRequestOriginRouteIdx(const size_t requestId) const { return _nbRequest * 6 + requestId * 2;}
+    [[nodiscard]] size_t getExitSubRequestDestinationRouteIdx(const size_t requestId) const { return _nbRequest * 6 + requestId * 2 + 1;}
     [[nodiscard]] SAEVKeyPoint& getExitSubRequestOrigin(const size_t requestId) { return _route[getExitSubRequestOriginRouteIdx(requestId)];}
     [[nodiscard]] SAEVKeyPoint& getExitSubRequestDestination(const size_t requestId) { return _route[getExitSubRequestDestinationRouteIdx(requestId)];}
     [[nodiscard]] size_t getExitSubRequestOriginNodeIdx(const size_t requestId) const { return _route[getExitSubRequestOriginRouteIdx(requestId)].getNodeIndex();}
-- 
GitLab


From fc61835d6ec0a7c89bc032e74ea833b4561d7837 Mon Sep 17 00:00:00 2001
From: Romain BERNARD <romain.bernard@uca.fr>
Date: Mon, 2 Sep 2024 15:26:46 +0200
Subject: [PATCH 241/327] set isOrigin properly

---
 src/routes/vehicle/SAEVRoute.cpp | 4 ++++
 1 file changed, 4 insertions(+)

diff --git a/src/routes/vehicle/SAEVRoute.cpp b/src/routes/vehicle/SAEVRoute.cpp
index 1220ab8..ae47532 100644
--- a/src/routes/vehicle/SAEVRoute.cpp
+++ b/src/routes/vehicle/SAEVRoute.cpp
@@ -42,6 +42,10 @@ void SAEVRoute::initMultimodalKeyPoints() {
                                             // 2*NbRequests O/D Bus entry Keypoints, 2*NbRequests O/D Bus exit Keypoints
 
     for (size_t i = 0; i < _nbRequest; ++i) {
+        //Set isOrigin accordingly
+        getEntrySubRequestOrigin(i).setIsOrigin(true);
+        getExitSubRequestOrigin(i).setIsOrigin(true);
+
         //Link Origins and Destinations for entry/exit subrequests
         getEntrySubRequestOrigin(i).setCounterpart(&getEntrySubRequestDestination(i));
         getEntrySubRequestDestination(i).setCounterpart(&getEntrySubRequestOrigin(i));
-- 
GitLab


From 73c2080c236c3b30158934d0c6de19ce98eed2a8 Mon Sep 17 00:00:00 2001
From: Romain BERNARD <romain.bernard@uca.fr>
Date: Mon, 2 Sep 2024 15:48:46 +0200
Subject: [PATCH 242/327] use the proper implementation here

---
 src/algorithm/DARP/Heuristics/BestInsertionHeuristic.cpp | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/src/algorithm/DARP/Heuristics/BestInsertionHeuristic.cpp b/src/algorithm/DARP/Heuristics/BestInsertionHeuristic.cpp
index 4b5e2c0..8d4262e 100644
--- a/src/algorithm/DARP/Heuristics/BestInsertionHeuristic.cpp
+++ b/src/algorithm/DARP/Heuristics/BestInsertionHeuristic.cpp
@@ -64,5 +64,5 @@ SAEVRouteChangelist BestInsertionHeuristic::tryBestRequestInsertionInActiveVehic
         route.getBestFeasibleInsertionsQueue(bestInsertions, requestKp, vehicleId);
     }
 
-    return tryVehicleBestInsertion(requestKp, vehicleId, route);
+    return tryVehicleBestInsertion(bestInsertions, route);
 }
-- 
GitLab


From c2bbe8411e9958652afb7161ea0c7f405b7676c5 Mon Sep 17 00:00:00 2001
From: Romain BERNARD <romain.bernard@uca.fr>
Date: Mon, 2 Sep 2024 17:04:12 +0200
Subject: [PATCH 243/327] Fix iteration to start at vehicle 0

---
 src/algorithm/DARP/Heuristics/BestInsertionHeuristic.cpp | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/src/algorithm/DARP/Heuristics/BestInsertionHeuristic.cpp b/src/algorithm/DARP/Heuristics/BestInsertionHeuristic.cpp
index 8d4262e..fa068f5 100644
--- a/src/algorithm/DARP/Heuristics/BestInsertionHeuristic.cpp
+++ b/src/algorithm/DARP/Heuristics/BestInsertionHeuristic.cpp
@@ -60,9 +60,9 @@ SAEVRouteChangelist BestInsertionHeuristic::tryBestRequestInsertionInActiveVehic
     size_t vehicleId = 0;
     BestInsertionQueue bestInsertions{requestKp};
     //Iteratively try inserting in every active vehicle and the first inactive vehicle
-    while(++vehicleId <= route.getLastActiveVehicleId() + 1) {
+    do {
         route.getBestFeasibleInsertionsQueue(bestInsertions, requestKp, vehicleId);
-    }
+    } while(++vehicleId <= route.getLastActiveVehicleId());
 
     return tryVehicleBestInsertion(bestInsertions, route);
 }
-- 
GitLab


From 10a0645a96f6209855949936b054b195d225e7bd Mon Sep 17 00:00:00 2001
From: Romain BERNARD <romain.bernard@uca.fr>
Date: Mon, 2 Sep 2024 17:09:09 +0200
Subject: [PATCH 244/327] revert changes already in tryBestRequestInsertion in
 fail cases

---
 src/algorithm/Multimodal/Heuristics/SimpleModularHeuristic.cpp | 2 --
 1 file changed, 2 deletions(-)

diff --git a/src/algorithm/Multimodal/Heuristics/SimpleModularHeuristic.cpp b/src/algorithm/Multimodal/Heuristics/SimpleModularHeuristic.cpp
index b92cfe0..eeb0445 100644
--- a/src/algorithm/Multimodal/Heuristics/SimpleModularHeuristic.cpp
+++ b/src/algorithm/Multimodal/Heuristics/SimpleModularHeuristic.cpp
@@ -104,8 +104,6 @@ SimpleModularHeuristic::insertBestTransitEntryInRoute(const std::vector<Request>
         //If we've found an insertion that doesn't create a vehicle, stop there
         if(changeList.success()) {
             return getSubrequest(requestId, true);
-        } else {
-            changeList.revertChanges();
         }
     }
 
-- 
GitLab


From bab766db889dee27c8716bba01834aef8e510856 Mon Sep 17 00:00:00 2001
From: Romain BERNARD <romain.bernard@uca.fr>
Date: Mon, 2 Sep 2024 17:09:59 +0200
Subject: [PATCH 245/327] use lower value than numeric limit to prevent
 overflows

---
 src/instance/requests/Request.cpp | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/src/instance/requests/Request.cpp b/src/instance/requests/Request.cpp
index e812dd2..a062f40 100644
--- a/src/instance/requests/Request.cpp
+++ b/src/instance/requests/Request.cpp
@@ -235,7 +235,7 @@ Request::Request(const Graph& graph, const Request &baseRequest, const TransitAc
         _arrivalTW.max = _departureTW.min + baseRequest.getDeltaTime(); //Reduce max arrival TW to a value we are 100% sure is compatible with our current min departure time
     }
     _transitTravelTimeRatio = baseRequest.getTransitTravelTimeRatio();
-    _deltaTime = std::numeric_limits<uint>::max();
+    _deltaTime = UINT16_MAX;
     _weight = baseRequest.getWeight();
 }
 
-- 
GitLab


From ee91273b8bce64b1a086fe7eff48f6f411f4f48e Mon Sep 17 00:00:00 2001
From: Romain BERNARD <romain.bernard@uca.fr>
Date: Mon, 2 Sep 2024 18:16:55 +0200
Subject: [PATCH 246/327] add assertion here for tests

---
 src/routes/vehicle/SAEVRoute.cpp | 6 ++++++
 1 file changed, 6 insertions(+)

diff --git a/src/routes/vehicle/SAEVRoute.cpp b/src/routes/vehicle/SAEVRoute.cpp
index ae47532..aa541f4 100644
--- a/src/routes/vehicle/SAEVRoute.cpp
+++ b/src/routes/vehicle/SAEVRoute.cpp
@@ -7,6 +7,11 @@
 #include "SAEVRoute.h"
 #include "BestInsertionQueue.h"
 
+// uncomment to disable assert()
+// #define NDEBUG
+#include <cassert>
+#define assertm(exp, msg) assert(((void)msg, exp))
+
 #ifdef DEBUG_CONSTRAINT_PROPAGATION
 #include <iostream>
 #define DEBUG_MSG(str) do { std::cout << str << std::endl; } while( false )
@@ -88,6 +93,7 @@ void SAEVRoute::insertRequest(SAEVKeyPoint &originKp, SAEVKeyPoint * originReque
 }
 
 void SAEVRoute::removeRequest(SAEVKeyPoint &originKp) {
+    assertm(originKp.getSuccessor() != nullptr, "Trying to remove a request that was already removed");
     //Before undoing the insertion, update weights on the route
     removeRequestWeightFromRoute(originKp);
 
-- 
GitLab


From d6e493f7acc9bf2321bbdd28f21a715a49f35031 Mon Sep 17 00:00:00 2001
From: Romain BERNARD <30secondstodraw@gmail.com>
Date: Tue, 3 Sep 2024 13:31:47 +0200
Subject: [PATCH 247/327] init multimodal keypoints in constructor directly to
 prevent random pointer staleness

---
 src/routes/vehicle/SAEVRoute.cpp              | 42 +++++++++++--------
 src/routes/vehicle/SAEVRoute.h                | 15 ++++---
 .../src/MultimodalInsertionHeuristicDebug.cpp |  3 +-
 3 files changed, 35 insertions(+), 25 deletions(-)

diff --git a/src/routes/vehicle/SAEVRoute.cpp b/src/routes/vehicle/SAEVRoute.cpp
index aa541f4..a1d94e1 100644
--- a/src/routes/vehicle/SAEVRoute.cpp
+++ b/src/routes/vehicle/SAEVRoute.cpp
@@ -19,8 +19,18 @@
 #define DEBUG_MSG(str) do { } while ( false )
 #endif
 
-SAEVRoute::SAEVRoute(const Graph& graph, const std::vector<Request>& requestList) : _nbRequest(requestList.size()), _graph(&graph), _requestList(&requestList) {
-    _route.resize(_nbRequest*4); //nbRequest*2 O/D KeyPoints + nbRequest*2 Start/End depots (upper bound #vehicle = #requests
+SAEVRoute::SAEVRoute(const Graph &graph, const std::vector<Request> &requestList)
+        : SAEVRoute(graph, requestList, false) {}
+
+SAEVRoute::SAEVRoute(const Graph &graph, const std::vector<Request> &requestList, bool initMultimodal)
+        : _nbRequest(requestList.size()), _graph(&graph), _requestList(&requestList) {
+
+    if(!initMultimodal) {
+        _route.resize(_nbRequest*4); //nbRequest*2 O/D KeyPoints + nbRequest*2 Start/End depots (upper bound #vehicle = #requests
+    } else {
+        _route.resize(_nbRequest * 8); // 2*NbRequests O/D Keypoints, 2*NbRequests O/D vehicle depot Keypoints
+                                                // 2*NbRequests O/D Bus entry Keypoints, 2*NbRequests O/D Bus exit Keypoints
+    }
 
     //Init Request O/D and Depot start/end key points
     for(size_t i = 0; i < _nbRequest; ++i) {
@@ -40,22 +50,20 @@ SAEVRoute::SAEVRoute(const Graph& graph, const std::vector<Request>& requestList
         getOriginDepot(i).setSuccessor(&getDestinationDepot(i));
         getDestinationDepot(i).setPredecessor(&getOriginDepot(i));
     }
-}
-
-void SAEVRoute::initMultimodalKeyPoints() {
-    _route.resize(_nbRequest * 8); // 2*NbRequests O/D Keypoints, 2*NbRequests O/D vehicle depot Keypoints
-                                            // 2*NbRequests O/D Bus entry Keypoints, 2*NbRequests O/D Bus exit Keypoints
 
-    for (size_t i = 0; i < _nbRequest; ++i) {
-        //Set isOrigin accordingly
-        getEntrySubRequestOrigin(i).setIsOrigin(true);
-        getExitSubRequestOrigin(i).setIsOrigin(true);
-
-        //Link Origins and Destinations for entry/exit subrequests
-        getEntrySubRequestOrigin(i).setCounterpart(&getEntrySubRequestDestination(i));
-        getEntrySubRequestDestination(i).setCounterpart(&getEntrySubRequestOrigin(i));
-        getExitSubRequestOrigin(i).setCounterpart(&getExitSubRequestDestination(i));
-        getExitSubRequestDestination(i).setCounterpart(&getExitSubRequestOrigin(i));
+    //Set values and init all links for multimodal keypoints
+    if(initMultimodal) {
+        for (size_t i = 0; i < _nbRequest; ++i) {
+            //Set isOrigin accordingly
+            getEntrySubRequestOrigin(i).setIsOrigin(true);
+            getExitSubRequestOrigin(i).setIsOrigin(true);
+
+            //Link Origins and Destinations for entry/exit subrequests
+            getEntrySubRequestOrigin(i).setCounterpart(&getEntrySubRequestDestination(i));
+            getEntrySubRequestDestination(i).setCounterpart(&getEntrySubRequestOrigin(i));
+            getExitSubRequestOrigin(i).setCounterpart(&getExitSubRequestDestination(i));
+            getExitSubRequestDestination(i).setCounterpart(&getExitSubRequestOrigin(i));
+        }
     }
 }
 
diff --git a/src/routes/vehicle/SAEVRoute.h b/src/routes/vehicle/SAEVRoute.h
index b3baa80..e22f110 100644
--- a/src/routes/vehicle/SAEVRoute.h
+++ b/src/routes/vehicle/SAEVRoute.h
@@ -27,7 +27,15 @@ public:
      * @param graph the instance's graph, used to get shortest paths values during key point initialization and later in constraint propagation
      * @param requestList the instance's request list, used to associate KeyPoints that represent requests with the appropriate informations
      */
-    explicit SAEVRoute(const Graph& graph, const std::vector<Request>& requestList);
+    explicit SAEVRoute(const Graph &graph, const std::vector<Request> &requestList);
+    /**
+     * Initializes a route following a tabular doubly chained approach where 0->nbRequest*2-1 are Request Origin (even)/Destination (odd)
+     * and nbRequest*2 -> nbRequest*4-1 are vehicle start (even)/end (odd) depot. Each KeyPoint has
+     * @param graph the instance's graph, used to get shortest paths values during key point initialization and later in constraint propagation
+     * @param requestList the instance's request list, used to associate KeyPoints that represent requests with the appropriate informations
+     * @param initMultimodal true to init the container to a multimodal approach compatible size in advance, false (default) otherwise to just have requests/depots sections
+     */
+    explicit SAEVRoute(const Graph &graph, const std::vector<Request> &requestList, bool initMultimodal);
 
     [[nodiscard]] const std::vector<SAEVKeyPoint> &getRoute() const {
         return _route;
@@ -175,11 +183,6 @@ public:
 
     std::string to_string(size_t vehicleId);
     void exportToFile();
-
-    /**
-     * Extends the existing route to add 4*NbRequests keypoints to represent entry/exit sub-requests Origin/Destination
-     */
-    void initMultimodalKeyPoints();
 };
 
 #include "propagation/SAEVRouteChangelist.h"
diff --git a/test/src/MultimodalInsertionHeuristicDebug.cpp b/test/src/MultimodalInsertionHeuristicDebug.cpp
index 0834703..fbe635e 100644
--- a/test/src/MultimodalInsertionHeuristicDebug.cpp
+++ b/test/src/MultimodalInsertionHeuristicDebug.cpp
@@ -25,14 +25,13 @@ TEST(MultimodalInsertionHeuristicDebug, DebugBaseInstance) {
 
     //Init instance
     Instance instance(requests,graphFromSingleFile,4);
-    SAEVRoute routesContainer(graphFromSingleFile, requests);
+    SAEVRoute routesContainer(graphFromSingleFile, requests, true);
     SimpleModularHeuristic multimodalHeuristic(&graphFromSingleFile, &routesContainer, &requests);
     STOP_TIMER("Instance parsing and init")
     std::cout << "------------------Fin parsing instance et route-------------------" << std::endl << std::endl;
 
     std::cout << "------------------Start preprocessings-------------------" << std::endl << std::endl;
     START_TIMER
-    routesContainer.initMultimodalKeyPoints();
     graphFromSingleFile.computeAndUpdateShortestTransitPaths();
     STOP_TIMER("Preprocess")
     std::cout << "------------------End preprocessings-------------------" << std::endl << std::endl;
-- 
GitLab


From 04fa3aafa05bc2b7ef514bfdbfb858fcf2c7a580 Mon Sep 17 00:00:00 2001
From: Romain BERNARD <30secondstodraw@gmail.com>
Date: Tue, 3 Sep 2024 13:32:01 +0200
Subject: [PATCH 248/327] add globals for windows compilation

---
 src/ShortestPath/Vehicle/VehicleShortestPath.h | 1 +
 src/instance/graph/Edge.h                      | 1 +
 2 files changed, 2 insertions(+)

diff --git a/src/ShortestPath/Vehicle/VehicleShortestPath.h b/src/ShortestPath/Vehicle/VehicleShortestPath.h
index 068b184..fad038d 100644
--- a/src/ShortestPath/Vehicle/VehicleShortestPath.h
+++ b/src/ShortestPath/Vehicle/VehicleShortestPath.h
@@ -8,6 +8,7 @@
 #include <compare>
 #include "../ShortestPath.h"
 #include "../../instance/graph/Node.h"
+#include "../../utils/Globals.h"
 
 class VehicleShortestPath : public ShortestPath<size_t> {
 private:
diff --git a/src/instance/graph/Edge.h b/src/instance/graph/Edge.h
index 29d819a..f8e5498 100644
--- a/src/instance/graph/Edge.h
+++ b/src/instance/graph/Edge.h
@@ -7,6 +7,7 @@
 
 
 #include "Node.h"
+#include "../../utils/Globals.h"
 
 class Edge {
 private:
-- 
GitLab


From 71406003397b67d712ef49965d10623e62defa00 Mon Sep 17 00:00:00 2001
From: Romain BERNARD <30secondstodraw@gmail.com>
Date: Tue, 3 Sep 2024 14:38:48 +0200
Subject: [PATCH 249/327] use integrated method to add new vehicle and return
 an id with a debug check for having no more vehicles available

---
 src/routes/vehicle/SAEVRoute.cpp | 3 +--
 src/routes/vehicle/SAEVRoute.h   | 8 ++++++++
 2 files changed, 9 insertions(+), 2 deletions(-)

diff --git a/src/routes/vehicle/SAEVRoute.cpp b/src/routes/vehicle/SAEVRoute.cpp
index a1d94e1..16d16a2 100644
--- a/src/routes/vehicle/SAEVRoute.cpp
+++ b/src/routes/vehicle/SAEVRoute.cpp
@@ -501,8 +501,7 @@ void SAEVRoute::removeRequestWeightFromRoute(SAEVKeyPoint& requestOriginKeyPoint
 }
 
 void SAEVRoute::insertRequestInNewVehicle(SAEVKeyPoint &originKp) {
-    size_t vehicleId = getLastActiveVehicleId() + 1;
-    setLastActiveVehicleId(vehicleId);
+    size_t vehicleId = addNewActiveVehicle();
     DEBUG_MSG("NEW VEHICLE CREATED, ID :" + std::to_string(vehicleId));
 
     tryAddRequest(originKp, &getOriginDepot(vehicleId), &getOriginDepot(vehicleId));
diff --git a/src/routes/vehicle/SAEVRoute.h b/src/routes/vehicle/SAEVRoute.h
index e22f110..eafbf07 100644
--- a/src/routes/vehicle/SAEVRoute.h
+++ b/src/routes/vehicle/SAEVRoute.h
@@ -5,6 +5,10 @@
 #ifndef GREEDYALGORITHM_SAEVROUTE_H
 #define GREEDYALGORITHM_SAEVROUTE_H
 
+// uncomment to disable assert()
+// #define NDEBUG
+#include <cassert>
+#define assertm(exp, msg) assert(((void)msg, exp))
 
 #include <vector>
 #include "SAEVKeyPoint.h"
@@ -172,6 +176,10 @@ public:
     [[nodiscard]] size_t getExitSubRequestDestinationNodeIdx(const size_t requestId) const { return _route[getExitSubRequestDestinationRouteIdx(requestId)].getNodeIndex();}
 
     [[nodiscard]] size_t getLastActiveVehicleId() const { return _lastActiveVehicleId; }
+    size_t addNewActiveVehicle() {
+        assertm(_lastActiveVehicleId < _nbRequest - 1, "No more vehicle available");
+        return ++_lastActiveVehicleId;
+    }
     void setLastActiveVehicleId(size_t lastActiveVehicleId) { _lastActiveVehicleId = lastActiveVehicleId; }
 
     /**
-- 
GitLab


From 62b02a4a8bf4aa55ab7400d9e079dc823955474a Mon Sep 17 00:00:00 2001
From: Romain BERNARD <30secondstodraw@gmail.com>
Date: Tue, 3 Sep 2024 15:11:05 +0200
Subject: [PATCH 250/327] remove useless method

---
 .../Heuristics/SimpleModularHeuristic.cpp           | 13 -------------
 .../Multimodal/Heuristics/SimpleModularHeuristic.h  |  1 -
 2 files changed, 14 deletions(-)

diff --git a/src/algorithm/Multimodal/Heuristics/SimpleModularHeuristic.cpp b/src/algorithm/Multimodal/Heuristics/SimpleModularHeuristic.cpp
index eeb0445..ac5c6dc 100644
--- a/src/algorithm/Multimodal/Heuristics/SimpleModularHeuristic.cpp
+++ b/src/algorithm/Multimodal/Heuristics/SimpleModularHeuristic.cpp
@@ -43,19 +43,6 @@ uint SimpleModularHeuristic::getMaxEntryConstraint(const Request &request, size_
     return (uint) std::floor(request.getMaxArrivalTw() - _graph->getShortestSAEVPath(ptEntryNodeIdx, request.getDestinationNodeIndex()) * request.getTransitTravelTimeRatio());
 }
 
-std::vector<Request>
-SimpleModularHeuristic::generateAndInsertBestEntries(const std::vector<Request> &baseRequestsList) {
-    std::vector<Request> entrySubRequestsList{baseRequestsList.size()}; //Init entry subrequests list
-    for(size_t i = 0; i < baseRequestsList.size(); ++i) {
-        const Request& baseRequest = baseRequestsList[i];
-        const Request subreq = insertBestTransitEntryInRoute(baseRequest, i);
-        _requestsVect->push_back(subreq);
-        entrySubRequestsList.push_back(subreq);
-    }
-
-    return entrySubRequestsList;
-}
-
 /**
  * Generates the best entries list (ordered by an implementation-dependant ,
  * then generates a vector of requests from these entries before starting the entry subrequest insertion process <br>
diff --git a/src/algorithm/Multimodal/Heuristics/SimpleModularHeuristic.h b/src/algorithm/Multimodal/Heuristics/SimpleModularHeuristic.h
index f7c3ceb..e8e7d75 100644
--- a/src/algorithm/Multimodal/Heuristics/SimpleModularHeuristic.h
+++ b/src/algorithm/Multimodal/Heuristics/SimpleModularHeuristic.h
@@ -42,7 +42,6 @@ private:
     Request insertBestTransitEntryInRoute(const Request &baseRequest, const std::vector<TransitAccess>& entriesAccessList, size_t requestId);
     const Request & insertBestTransitEntryInRoute(const std::vector<Request>& entrySubRequestsList, size_t requestId);
 
-    std::vector<Request> generateAndInsertBestEntries(const std::vector<Request> &baseRequestsList);
     void insertBestTransitExitsInRoute(const std::vector<Request>& baseRequestsList, const std::vector<TransitAccess>& transitEntriesList);
 
     //Best candidates function
-- 
GitLab


From 0595a5e3ec27db392cb137a1e4a5d413c7f5f1c9 Mon Sep 17 00:00:00 2001
From: Romain BERNARD <30secondstodraw@gmail.com>
Date: Tue, 3 Sep 2024 15:11:54 +0200
Subject: [PATCH 251/327] only loop over base requests in tests (will be
 accounted for in the global algorithm)

---
 src/algorithm/Multimodal/Heuristics/SimpleModularHeuristic.h | 4 ++++
 test/src/MultimodalInsertionHeuristicDebug.cpp               | 2 +-
 2 files changed, 5 insertions(+), 1 deletion(-)

diff --git a/src/algorithm/Multimodal/Heuristics/SimpleModularHeuristic.h b/src/algorithm/Multimodal/Heuristics/SimpleModularHeuristic.h
index e8e7d75..5004ae6 100644
--- a/src/algorithm/Multimodal/Heuristics/SimpleModularHeuristic.h
+++ b/src/algorithm/Multimodal/Heuristics/SimpleModularHeuristic.h
@@ -35,6 +35,10 @@ public:
 
     void multimodalRequestsInsertion(const std::vector<Request>& requestsToInsert);
 
+    [[nodiscard]] size_t getNbBaseRquests() const {
+        return _nbBaseRquests;
+    }
+
 //Private members for heuristic internal functions we don't wish to see overriden
 private:
 
diff --git a/test/src/MultimodalInsertionHeuristicDebug.cpp b/test/src/MultimodalInsertionHeuristicDebug.cpp
index fbe635e..d87cafd 100644
--- a/test/src/MultimodalInsertionHeuristicDebug.cpp
+++ b/test/src/MultimodalInsertionHeuristicDebug.cpp
@@ -37,7 +37,7 @@ TEST(MultimodalInsertionHeuristicDebug, DebugBaseInstance) {
     std::cout << "------------------End preprocessings-------------------" << std::endl << std::endl;
     std::cout << "------------------Start multimodal insertion (entry)-------------------" << std::endl << std::endl;
     START_TIMER
-    for(size_t i = 0; i < requests.size(); ++i) {
+    for(size_t i = 0; i < multimodalHeuristic.getNbBaseRquests(); ++i) {
         multimodalHeuristic.insertBestTransitEntryInRoute(requests[i], i);
     }
     STOP_TIMER("Multimodal insertion (entry)")
-- 
GitLab


From b7dd4dbd3c98e8d56d5505ba1873c99a88bc6bc3 Mon Sep 17 00:00:00 2001
From: Romain BERNARD <30secondstodraw@gmail.com>
Date: Tue, 3 Sep 2024 15:13:04 +0200
Subject: [PATCH 252/327] add some debug definitions in test cmake to have
 those on hand (decomment during tests and don't commit unless adding a new
 one to avoid cluttering git history)

---
 test/CMakeLists.txt | 4 ++++
 1 file changed, 4 insertions(+)

diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt
index cccb961..021c6e1 100644
--- a/test/CMakeLists.txt
+++ b/test/CMakeLists.txt
@@ -5,6 +5,10 @@ project(Google_tests)
 add_subdirectory(lib/googletest)
 include_directories(${gtest_SOURCE_DIR}/include ${gtest_SOURCE_DIR})
 
+#add_definitions(-DDEBUG_TRANSIT_PRECOMPUTE)
+#add_definitions(-DDEBUG_CONSTRAINT_PROPAGATION)
+#add_definitions(-DDEBUG_BEST_INSERTION_HEURISTIC)
+
 # 'Google_Tests_run' is the target name
 # 'test1.cpp test2.cpp' are source files with tests
 add_executable(Line_UT
-- 
GitLab


From 15c10712b0cdc64248cfeef9372a965b2f5d7652 Mon Sep 17 00:00:00 2001
From: Romain BERNARD <30secondstodraw@gmail.com>
Date: Tue, 3 Sep 2024 15:13:52 +0200
Subject: [PATCH 253/327] avoid uint overflows in route algorithms (required
 for "infinite" deltas for subrequests

---
 src/routes/vehicle/SAEVKeyPoint.cpp | 4 ++--
 src/routes/vehicle/SAEVKeyPoint.h   | 4 ++--
 src/routes/vehicle/SAEVRoute.cpp    | 4 ++--
 3 files changed, 6 insertions(+), 6 deletions(-)

diff --git a/src/routes/vehicle/SAEVKeyPoint.cpp b/src/routes/vehicle/SAEVKeyPoint.cpp
index c9f7696..ccdbc68 100644
--- a/src/routes/vehicle/SAEVKeyPoint.cpp
+++ b/src/routes/vehicle/SAEVKeyPoint.cpp
@@ -32,7 +32,7 @@ void SAEVKeyPoint::setCurrentOccupation(uint currentCapacity) {
     _currentOccupation = currentCapacity;
 }
 
-uint SAEVKeyPoint::getMinTw() const {
+int SAEVKeyPoint::getMinTw() const {
     return _minTW;
 }
 
@@ -40,7 +40,7 @@ void SAEVKeyPoint::setMinTw(uint minTw) {
     _minTW = minTw;
 }
 
-uint SAEVKeyPoint::getMaxTw() const {
+int SAEVKeyPoint::getMaxTw() const {
     return _maxTW;
 }
 
diff --git a/src/routes/vehicle/SAEVKeyPoint.h b/src/routes/vehicle/SAEVKeyPoint.h
index 394444f..1e6992c 100644
--- a/src/routes/vehicle/SAEVKeyPoint.h
+++ b/src/routes/vehicle/SAEVKeyPoint.h
@@ -48,10 +48,10 @@ public:
     [[nodiscard]] uint getCurrentOccupation() const;
     void setCurrentOccupation(uint currentCapacity);
 
-    [[nodiscard]] uint getMinTw() const;
+    [[nodiscard]] int getMinTw() const;
     void setMinTw(uint minTw);
 
-    [[nodiscard]] uint getMaxTw() const;
+    [[nodiscard]] int getMaxTw() const;
     void setMaxTw(uint maxTw);
 
     [[nodiscard]] bool isOrigin() const;
diff --git a/src/routes/vehicle/SAEVRoute.cpp b/src/routes/vehicle/SAEVRoute.cpp
index 16d16a2..c5ee0cf 100644
--- a/src/routes/vehicle/SAEVRoute.cpp
+++ b/src/routes/vehicle/SAEVRoute.cpp
@@ -234,8 +234,8 @@ SAEVRouteChangelist SAEVRoute::insertRequestWithPropagation(SAEVKeyPoint &origin
     boundPropagationQueue.emplace(Max, destinationKP);
 
     //Pre-init variables used in the loop
-    uint oldValue;
-    uint newValue;
+    int oldValue;
+    int newValue;
     SAEVKeyPoint * predecessorKP;
     SAEVKeyPoint * successorKP;
     SAEVKeyPoint * counterpartKP; //An Origin's Destination, or a Destination's Origin
-- 
GitLab


From f3fd6146fc8441e2d11077172fe87d2599846980 Mon Sep 17 00:00:00 2001
From: Romain BERNARD <romain.bernard@uca.fr>
Date: Wed, 4 Sep 2024 17:30:43 +0200
Subject: [PATCH 254/327] move assertm macro to Globals.h

---
 src/algorithm/Multimodal/Heuristics/SimpleModularHeuristic.h | 5 +----
 src/routes/vehicle/SAEVRoute.cpp                             | 5 -----
 src/routes/vehicle/SAEVRoute.h                               | 4 ----
 src/utils/Globals.h                                          | 5 +++++
 4 files changed, 6 insertions(+), 13 deletions(-)

diff --git a/src/algorithm/Multimodal/Heuristics/SimpleModularHeuristic.h b/src/algorithm/Multimodal/Heuristics/SimpleModularHeuristic.h
index 5004ae6..be4bd4d 100644
--- a/src/algorithm/Multimodal/Heuristics/SimpleModularHeuristic.h
+++ b/src/algorithm/Multimodal/Heuristics/SimpleModularHeuristic.h
@@ -5,10 +5,6 @@
 #ifndef GREEDYALGORITHM_SIMPLEMODULARHEURISTIC_H
 #define GREEDYALGORITHM_SIMPLEMODULARHEURISTIC_H
 
-// uncomment to disable assert()
-// #define NDEBUG
-#include <cassert>
-#define assertm(exp, msg) assert(((void)msg, exp))
 
 #include <cstddef>
 #include <vector>
@@ -27,6 +23,7 @@ private:
 
     //Add friend test classes to test inner workings without making the whole API public
     FRIEND_TEST(MultimodalInsertionHeuristicDebug, DebugBaseInstance);
+    FRIEND_TEST(MultimodalInsertionHeuristicDebug, DebugInstanceAlain);
 
 //Public interface to interact with the modular heuristic
 public:
diff --git a/src/routes/vehicle/SAEVRoute.cpp b/src/routes/vehicle/SAEVRoute.cpp
index c5ee0cf..98b415b 100644
--- a/src/routes/vehicle/SAEVRoute.cpp
+++ b/src/routes/vehicle/SAEVRoute.cpp
@@ -7,11 +7,6 @@
 #include "SAEVRoute.h"
 #include "BestInsertionQueue.h"
 
-// uncomment to disable assert()
-// #define NDEBUG
-#include <cassert>
-#define assertm(exp, msg) assert(((void)msg, exp))
-
 #ifdef DEBUG_CONSTRAINT_PROPAGATION
 #include <iostream>
 #define DEBUG_MSG(str) do { std::cout << str << std::endl; } while( false )
diff --git a/src/routes/vehicle/SAEVRoute.h b/src/routes/vehicle/SAEVRoute.h
index eafbf07..c39b0bc 100644
--- a/src/routes/vehicle/SAEVRoute.h
+++ b/src/routes/vehicle/SAEVRoute.h
@@ -5,10 +5,6 @@
 #ifndef GREEDYALGORITHM_SAEVROUTE_H
 #define GREEDYALGORITHM_SAEVROUTE_H
 
-// uncomment to disable assert()
-// #define NDEBUG
-#include <cassert>
-#define assertm(exp, msg) assert(((void)msg, exp))
 
 #include <vector>
 #include "SAEVKeyPoint.h"
diff --git a/src/utils/Globals.h b/src/utils/Globals.h
index 34cd27e..88a94e0 100644
--- a/src/utils/Globals.h
+++ b/src/utils/Globals.h
@@ -5,6 +5,11 @@
 #ifndef GREEDYALGORITHM_GLOBALS_H
 #define GREEDYALGORITHM_GLOBALS_H
 
+// uncomment to disable assert()
+// #define NDEBUG
+#include <cassert>
+#define assertm(exp, msg) assert(((void)msg, exp))
+
 using uint = unsigned int;
 using ulong = unsigned long;
 
-- 
GitLab


From 24aa911fdbd300d8d876777f2e2862f4b5de12bf Mon Sep 17 00:00:00 2001
From: Romain BERNARD <romain.bernard@uca.fr>
Date: Wed, 4 Sep 2024 17:32:19 +0200
Subject: [PATCH 255/327] add assertions to check if file was properly opened
 in debug

---
 src/instance/Instance.cpp         | 1 +
 src/instance/graph/Graph.cpp      | 4 ++++
 src/instance/requests/Request.cpp | 1 +
 3 files changed, 6 insertions(+)

diff --git a/src/instance/Instance.cpp b/src/instance/Instance.cpp
index 498dcf0..8357603 100644
--- a/src/instance/Instance.cpp
+++ b/src/instance/Instance.cpp
@@ -17,6 +17,7 @@ Instance::Instance(const std::string& graphFilePath,
 
 void Instance::parseRequestsFromFile(const std::string &requestsFilePath) {
     std::ifstream infile(requestsFilePath);
+    assertm(!infile.fail(), "Failed to open the given file");
     DATRow currentRow = DATRow(',');
     std::string currentLine;
     while(infile >> currentRow && !currentRow[0].starts_with('#')) {
diff --git a/src/instance/graph/Graph.cpp b/src/instance/graph/Graph.cpp
index 4118460..63d01dc 100644
--- a/src/instance/graph/Graph.cpp
+++ b/src/instance/graph/Graph.cpp
@@ -26,6 +26,7 @@ Graph::Graph(const std::string& nodesFilePath, const std::string& edgesFilePath,
 
     //Nodes instantiation
     std::ifstream nodesFile(nodesFilePath);
+    assertm(!nodesFile.fail(), "Failed to open the given file");
     std::cout << "Nodes instantiation" << std::endl;
     for(auto& row: CSVRange(nodesFile))
     {
@@ -37,6 +38,7 @@ Graph::Graph(const std::string& nodesFilePath, const std::string& edgesFilePath,
 
     //Edges instantiation
     std::ifstream edgesFile(edgesFilePath);
+    assertm(!edgesFile.fail(), "Failed to open the given file");
     std::cout << "Edges instantiation" << std::endl;
     for(auto& row: CSVRange(edgesFile))
     {
@@ -49,6 +51,7 @@ Graph::Graph(const std::string& nodesFilePath, const std::string& edgesFilePath,
     std::uniform_int_distribution<uint32_t> uint_dist10(1,10);
     std::uniform_int_distribution<uint32_t> uint_dist60(1,60);
     std::ifstream ptLinesFile(ptLinesFilePath);
+    assertm(!ptLinesFile.fail(), "Failed to open the given file");
     std::cout << "Lines instantiation" << std::endl;
     for(auto& row: CSVRange(ptLinesFile))
     {
@@ -64,6 +67,7 @@ Graph::Graph(const std::string& nodesFilePath, const std::string& edgesFilePath,
 
 Graph::Graph(const std::string& datFilePath) {
     std::ifstream infile(datFilePath);
+    assertm(!infile.fail(), "Failed to open the given file");
     DATRow currentRow = DATRow(',');
 
     //-- Read params
diff --git a/src/instance/requests/Request.cpp b/src/instance/requests/Request.cpp
index a062f40..bd91fc7 100644
--- a/src/instance/requests/Request.cpp
+++ b/src/instance/requests/Request.cpp
@@ -73,6 +73,7 @@ std::vector<Request> Request::getRequestsFromFile(const std::string& datFilePath
     std::vector<Request> requests;
 
     std::ifstream infile(datFilePath);
+    assertm(!infile.fail(), "Failed to open the given file");
     DATRow currentRow = DATRow(',');
 
     //-- Read params
-- 
GitLab


From 069204b846ae9e25367f59c8a9d8bfadccfd7e74 Mon Sep 17 00:00:00 2001
From: Romain BERNARD <romain.bernard@uca.fr>
Date: Wed, 4 Sep 2024 17:33:02 +0200
Subject: [PATCH 256/327] remove now unusable debug msg due to removal of
 requestId

---
 src/algorithm/DARP/Heuristics/BestInsertionHeuristic.cpp | 1 -
 1 file changed, 1 deletion(-)

diff --git a/src/algorithm/DARP/Heuristics/BestInsertionHeuristic.cpp b/src/algorithm/DARP/Heuristics/BestInsertionHeuristic.cpp
index fa068f5..0961619 100644
--- a/src/algorithm/DARP/Heuristics/BestInsertionHeuristic.cpp
+++ b/src/algorithm/DARP/Heuristics/BestInsertionHeuristic.cpp
@@ -22,7 +22,6 @@ SAEVRouteChangelist BestInsertionHeuristic::tryVehicleBestInsertion(BestInsertio
     SAEVKeyPoint & requestKp = bestInsertionsQueue.getOriginKp();
     SAEVRouteChangelist lastInsertionChangelist(&route, &requestKp);
 
-    DEBUG_MSG("Trying to insert request " + std::to_string(requestId) + " in vehicle " + std::to_string(vehicleId) + " queue size : " + std::to_string(bestInsertionsQueue.size()));
     while(!bestInsertionsQueue.empty() && !bestInsertionFound) {
         currentBestInsertion = bestInsertionsQueue.topAndPop();
         DEBUG_MSG("Trying insertion " + currentBestInsertion.to_string() + ", remaining : " + std::to_string(bestInsertionsQueue.size()));
-- 
GitLab


From 66d12713bc386474dca9be90b15f217d0af97e36 Mon Sep 17 00:00:00 2001
From: Romain BERNARD <romain.bernard@uca.fr>
Date: Wed, 4 Sep 2024 18:22:01 +0200
Subject: [PATCH 257/327] add subrequest debug logging

---
 src/TimeWindow.cpp                                         | 4 ++++
 src/TimeWindow.h                                           | 3 +++
 .../Multimodal/Heuristics/SimpleModularHeuristic.cpp       | 2 ++
 src/instance/requests/Request.cpp                          | 7 +++++++
 src/instance/requests/Request.h                            | 1 +
 5 files changed, 17 insertions(+)

diff --git a/src/TimeWindow.cpp b/src/TimeWindow.cpp
index 2ac1dd3..c04d424 100644
--- a/src/TimeWindow.cpp
+++ b/src/TimeWindow.cpp
@@ -52,3 +52,7 @@ bool TimeWindow::isInTimeWindow(uint instant) const {
 bool TimeWindow::isInTimeWindow(const TimeWindow &instant) const {
     return this->isInTimeWindow(instant.min) && this->isInTimeWindow(instant.max);
 }
+
+std::string TimeWindow::to_string() const {
+    return "[" + std::to_string(min) + "," + std::to_string(max) + "]";
+}
diff --git a/src/TimeWindow.h b/src/TimeWindow.h
index 5024c7d..76dff6c 100644
--- a/src/TimeWindow.h
+++ b/src/TimeWindow.h
@@ -6,6 +6,7 @@
 #define GREEDYALGORITHM_TIMEWINDOW_H
 
 #include <cstdlib>
+#include <string>
 #include "utils/Globals.h"
 
 /**
@@ -27,6 +28,8 @@ struct TimeWindow {
     */
     [[nodiscard]] bool isInTimeWindow(const TimeWindow& instant) const;
 
+    [[nodiscard]] std::string to_string() const;
+
     TimeWindow operator+(uint rhs) const;
     TimeWindow& operator+=(uint rhs);
     TimeWindow operator-(uint rhs) const;
diff --git a/src/algorithm/Multimodal/Heuristics/SimpleModularHeuristic.cpp b/src/algorithm/Multimodal/Heuristics/SimpleModularHeuristic.cpp
index ac5c6dc..c0f9083 100644
--- a/src/algorithm/Multimodal/Heuristics/SimpleModularHeuristic.cpp
+++ b/src/algorithm/Multimodal/Heuristics/SimpleModularHeuristic.cpp
@@ -90,11 +90,13 @@ SimpleModularHeuristic::insertBestTransitEntryInRoute(const std::vector<Request>
         SAEVRouteChangelist changeList = BestInsertionHeuristic::tryBestRequestInsertionInActiveVehicle(_route->getEntrySubRequestOrigin(requestId), *_route);
         //If we've found an insertion that doesn't create a vehicle, stop there
         if(changeList.success()) {
+            DEBUG_MSG("ENTRY CANDIDATE SUCCESS : " + subreq.to_string());
             return getSubrequest(requestId, true);
         }
     }
 
     //If no active vehicle insertion worked, do best insertion on a new vehicle with the first subrequest (supposedly it's the most advantageous)
+    DEBUG_MSG("CREATE VEHICLE");
     updateSubRequest(requestId, entrySubRequestsList[0], true);
     _route->insertRequestInNewVehicle(_route->getEntrySubRequestOrigin(requestId));
     return getSubrequest(requestId, true);
diff --git a/src/instance/requests/Request.cpp b/src/instance/requests/Request.cpp
index bd91fc7..a693fab 100644
--- a/src/instance/requests/Request.cpp
+++ b/src/instance/requests/Request.cpp
@@ -209,6 +209,13 @@ void Request::resetKeyPoint(int routeIndex) {
     _currentRoute.resetKeyPoint(routeIndex);
 }
 
+std::string Request::to_string() const {
+    std::string res = "O=" + std::to_string(_originNodeIndex) + "," + "D=" + std::to_string(_destinationNodeIndex) //FIXME:replace with std::format whenever possible
+                      + ", " + _departureTW.to_string() + ", " + _arrivalTW.to_string()
+                      + ", w=" + std::to_string(_weight);
+    return res;
+}
+
 std::string Request::to_string_export() const {
     std::string res = std::to_string(_originNodeIndex) + "," + std::to_string(_destinationNodeIndex) //FIXME:replace with std::format whenever possible
             + "," + std::to_string(_arrivalTW.min) + "," + std::to_string(_arrivalTW.max)
diff --git a/src/instance/requests/Request.h b/src/instance/requests/Request.h
index 0dab0c7..8e4f08d 100644
--- a/src/instance/requests/Request.h
+++ b/src/instance/requests/Request.h
@@ -109,6 +109,7 @@ public:
      * @return A properly formatted string to import back again
      */
     [[nodiscard]] std::string to_string_export() const;
+    [[nodiscard]] std::string to_string() const;
 };
 
 
-- 
GitLab


From 09b486ef4c93c5ddfa33d158ba222e3dffa39a0d Mon Sep 17 00:00:00 2001
From: Romain BERNARD <romain.bernard@uca.fr>
Date: Wed, 4 Sep 2024 18:27:21 +0200
Subject: [PATCH 258/327] add global route logging function to log all vehicle
 routes

---
 src/routes/vehicle/SAEVRoute.cpp | 8 ++++++++
 src/routes/vehicle/SAEVRoute.h   | 8 ++++++++
 2 files changed, 16 insertions(+)

diff --git a/src/routes/vehicle/SAEVRoute.cpp b/src/routes/vehicle/SAEVRoute.cpp
index 98b415b..88c7db4 100644
--- a/src/routes/vehicle/SAEVRoute.cpp
+++ b/src/routes/vehicle/SAEVRoute.cpp
@@ -502,3 +502,11 @@ void SAEVRoute::insertRequestInNewVehicle(SAEVKeyPoint &originKp) {
     tryAddRequest(originKp, &getOriginDepot(vehicleId), &getOriginDepot(vehicleId));
 }
 
+std::string SAEVRoute::to_string() {
+    std::string res;
+    for(size_t i = 0; i < _lastActiveVehicleId; ++i){
+        res += "Vehicle #" + std::to_string(i) + ": " + to_string(i) + "\n";
+    }
+    return res;
+}
+
diff --git a/src/routes/vehicle/SAEVRoute.h b/src/routes/vehicle/SAEVRoute.h
index c39b0bc..f9ce97a 100644
--- a/src/routes/vehicle/SAEVRoute.h
+++ b/src/routes/vehicle/SAEVRoute.h
@@ -185,6 +185,14 @@ public:
      */
     bool checkRouteTimeWindows(size_t vehicleId);
 
+    /**
+     * @return A string comprised of every vehicle appended to their own line each
+     */
+    std::string to_string();
+    /**
+     * @param vehicleId ID of the vehicle for which we want to print the current route
+     * @return A string comprised of every keypoint traversed by the vehicle corresponding to the given vehicleId
+     */
     std::string to_string(size_t vehicleId);
     void exportToFile();
 };
-- 
GitLab


From 4093dc965aa5fb8336767306015fad16a9111e29 Mon Sep 17 00:00:00 2001
From: Romain BERNARD <romain.bernard@uca.fr>
Date: Wed, 4 Sep 2024 18:27:59 +0200
Subject: [PATCH 259/327] create a bigger scale test for multimodal insertion
 heuristic debug purposes

---
 .../even_more_requests.dat                    | 39 ++++++++++++++++++
 .../instance_alain_140624/graph.dat           | 41 +++++++++++++++++++
 .../instance_alain_140624/more_requests.dat   | 15 +++++++
 .../instance_alain_140624/requests.dat        |  9 ++++
 .../src/MultimodalInsertionHeuristicDebug.cpp | 34 +++++++++++++++
 5 files changed, 138 insertions(+)
 create mode 100644 resources/test/instances/MultimodalHeuristic/instance_alain_140624/even_more_requests.dat
 create mode 100644 resources/test/instances/MultimodalHeuristic/instance_alain_140624/graph.dat
 create mode 100644 resources/test/instances/MultimodalHeuristic/instance_alain_140624/more_requests.dat
 create mode 100644 resources/test/instances/MultimodalHeuristic/instance_alain_140624/requests.dat

diff --git a/resources/test/instances/MultimodalHeuristic/instance_alain_140624/even_more_requests.dat b/resources/test/instances/MultimodalHeuristic/instance_alain_140624/even_more_requests.dat
new file mode 100644
index 0000000..6099ca0
--- /dev/null
+++ b/resources/test/instances/MultimodalHeuristic/instance_alain_140624/even_more_requests.dat
@@ -0,0 +1,39 @@
+#Global Params (delta ratio)
+1
+#Requests (origin_idx,destination_idx,min_tw_start,max_tw_start,min_tw_end,max_tw_end,delta baseline,capacity)
+1,2,3,6,,,16,1
+3,4,6,9,,,8,1
+5,6,11,13,,,18,1
+7,8,0,4,,,13,1
+9,10,2,7,,,22,1
+11,12,14,16,,,6,1
+1,2,3,6,,,16,1
+3,4,6,9,,,8,1
+5,6,11,13,,,18,1
+7,8,0,4,,,13,1
+9,10,2,7,,,22,1
+11,12,14,16,,,6,1
+1,2,3,6,,,16,1
+3,4,6,9,,,8,1
+5,6,11,13,,,18,1
+7,8,0,4,,,13,1
+9,10,2,7,,,22,1
+11,12,14,16,,,6,1
+1,2,3,6,,,16,1
+3,4,6,9,,,8,1
+5,6,11,13,,,18,1
+7,8,0,4,,,13,1
+9,10,2,7,,,22,1
+11,12,14,16,,,6,1
+1,2,3,6,,,16,1
+3,4,6,9,,,8,1
+5,6,11,13,,,18,1
+7,8,0,4,,,13,1
+9,10,2,7,,,22,1
+11,12,14,16,,,6,1
+1,2,3,6,,,16,1
+3,4,6,9,,,8,1
+5,6,11,13,,,18,1
+7,8,0,4,,,13,1
+9,10,2,7,,,22,1
+11,12,14,16,,,6,1
diff --git a/resources/test/instances/MultimodalHeuristic/instance_alain_140624/graph.dat b/resources/test/instances/MultimodalHeuristic/instance_alain_140624/graph.dat
new file mode 100644
index 0000000..8f87fdf
--- /dev/null
+++ b/resources/test/instances/MultimodalHeuristic/instance_alain_140624/graph.dat
@@ -0,0 +1,41 @@
+#Params (seed)
+123456789
+#Nodes format : status (work, leisure, residential),x,y
+,3,1
+,2,1
+,5,4
+,1,1
+,2,3
+,0,4
+,4,0
+,3,2
+,3,5
+,1,2
+,4,1
+,4,3
+,5,0
+,0,0
+,5,5
+,3,0
+#Edges start,end,length
+0,1,4
+1,3,3
+3,5,5
+5,4,2
+4,2,6
+2,6,7
+6,0,2
+0,7,1
+7,9,3
+9,8,6
+8,11,5
+11,12,4
+12,10,2
+10,0,3
+#PT line format : freq (min), start_time, end_time, node_1, ..., node_n
+5,2,40,1,3,5,6
+5,3,40,6,5,3,1
+3,6,40,7,8,2,12,10,6,0
+3,5,40,0,6,10,12,2,8,7
+4,9,40,14,3,11,9,0,15,6
+4,9,40,6,15,0,9,11,3,14
\ No newline at end of file
diff --git a/resources/test/instances/MultimodalHeuristic/instance_alain_140624/more_requests.dat b/resources/test/instances/MultimodalHeuristic/instance_alain_140624/more_requests.dat
new file mode 100644
index 0000000..12d7cf0
--- /dev/null
+++ b/resources/test/instances/MultimodalHeuristic/instance_alain_140624/more_requests.dat
@@ -0,0 +1,15 @@
+#Global Params (delta ratio)
+1
+#Requests (origin_idx,destination_idx,min_tw_start,max_tw_start,min_tw_end,max_tw_end,delta baseline,capacity)
+1,2,3,6,,,16,1
+3,4,6,9,,,8,1
+5,6,11,13,,,18,1
+7,8,0,4,,,13,1
+9,10,2,7,,,22,1
+11,12,14,16,,,6,1
+1,2,3,6,,,16,1
+3,4,6,9,,,8,1
+5,6,11,13,,,18,1
+7,8,0,4,,,13,1
+9,10,2,7,,,22,1
+11,12,14,16,,,6,1
diff --git a/resources/test/instances/MultimodalHeuristic/instance_alain_140624/requests.dat b/resources/test/instances/MultimodalHeuristic/instance_alain_140624/requests.dat
new file mode 100644
index 0000000..d4e1219
--- /dev/null
+++ b/resources/test/instances/MultimodalHeuristic/instance_alain_140624/requests.dat
@@ -0,0 +1,9 @@
+#Global Params (delta ratio)
+1
+#Requests (origin_idx,destination_idx,min_tw_start,max_tw_start,min_tw_end,max_tw_end,delta baseline,capacity)
+1,2,3,6,,,16,1
+3,4,6,9,,,8,1
+5,6,11,13,,,18,1
+7,8,0,4,,,13,1
+9,10,2,7,,,22,1
+11,12,14,16,,,6,1
\ No newline at end of file
diff --git a/test/src/MultimodalInsertionHeuristicDebug.cpp b/test/src/MultimodalInsertionHeuristicDebug.cpp
index d87cafd..476cb10 100644
--- a/test/src/MultimodalInsertionHeuristicDebug.cpp
+++ b/test/src/MultimodalInsertionHeuristicDebug.cpp
@@ -44,6 +44,40 @@ TEST(MultimodalInsertionHeuristicDebug, DebugBaseInstance) {
     std::cout << "------------------End multimodal insertion (entry)-------------------" << std::endl << std::endl;
 }
 
+TEST(MultimodalInsertionHeuristicDebug, DebugInstanceAlain) {
+    std::string instancesPath = "../../resources/test/instances/MultimodalHeuristic/";
+    std::string instanceFolder = "instance_alain_140624/";
+    std::string graphDatFile = "graph.dat";
+    std::string requestDatFile = "even_more_requests.dat";
+
+
+    //Parse graph
+    INIT_TIMER
+    Graph graphFromSingleFile(instancesPath + instanceFolder + graphDatFile);
+    graphFromSingleFile.computeAndUpdateShortestPathsMatrix(true);
+    std::vector<Request> requests = Request::getRequestsFromFile(instancesPath + instanceFolder + requestDatFile, graphFromSingleFile);
+
+    //Init instance
+    Instance instance(requests,graphFromSingleFile,4);
+    SAEVRoute routesContainer(graphFromSingleFile, requests, true);
+    SimpleModularHeuristic multimodalHeuristic(&graphFromSingleFile, &routesContainer, &requests);
+    STOP_TIMER("Instance parsing and init")
+    std::cout << "------------------Fin parsing instance et route-------------------" << std::endl << std::endl;
+
+    std::cout << "------------------Start preprocessings-------------------" << std::endl << std::endl;
+    START_TIMER
+    graphFromSingleFile.computeAndUpdateShortestTransitPaths();
+    STOP_TIMER("Preprocess")
+    std::cout << "------------------End preprocessings-------------------" << std::endl << std::endl;
+    std::cout << "------------------Start multimodal insertion (entry)-------------------" << std::endl << std::endl;
+    START_TIMER
+    for(size_t i = 0; i < multimodalHeuristic.getNbBaseRquests(); ++i) {
+        multimodalHeuristic.insertBestTransitEntryInRoute(requests[i], i);
+    }
+    STOP_TIMER("Multimodal insertion (entry)")
+    std::cout << "------------------End multimodal insertion (entry)-------------------" << std::endl << std::endl;
+}
+
 int main(int argc, char* argv[]) {
     testing::InitGoogleTest(&argc, argv);
     return RUN_ALL_TESTS();
-- 
GitLab


From 2c9df4ebf7dd5aa8af89018537e61dcd52b6868b Mon Sep 17 00:00:00 2001
From: Romain BERNARD <romain.bernard@uca.fr>
Date: Thu, 5 Sep 2024 12:54:06 +0200
Subject: [PATCH 260/327] fix to_string() missing the last active vehicle

---
 src/routes/vehicle/SAEVRoute.cpp | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/src/routes/vehicle/SAEVRoute.cpp b/src/routes/vehicle/SAEVRoute.cpp
index 88c7db4..7daa464 100644
--- a/src/routes/vehicle/SAEVRoute.cpp
+++ b/src/routes/vehicle/SAEVRoute.cpp
@@ -504,7 +504,7 @@ void SAEVRoute::insertRequestInNewVehicle(SAEVKeyPoint &originKp) {
 
 std::string SAEVRoute::to_string() {
     std::string res;
-    for(size_t i = 0; i < _lastActiveVehicleId; ++i){
+    for(size_t i = 0; i <= _lastActiveVehicleId; ++i){
         res += "Vehicle #" + std::to_string(i) + ": " + to_string(i) + "\n";
     }
     return res;
-- 
GitLab


From feb7b822595a50d9cfb29cdeedcb0a3584879d59 Mon Sep 17 00:00:00 2001
From: Romain BERNARD <romain.bernard@uca.fr>
Date: Thu, 5 Sep 2024 13:39:47 +0200
Subject: [PATCH 261/327] add specific debug messages for multimodal heuristic

---
 .../Multimodal/Heuristics/SimpleModularHeuristic.cpp       | 2 ++
 .../Multimodal/Heuristics/SimpleModularHeuristic.h         | 7 +++++++
 2 files changed, 9 insertions(+)

diff --git a/src/algorithm/Multimodal/Heuristics/SimpleModularHeuristic.cpp b/src/algorithm/Multimodal/Heuristics/SimpleModularHeuristic.cpp
index c0f9083..aabcc23 100644
--- a/src/algorithm/Multimodal/Heuristics/SimpleModularHeuristic.cpp
+++ b/src/algorithm/Multimodal/Heuristics/SimpleModularHeuristic.cpp
@@ -92,6 +92,8 @@ SimpleModularHeuristic::insertBestTransitEntryInRoute(const std::vector<Request>
         if(changeList.success()) {
             DEBUG_MSG("ENTRY CANDIDATE SUCCESS : " + subreq.to_string());
             return getSubrequest(requestId, true);
+        } else {
+            DEBUG_MSG("ENTRY CANDIDATE FAILURE : " + subreq.to_string());
         }
     }
 
diff --git a/src/algorithm/Multimodal/Heuristics/SimpleModularHeuristic.h b/src/algorithm/Multimodal/Heuristics/SimpleModularHeuristic.h
index be4bd4d..23e4d47 100644
--- a/src/algorithm/Multimodal/Heuristics/SimpleModularHeuristic.h
+++ b/src/algorithm/Multimodal/Heuristics/SimpleModularHeuristic.h
@@ -14,6 +14,13 @@
 #include "../../DARP/Heuristics/BestInsertionHeuristic.h"
 #include "../../../../test/lib/googletest/googletest/include/gtest/gtest_prod.h"
 
+#ifdef DEBUG_MULTIMODAL_HEURISTIC
+#include <iostream>
+#define DEBUG_MSG(str) do { std::cout << str << std::endl; } while( false )
+#else
+#define DEBUG_MSG(str) do { } while ( false )
+#endif
+
 class SimpleModularHeuristic {
 private:
     const Graph* _graph{nullptr};
-- 
GitLab


From a34031356e7817dc4ab2a012a299de84ff092794 Mon Sep 17 00:00:00 2001
From: Romain BERNARD <romain.bernard@uca.fr>
Date: Thu, 5 Sep 2024 13:40:32 +0200
Subject: [PATCH 262/327] replace assign to properly replace the request

---
 src/algorithm/Multimodal/Heuristics/SimpleModularHeuristic.cpp | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/src/algorithm/Multimodal/Heuristics/SimpleModularHeuristic.cpp b/src/algorithm/Multimodal/Heuristics/SimpleModularHeuristic.cpp
index aabcc23..1ab4bfb 100644
--- a/src/algorithm/Multimodal/Heuristics/SimpleModularHeuristic.cpp
+++ b/src/algorithm/Multimodal/Heuristics/SimpleModularHeuristic.cpp
@@ -126,7 +126,7 @@ void SimpleModularHeuristic::updateSubRequest(size_t requestId, const Request &r
         _requestsVect->emplace_back(request);
         assertm((_requestsVect->size() - 1) == subRequestIndex,"A request seems to have been missed or doesn't have any subrequest defined");
     } else {
-        _requestsVect->assign(subRequestIndex, request);
+        (*_requestsVect)[subRequestIndex] = request;
     }
 
     std::vector<Request>& requestVectRef = *_requestsVect;
-- 
GitLab


From 09fa2822ee1fe3baeabe97959edc0bb45a6a6c25 Mon Sep 17 00:00:00 2001
From: Romain BERNARD <romain.bernard@uca.fr>
Date: Thu, 5 Sep 2024 13:56:54 +0200
Subject: [PATCH 263/327] Add Emma Lacoste's visualisation scripts (no account
 for her on LIMOS' Gitlab, so I can't properly add authorship)

---
 src/utils/Python visualiser/final.py   |  54 ++++++++
 src/utils/Python visualiser/graphe.py  | 171 +++++++++++++++++++++++++
 src/utils/Python visualiser/main.py    |  13 ++
 src/utils/Python visualiser/voiture.py |  78 +++++++++++
 4 files changed, 316 insertions(+)
 create mode 100644 src/utils/Python visualiser/final.py
 create mode 100644 src/utils/Python visualiser/graphe.py
 create mode 100644 src/utils/Python visualiser/main.py
 create mode 100644 src/utils/Python visualiser/voiture.py

diff --git a/src/utils/Python visualiser/final.py b/src/utils/Python visualiser/final.py
new file mode 100644
index 0000000..ef60dec
--- /dev/null
+++ b/src/utils/Python visualiser/final.py	
@@ -0,0 +1,54 @@
+from graphe import Graphe
+from voiture import lire_fichier_routes, afficher_routes, tracer_routes, recuperer_identifiants_noeuds
+import matplotlib.pyplot as plt
+import random
+import numpy as np
+
+def couleur_aleatoire():
+    return (random.randint(0, 255) / 255, random.randint(0, 255) / 255, random.randint(0, 255) / 255)
+
+def afficher_routes_et_graphe(graphe, routes):
+    fig, ax = plt.subplots()
+    ax.axis('off')
+    
+    graphe.tracer_noeuds(fig, ax)
+
+    liste_identifiants_noeuds = recuperer_identifiants_noeuds(routes)
+    liste_coordonnees = [] 
+    for route in liste_identifiants_noeuds:
+        route_coords = []
+        for identifiant in route:
+            x, y = graphe.get_coordonnees(identifiant + 1)
+            route_coords.append((x, y))
+        liste_coordonnees.append(route_coords)
+        
+    rayon = 0.1 
+    for route in liste_coordonnees:
+        couleur = couleur_aleatoire()
+        for i in range(len(route) - 1):  
+            x_start, y_start = route[i][0], route[i][1]
+            x_end, y_end = route[i + 1][0], route[i + 1][1]
+            
+            """
+            dx = x_end - x_start
+            dy = y_end - y_start
+            distance = np.sqrt(dx**2 + dy**2)
+            if distance != 0:
+                cosinus = dx = distance
+                dy /= distance
+                
+            # normaliser le vecteur = le même vecteur mais avec une norme 1 
+            
+            x_start_adj = x_start + dx * rayon  # on ajoute au début de la flèche le début du vecteur 
+            y_start_adj = y_start + dy * rayon
+            x_end_adj = x_end - dx * rayon  # idem mais on soustrait 
+            y_end_adj = y_end - dy * rayon 
+            """
+            ax.annotate("", xy=(x_end, y_end), xytext=(x_start, y_start), arrowprops=dict(arrowstyle="->", color=couleur))
+            
+            # xy=(x_end, y_end) = position de la pointe de la flèche.
+            # xytext=(x_start, y_start) = position de la base de la flèche
+            
+    ax.set_title('Réseau de transport et routes')
+    fig.savefig("graphe_avec_routes.png")
+    plt.close(fig)
diff --git a/src/utils/Python visualiser/graphe.py b/src/utils/Python visualiser/graphe.py
new file mode 100644
index 0000000..4e72d4a
--- /dev/null
+++ b/src/utils/Python visualiser/graphe.py	
@@ -0,0 +1,171 @@
+import numpy as np
+import matplotlib.pyplot as plt
+import matplotlib.patches as patches
+import random
+from matplotlib.patches import Circle, RegularPolygon
+import sys
+import math
+
+def couleur_aleatoire():
+    return (random.randint(0, 255) / 255, random.randint(0, 255) / 255, random.randint(0, 255) / 255)
+
+class Graphe:
+    def __init__(self):
+        self.noeuds = {}  # {"1" : {1, 2}}
+        self.lignes = []
+        self.depot_node = 0
+        self.matrice_temps = []
+
+    def ajouter_noeud(self, identifiant, x, y):   # l'identifiant (commence à 1) du noeud et ses coordonnées 
+        self.noeuds[int(identifiant)] = {'x': x, 'y': y}
+
+    def ajouter_ligne(self, freq, start_time, end_time, noeuds):
+        self.lignes.append({'freq': freq, 'start_time': start_time, 'end_time': end_time, 'noeuds': noeuds}) 
+        
+    def ajouter_matrice(self, temps):
+        self.matrice_temps.append(temps)
+        
+    def get_distance(self, id_noeud1, id_noeud2):
+        index_noeud1 = id_noeud1 - 1
+        index_noeud2 = id_noeud2 - 1
+        distance = self.matrice_temps[index_noeud1][index_noeud2]
+        return distance
+    
+    def get_coordonnees(self, identifiant):
+        if identifiant in self.noeuds:
+            return self.noeuds[identifiant]['x'], self.noeuds[identifiant]['y']
+        else:
+            raise ValueError(f"Le noeud avec l'identifiant {identifiant} n'existe pas.")   
+        
+    def lire_fichier(self, chemin_fichier):
+        with open(chemin_fichier, 'r') as fichier:
+            bool_noeuds = False 
+            bool_ligne = False
+            bool_matrice = False
+            lignes_a_sauter = 0
+
+            for ligne in fichier:
+                ligne = ligne.strip()  # Supprime les espaces blancs
+                if lignes_a_sauter > 0:
+                    lignes_a_sauter -= 1
+                    continue
+                if ligne.startswith("#Params"):
+                    lignes_a_sauter = 1
+                    continue
+                if ligne.startswith("#Nodes format"):
+                    bool_noeuds = True
+                    bool_ligne = False
+                    bool_matrice = False
+                    continue
+                if ligne.startswith("#Matrix"):
+                    bool_noeuds = False 
+                    bool_ligne = False
+                    bool_matrice = True
+                if ligne.startswith("#PT line format"):
+                    bool_noeuds = False
+                    bool_ligne = True
+                    bool_matrice = False
+                    continue 
+                if ligne.startswith("#Depot node index"):
+                    bool_noeuds = False
+                    bool_ligne = False
+                    bool_matrice = False
+                    self.depot_node = int(fichier.readline().strip())
+                    continue 
+                
+                if bool_ligne:
+                    parties = ligne.split(',') 
+                    parties = [str(x) for x in parties]
+                    freq = parties[0]
+                    start_time = parties[1]
+                    end_time = parties[2]
+                    noeuds = parties[3:]
+                    self.ajouter_ligne(freq, start_time, end_time, noeuds)
+
+                if bool_noeuds:
+                    _, x, y = ligne.split(',')   
+                    identifiant = len(self.noeuds) + 1  # commence à 1 
+                    self.ajouter_noeud(identifiant, int(x), int(y))
+                    
+                if bool_matrice:
+                    for i in range(len(self.noeuds)):
+                        ligne_matrice = list(map(int, fichier.readline().strip().split(',')))
+                        self.ajouter_matrice(ligne_matrice)
+                        continue
+                        
+    def tracer_noeuds(self, fig, ax):
+        for identifiant, coordonnees in self.noeuds.items():
+            x = coordonnees['x']
+            y = coordonnees['y']
+            if identifiant == self.depot_node + 1: # tracer le noeud de dépôt avec un triangle noir
+                triangle = RegularPolygon((x, y), numVertices=3, radius=0.1, color='black')
+                ax.add_patch(triangle)
+            else:
+                ax.scatter(x, y, color='blue', label=f'Noeud {identifiant}')   
+                circle = Circle((x, y), radius=0.1, color="red")   # pour que les stations soient représentées par des ronds sur la figure 
+                ax.add_patch(circle)
+                
+                ax.annotate(f'Noeud {identifiant}', (x, y))
+                
+        return fig, ax
+    
+    def tracer_lignes(self, fig, ax):
+        for ligne in self.lignes:
+            liste_noeuds_ligne = list(map(int, ligne["noeuds"]))
+            couleur_aleatoire = couleur_aleatoire()
+            for i in range(len(liste_noeuds_ligne) - 1): 
+                noeud_depart = int(liste_noeuds_ligne[i])
+                noeud_arrive = int(liste_noeuds_ligne[i + 1])
+                x_depart = self.noeuds[noeud_depart]['x']
+                y_depart = self.noeuds[noeud_depart]['y']
+                x_arrive = self.noeuds[noeud_arrive]['x']
+                y_arrive = self.noeuds[noeud_arrive]['y']
+                temps = self.matrice_temps[noeud_depart - 1][noeud_arrive - 1] 
+                ax.plot([x_depart, x_arrive], [y_depart, y_arrive], color=couleur_aleatoire)
+                milieu_x = (x_depart + x_arrive) / 2
+                milieu_y = (y_depart + y_arrive) / 2
+                
+          
+                if x_depart < x_arrive:
+                    h = 'top'  
+                else:
+                    h = 'left'
+                ax.text(milieu_x, milieu_y, f"{temps}", ha=h, va='center')
+                
+        return fig, ax
+    
+    def tracer_arrete(self, ax, x1, y1, x2, y2, couleur):
+        ax.plot([x1, x2], [y1, y2], color=couleur)
+                        
+    def sauvegarder_graphe(self):
+        fig, ax = plt.subplots() 
+        
+        fig, ax = tracer_noeuds(fig, ax)
+        fig, ax = tracer_lignes(fig, ax)
+    
+        # pour que la figure contienne toutes les stations (que ça ne dépasse pas) : 
+        min_x = min(coordonnees['x'] for coordonnees in self.noeuds.values())
+        max_x = max(coordonnees['x'] for coordonnees in self.noeuds.values())
+        min_y = min(coordonnees['y'] for coordonnees in self.noeuds.values())
+        max_y = max(coordonnees['y'] for coordonnees in self.noeuds.values())
+        ax.set_xlim(min_x - 1, max_x + 1) 
+        ax.set_ylim(min_y - 1, max_y + 1)
+
+        ax.set_xlabel('X')
+        ax.set_ylabel('Y')
+        ax.set_title('Graphe')
+        fig.savefig("graphe.png")
+        plt.close(fig)
+        
+    def afficher_graphe(self):
+        print("Les stations :")
+        for identifiant, coordonnees in self.noeuds.items():
+            print(f"Identifiant : {identifiant}, Coordonnées : ({coordonnees['x']}, {coordonnees['y']})")
+
+        print("\nLes lignes :")
+        for ligne in self.lignes:
+            print(f"Fréquence : {ligne['freq']} min, Début : {ligne['start_time']} min, Fin : {ligne['end_time']} min, Stations : {ligne['noeuds']}")
+
+        if self.depot_node is not None:
+            print(f"\nNoeud de dépôt : {self.depot_node}")
+            
\ No newline at end of file
diff --git a/src/utils/Python visualiser/main.py b/src/utils/Python visualiser/main.py
new file mode 100644
index 0000000..9c7a132
--- /dev/null
+++ b/src/utils/Python visualiser/main.py	
@@ -0,0 +1,13 @@
+from graphe import Graphe
+from voiture import lire_fichier_routes, afficher_routes, tracer_routes, recuperer_identifiants_noeuds
+from final import afficher_routes_et_graphe
+
+def main():
+    graphe = Graphe()
+    
+    graphe.lire_fichier("graph.txt")
+    routes = lire_fichier_routes("saev_routes.out")
+
+    afficher_routes_et_graphe(graphe, routes)
+
+main()
diff --git a/src/utils/Python visualiser/voiture.py b/src/utils/Python visualiser/voiture.py
new file mode 100644
index 0000000..786e644
--- /dev/null
+++ b/src/utils/Python visualiser/voiture.py	
@@ -0,0 +1,78 @@
+import matplotlib.pyplot as plt
+import random
+import math
+import time
+
+from graphe import Graphe
+
+def couleur_aleatoire():
+    return (random.randint(0, 255) / 255, random.randint(0, 255) / 255, random.randint(0, 255) / 255)
+
+def lire_fichier_routes(chemin_fichier):
+    routes = []
+    with open(chemin_fichier, 'r') as fichier:
+        for ligne in fichier:
+            if ligne.startswith("#SAEV Route format"):
+                continue
+            points_passage = ligne.strip().split(';')
+            route = []
+            for point in points_passage:
+                contenu = point.strip('()').split(',')
+                identifiant_noeud = contenu[0]
+                identifiant_requete = contenu[1]
+                fenetre_temps_min = contenu[2]
+                fenetre_temps_max = contenu[3]
+                route.append((identifiant_noeud, identifiant_requete, fenetre_temps_min, fenetre_temps_max))
+            routes.append(route)
+    return routes
+
+def afficher_routes(routes):
+    for i in range(len(routes)):
+        route = routes[i]
+        for point in route:
+            identifiant_noeud = int(point[0]) + 1
+            fenetre_temps_min = point[2]
+            fenetre_temps_max = point[3]
+            print(f"Noeud {identifiant_noeud} Fenêtre de temps ({fenetre_temps_min}, {fenetre_temps_max})")
+        print()
+
+def tracer_routes(routes, graphe, chemin_fichier):
+    fig, ax = plt.subplots()
+    ax.axis('off')
+    for i in range(len(routes)):
+        route = routes[i]
+        for j in range(len(route)):    # j est un point de passage 
+            noeud, id_requete, tw_min, tw_max = route[j]
+
+            if id_requete:  # Utilisation d'une graine aléatoire spécifique pour les couleurs
+                random.seed(int(id_requete))
+            else:
+                random.seed(int(time.time()))  # Utilisation du timestamp actuel comme graine aléatoire
+
+            couleur_aleatoire = couleur_aleatoire()
+
+            noeud = int(noeud)
+            label = f"({tw_min},{tw_max})"
+            ax.scatter(j, i+1, color=couleur_aleatoire, s=10)
+            ax.text(j, i+1 - 0.2, label, ha='center', va='top', fontsize=8)
+            ax.text(j, i+1 + 0.1, f"NÅ“ud {noeud}", ha='center', va='bottom', fontsize=8)
+            
+            if j < len(route) - 1:
+                noeud_suivant = int(route[j + 1][0])   # point de passage suivant 
+                distance = graphe.get_distance(noeud+1, noeud_suivant+1)
+                milieu_x = (j + (j + 1)) / 2
+                milieu_y = (i + 1 + (i + 1)) / 2
+                ax.text(milieu_x, milieu_y - 0.1, f"{distance:.2f}", ha='center', va='center', fontsize=8)
+                ax.plot([j, j+1], [i+1, i+1], color='black')
+
+    fig.savefig(chemin_fichier)
+    plt.close(fig)
+    
+def recuperer_identifiants_noeuds(routes):
+    identifiants_noeuds = []
+    for route in routes:
+        noeuds_route=[]
+        for point in route:
+            noeuds_route.append(int(point[0]))
+        identifiants_noeuds.append(noeuds_route)
+    return identifiants_noeuds
-- 
GitLab


From 4b426bb9a4a98f05315e1c02ac2f18a9b81a3ee1 Mon Sep 17 00:00:00 2001
From: Romain BERNARD <romain.bernard@uca.fr>
Date: Thu, 5 Sep 2024 17:15:23 +0200
Subject: [PATCH 264/327] make the actual insertion function generic for
 entries/exits subrequests

---
 .../Heuristics/SimpleModularHeuristic.cpp     | 32 ++++++++++++++-----
 .../Heuristics/SimpleModularHeuristic.h       |  3 +-
 2 files changed, 26 insertions(+), 9 deletions(-)

diff --git a/src/algorithm/Multimodal/Heuristics/SimpleModularHeuristic.cpp b/src/algorithm/Multimodal/Heuristics/SimpleModularHeuristic.cpp
index 1ab4bfb..80925c2 100644
--- a/src/algorithm/Multimodal/Heuristics/SimpleModularHeuristic.cpp
+++ b/src/algorithm/Multimodal/Heuristics/SimpleModularHeuristic.cpp
@@ -73,25 +73,27 @@ Request SimpleModularHeuristic::insertBestTransitEntryInRoute(const Request &bas
     for(auto const& access : entriesAccessList) {
         entrySubRequestsList.emplace_back(*_graph, baseRequest, access, true);
     }
-    return insertBestTransitEntryInRoute(entrySubRequestsList, requestId);
+    return insertBestTransitAccessInRoute(entrySubRequestsList, requestId, true);
 }
 
 /**
  * The insertion process first tries best insertions without creating a new vehicles in order of the best entries list.
  * If none result in a valid insertion, we insert the first subrequest (supposedly the better one) in a new vehicle
- * @param entrySubRequestsList A list of entry subrequest candidates, preferably ordered from best to worst candidate, but the list order is implementation dependant
+ * @param accessSubRequestsList A list of entry subrequest candidates, preferably ordered from best to worst candidate, but the list order is implementation dependant
  * @param requestId ID/index in the request vector for our base request
+ * @param isEntry true iff the given access requests are transit entry requests
  * @return The subrequest successfully inserted in our route. This method's caller needs to add this request to its main request vector
  */
 const Request &
-SimpleModularHeuristic::insertBestTransitEntryInRoute(const std::vector<Request>& entrySubRequestsList, size_t requestId) {
-    for(const auto& subreq : entrySubRequestsList) {
-        updateSubRequest(requestId, subreq, true);
+SimpleModularHeuristic::insertBestTransitAccessInRoute(const std::vector<Request> &accessSubRequestsList,
+                                                       size_t requestId, bool isEntry) {
+    for(const auto& subreq : accessSubRequestsList) {
+        updateSubRequest(requestId, subreq, isEntry);
         SAEVRouteChangelist changeList = BestInsertionHeuristic::tryBestRequestInsertionInActiveVehicle(_route->getEntrySubRequestOrigin(requestId), *_route);
         //If we've found an insertion that doesn't create a vehicle, stop there
         if(changeList.success()) {
             DEBUG_MSG("ENTRY CANDIDATE SUCCESS : " + subreq.to_string());
-            return getSubrequest(requestId, true);
+            return getSubrequest(requestId, isEntry);
         } else {
             DEBUG_MSG("ENTRY CANDIDATE FAILURE : " + subreq.to_string());
         }
@@ -99,9 +101,9 @@ SimpleModularHeuristic::insertBestTransitEntryInRoute(const std::vector<Request>
 
     //If no active vehicle insertion worked, do best insertion on a new vehicle with the first subrequest (supposedly it's the most advantageous)
     DEBUG_MSG("CREATE VEHICLE");
-    updateSubRequest(requestId, entrySubRequestsList[0], true);
+    updateSubRequest(requestId, accessSubRequestsList[0], isEntry);
     _route->insertRequestInNewVehicle(_route->getEntrySubRequestOrigin(requestId));
-    return getSubrequest(requestId, true);
+    return getSubrequest(requestId, isEntry);
 }
 
 const Graph *SimpleModularHeuristic::getGraph() const {
@@ -144,3 +146,17 @@ size_t SimpleModularHeuristic::getSubrequestIndex(size_t requestId, bool isEntry
 const Request& SimpleModularHeuristic::getSubrequest(size_t requestId, bool isEntry) {
     return (*_requestsVect)[getSubrequestIndex(requestId, isEntry)];
 }
+
+double SimpleModularHeuristic::getTransitExitScore(const Request &baseRequest, const TransitAccess &exitData) {
+    return _graph->getShortestSAEVPath(exitData.getAccessNodeIdx(), baseRequest.getDestinationNodeIndex())
+           + exitData.getAccessTimestamp();
+}
+
+uint SimpleModularHeuristic::getMinExitConstraint(size_t baseRequestId, const TransitAccess &exitData) {
+    return 0;
+}
+
+uint SimpleModularHeuristic::getMaxExitConstraint(size_t baseRequestId, const TransitAccess &exitData) {
+    const Request& baseRequest = (*_requestsVect)[baseRequestId];
+    return baseRequest.getMaxArrivalTw() - _graph->getShortestSAEVPath(exitData.getAccessNodeIdx(), baseRequest.getDestinationNodeIndex());
+}
diff --git a/src/algorithm/Multimodal/Heuristics/SimpleModularHeuristic.h b/src/algorithm/Multimodal/Heuristics/SimpleModularHeuristic.h
index 23e4d47..2751272 100644
--- a/src/algorithm/Multimodal/Heuristics/SimpleModularHeuristic.h
+++ b/src/algorithm/Multimodal/Heuristics/SimpleModularHeuristic.h
@@ -48,7 +48,8 @@ private:
 
     Request insertBestTransitEntryInRoute(const Request &baseRequest, size_t requestId);
     Request insertBestTransitEntryInRoute(const Request &baseRequest, const std::vector<TransitAccess>& entriesAccessList, size_t requestId);
-    const Request & insertBestTransitEntryInRoute(const std::vector<Request>& entrySubRequestsList, size_t requestId);
+    const Request &insertBestTransitAccessInRoute(const std::vector<Request> &accessSubRequestsList,
+                                                  size_t requestId, bool isEntry);
 
     void insertBestTransitExitsInRoute(const std::vector<Request>& baseRequestsList, const std::vector<TransitAccess>& transitEntriesList);
 
-- 
GitLab


From 58d9641349762ad56ff1afb272c561481e75da6f Mon Sep 17 00:00:00 2001
From: Romain BERNARD <romain.bernard@uca.fr>
Date: Thu, 5 Sep 2024 17:20:22 +0200
Subject: [PATCH 265/327] implement min/max/scoring functions for exit requests
 (modify via override if needed)

---
 .../Heuristics/SimpleModularHeuristic.h       | 29 +++++++++++++++++--
 1 file changed, 26 insertions(+), 3 deletions(-)

diff --git a/src/algorithm/Multimodal/Heuristics/SimpleModularHeuristic.h b/src/algorithm/Multimodal/Heuristics/SimpleModularHeuristic.h
index 2751272..4c5924c 100644
--- a/src/algorithm/Multimodal/Heuristics/SimpleModularHeuristic.h
+++ b/src/algorithm/Multimodal/Heuristics/SimpleModularHeuristic.h
@@ -91,8 +91,31 @@ protected:
     [[nodiscard]] uint getMinEntryConstraint(const Request &request, size_t ptEntryNodeIdx) const;
     [[nodiscard]] uint getMaxEntryConstraint(const Request &request, size_t ptEntryNodeIdx) const;
     //Exit filter
-    uint getMinExitConstraint(const Request &request, size_t exitNodeIndex);
-    uint getMaxExitConstraint(const Request &request, size_t exitNodeIndex);
+    /**
+     * Base implementation of min exit constraint.
+     * This implementation is equivalent to no min constraint, as our subset of possible moves already filters our options a bit
+     * @param baseRequest
+     * @param exitNodeIndex
+     * @return
+     */
+    [[nodiscard]] uint getMinExitConstraint(size_t baseRequestId, const TransitAccess &exitData);
+    /**
+     * Base implementation of max exit constraint.
+     * This base implementation just checks for arrival validity wrt the base request's max time window
+     * @param baseRequestId Id of the base request for which we generate exit subrequests. Necessary to get data on base request and entry subrequest if necessary
+     * @param exitData Data containing the exit node and timestamp
+     * @return baseRequest.DestinationTW.max - T(exitData.Node, baseRequest.Destination)
+     */
+    [[nodiscard]] uint getMaxExitConstraint(size_t baseRequestId, const TransitAccess &exitData);
+    /**
+     * Base implementation of a sorting score (lower is better) for exit candidates.
+     * This implementation scores via T(exitNode, destinationNode) + exitTime to try and
+     * incentivize early and/or close access points
+     * @param baseRequest the base request, required to get the destination
+     * @param exitData exit data containing the exit point and timestamp
+     * @return A score allowing to sort transit exits in ascending score order
+     */ //TODO: try other scoring functions (current other idea : T(exitNode, destinationNode) * exitTime; alpha*T(exitNode, destinationNode) + exitTime)
+    [[nodiscard]] double getTransitExitScore(const Request& baseRequest, const TransitAccess& exitData);
 
     [[nodiscard]] const Graph *getGraph() const;
     void setGraph(const Graph *graph);
@@ -102,7 +125,7 @@ protected:
 
     void updateSubRequest(size_t requestId, const Request &request, bool isEntry);
 
-    size_t getSubrequestIndex(size_t requestId, bool isEntry) const;
+    [[nodiscard]] size_t getSubrequestIndex(size_t requestId, bool isEntry) const;
 
     const Request &getSubrequest(size_t requestId, bool isEntry);
 };
-- 
GitLab


From 204a7d88743f72c8438c46e144f4a20dda084803 Mon Sep 17 00:00:00 2001
From: Romain BERNARD <romain.bernard@uca.fr>
Date: Thu, 5 Sep 2024 17:22:33 +0200
Subject: [PATCH 266/327] rename parameter for more clarity

---
 .../Heuristics/SimpleModularHeuristic.cpp     | 28 +++++++++----------
 .../Heuristics/SimpleModularHeuristic.h       |  6 ++--
 2 files changed, 17 insertions(+), 17 deletions(-)

diff --git a/src/algorithm/Multimodal/Heuristics/SimpleModularHeuristic.cpp b/src/algorithm/Multimodal/Heuristics/SimpleModularHeuristic.cpp
index 80925c2..113dace 100644
--- a/src/algorithm/Multimodal/Heuristics/SimpleModularHeuristic.cpp
+++ b/src/algorithm/Multimodal/Heuristics/SimpleModularHeuristic.cpp
@@ -49,12 +49,12 @@ uint SimpleModularHeuristic::getMaxEntryConstraint(const Request &request, size_
  * The insertion process first tries best insertions without creating a new vehicles in order of the best entries list.
  * If none result in a valid insertion, we insert the first subrequest (supposedly the better one) in a new vehicle
  * @param baseRequest const ref to the request we use as our base to get the best entries list
- * @param requestId ID/index in the request vector for our base request
+ * @param baseRequestId ID/index in the request vector for our base request
  * @return The subrequest successfully inserted in our route. This method's caller needs to add this request to its main request vector
  */
-Request SimpleModularHeuristic::insertBestTransitEntryInRoute(const Request &baseRequest, size_t requestId) {
+Request SimpleModularHeuristic::insertBestTransitEntryInRoute(const Request &baseRequest, size_t baseRequestId) {
     std::vector<TransitAccess> entriesAccessList = getBestTransitEntriesList(baseRequest);
-    return insertBestTransitEntryInRoute(baseRequest, entriesAccessList, requestId);
+    return insertBestTransitEntryInRoute(baseRequest, entriesAccessList, baseRequestId);
 }
 
 /**
@@ -63,37 +63,37 @@ Request SimpleModularHeuristic::insertBestTransitEntryInRoute(const Request &bas
  * If none result in a valid insertion, we insert the first subrequest (supposedly the better one) in a new vehicle
  * @param baseRequest const ref to the request we use as our base to generate subrequest frm the best entries list
  * @param entriesAccessList A list of best entries, preferably ordered from best to worst and sized according to the max number of candidates we want to try inserting
- * @param requestId ID/index in the request vector for our base request
+ * @param baseRequestId ID/index in the request vector for our base request
  * @return The subrequest successfully inserted in our route. This method's caller needs to add this request to its main request vector
  */
-Request SimpleModularHeuristic::insertBestTransitEntryInRoute(const Request &baseRequest, const std::vector<TransitAccess>& entriesAccessList, size_t requestId) {
+Request SimpleModularHeuristic::insertBestTransitEntryInRoute(const Request &baseRequest, const std::vector<TransitAccess>& entriesAccessList, size_t baseRequestId) {
     std::vector<Request> entrySubRequestsList;
     entrySubRequestsList.reserve(Constants::MAX_TRANSIT_ENTRY_CANDIDATES); //Init entry subrequests list to the appropriate size
     //Generate subrequests from best transit entries
     for(auto const& access : entriesAccessList) {
         entrySubRequestsList.emplace_back(*_graph, baseRequest, access, true);
     }
-    return insertBestTransitAccessInRoute(entrySubRequestsList, requestId, true);
+    return insertBestTransitAccessInRoute(entrySubRequestsList, baseRequestId, true);
 }
 
 /**
  * The insertion process first tries best insertions without creating a new vehicles in order of the best entries list.
  * If none result in a valid insertion, we insert the first subrequest (supposedly the better one) in a new vehicle
  * @param accessSubRequestsList A list of entry subrequest candidates, preferably ordered from best to worst candidate, but the list order is implementation dependant
- * @param requestId ID/index in the request vector for our base request
+ * @param baseRequestId ID/index in the request vector for our base request
  * @param isEntry true iff the given access requests are transit entry requests
  * @return The subrequest successfully inserted in our route. This method's caller needs to add this request to its main request vector
  */
 const Request &
 SimpleModularHeuristic::insertBestTransitAccessInRoute(const std::vector<Request> &accessSubRequestsList,
-                                                       size_t requestId, bool isEntry) {
+                                                       size_t baseRequestId, bool isEntry) {
     for(const auto& subreq : accessSubRequestsList) {
-        updateSubRequest(requestId, subreq, isEntry);
-        SAEVRouteChangelist changeList = BestInsertionHeuristic::tryBestRequestInsertionInActiveVehicle(_route->getEntrySubRequestOrigin(requestId), *_route);
+        updateSubRequest(baseRequestId, subreq, isEntry);
+        SAEVRouteChangelist changeList = BestInsertionHeuristic::tryBestRequestInsertionInActiveVehicle(_route->getEntrySubRequestOrigin(baseRequestId), *_route);
         //If we've found an insertion that doesn't create a vehicle, stop there
         if(changeList.success()) {
             DEBUG_MSG("ENTRY CANDIDATE SUCCESS : " + subreq.to_string());
-            return getSubrequest(requestId, isEntry);
+            return getSubrequest(baseRequestId, isEntry);
         } else {
             DEBUG_MSG("ENTRY CANDIDATE FAILURE : " + subreq.to_string());
         }
@@ -101,9 +101,9 @@ SimpleModularHeuristic::insertBestTransitAccessInRoute(const std::vector<Request
 
     //If no active vehicle insertion worked, do best insertion on a new vehicle with the first subrequest (supposedly it's the most advantageous)
     DEBUG_MSG("CREATE VEHICLE");
-    updateSubRequest(requestId, accessSubRequestsList[0], isEntry);
-    _route->insertRequestInNewVehicle(_route->getEntrySubRequestOrigin(requestId));
-    return getSubrequest(requestId, isEntry);
+    updateSubRequest(baseRequestId, accessSubRequestsList[0], isEntry);
+    _route->insertRequestInNewVehicle(_route->getEntrySubRequestOrigin(baseRequestId));
+    return getSubrequest(baseRequestId, isEntry);
 }
 
 const Graph *SimpleModularHeuristic::getGraph() const {
diff --git a/src/algorithm/Multimodal/Heuristics/SimpleModularHeuristic.h b/src/algorithm/Multimodal/Heuristics/SimpleModularHeuristic.h
index 4c5924c..799c403 100644
--- a/src/algorithm/Multimodal/Heuristics/SimpleModularHeuristic.h
+++ b/src/algorithm/Multimodal/Heuristics/SimpleModularHeuristic.h
@@ -46,10 +46,10 @@ public:
 //Private members for heuristic internal functions we don't wish to see overriden
 private:
 
-    Request insertBestTransitEntryInRoute(const Request &baseRequest, size_t requestId);
-    Request insertBestTransitEntryInRoute(const Request &baseRequest, const std::vector<TransitAccess>& entriesAccessList, size_t requestId);
+    Request insertBestTransitEntryInRoute(const Request &baseRequest, size_t baseRequestId);
+    Request insertBestTransitEntryInRoute(const Request &baseRequest, const std::vector<TransitAccess>& entriesAccessList, size_t baseRequestId);
     const Request &insertBestTransitAccessInRoute(const std::vector<Request> &accessSubRequestsList,
-                                                  size_t requestId, bool isEntry);
+                                                  size_t baseRequestId, bool isEntry);
 
     void insertBestTransitExitsInRoute(const std::vector<Request>& baseRequestsList, const std::vector<TransitAccess>& transitEntriesList);
 
-- 
GitLab


From 53a725efaab6cae9638dcda6afcb0ca5949ee100 Mon Sep 17 00:00:00 2001
From: Romain BERNARD <romain.bernard@uca.fr>
Date: Thu, 5 Sep 2024 18:19:40 +0200
Subject: [PATCH 267/327] docs edition

---
 .../Multimodal/Heuristics/SimpleModularHeuristic.h          | 6 +++---
 1 file changed, 3 insertions(+), 3 deletions(-)

diff --git a/src/algorithm/Multimodal/Heuristics/SimpleModularHeuristic.h b/src/algorithm/Multimodal/Heuristics/SimpleModularHeuristic.h
index 799c403..7ec22da 100644
--- a/src/algorithm/Multimodal/Heuristics/SimpleModularHeuristic.h
+++ b/src/algorithm/Multimodal/Heuristics/SimpleModularHeuristic.h
@@ -94,9 +94,9 @@ protected:
     /**
      * Base implementation of min exit constraint.
      * This implementation is equivalent to no min constraint, as our subset of possible moves already filters our options a bit
-     * @param baseRequest
-     * @param exitNodeIndex
-     * @return
+     * @param baseRequestId Id of the base request for which we generate exit subrequests. Necessary to get data on base request and entry subrequest if necessary
+     * @param exitData Data containing the exit node and timestamp
+     * @return 0
      */
     [[nodiscard]] uint getMinExitConstraint(size_t baseRequestId, const TransitAccess &exitData);
     /**
-- 
GitLab


From e79691d49542cf7467bc9759f1af6999f23387f8 Mon Sep 17 00:00:00 2001
From: Romain BERNARD <romain.bernard@uca.fr>
Date: Fri, 6 Sep 2024 13:57:54 +0200
Subject: [PATCH 268/327] take into account that the container can be setup to
 hold cells for every possible goal node

---
 .../Transit/TransitShortestPathContainer.cpp          | 11 ++++++++---
 1 file changed, 8 insertions(+), 3 deletions(-)

diff --git a/src/ShortestPath/Transit/TransitShortestPathContainer.cpp b/src/ShortestPath/Transit/TransitShortestPathContainer.cpp
index a3700e7..0dc3dbd 100644
--- a/src/ShortestPath/Transit/TransitShortestPathContainer.cpp
+++ b/src/ShortestPath/Transit/TransitShortestPathContainer.cpp
@@ -36,9 +36,14 @@ TransitShortestPathContainer::getShortestPathsFrom(size_t startNodeIndex, uint e
 TransitShortestPath
 TransitShortestPathContainer::getShortestPathToYFromTime(size_t startNodeIndex, uint earliestStartInstant, size_t goalNode) {
     auto [startNode, shortestPathsVector] = getShortestPathsFrom(startNodeIndex, earliestStartInstant);
-    for(const auto& shortestPath : shortestPathsVector) {
-        if(shortestPath.getArrivalNode() == goalNode) {
-            return shortestPath;
+    //Check if destination vector size is the same as the container's which means we have a cell for every graph node => O(1) access
+    if(shortestPathsVector.size() == container.size())  {
+        return shortestPathsVector[goalNode];
+    } else {
+        for (const auto &shortestPath: shortestPathsVector) {
+            if (shortestPath.getArrivalNode() == goalNode) {
+                return shortestPath;
+            }
         }
     }
     return  TransitShortestPath{};
-- 
GitLab


From b2cddc187554f8e50313055f579c479e7cbb20ea Mon Sep 17 00:00:00 2001
From: Romain BERNARD <romain.bernard@uca.fr>
Date: Fri, 6 Sep 2024 14:26:25 +0200
Subject: [PATCH 269/327] add shortest transit paths API to graphs (note to
 self : maybe rework this to have an "enhanced graph" wrapper for preprocesses
 etc ?)

---
 src/instance/graph/Graph.cpp | 14 ++++++++++++++
 src/instance/graph/Graph.h   |  4 ++++
 2 files changed, 18 insertions(+)

diff --git a/src/instance/graph/Graph.cpp b/src/instance/graph/Graph.cpp
index 63d01dc..1820bd0 100644
--- a/src/instance/graph/Graph.cpp
+++ b/src/instance/graph/Graph.cpp
@@ -388,3 +388,17 @@ void Graph::linkAllPTNodes() {
         }
     }
 }
+
+const TransitShortestPathContainer &Graph::getTransitShortestPaths() const {
+    return transitShortestPaths;
+}
+
+const std::pair<size_t, std::vector<TransitShortestPath>> &
+Graph::getShortestTransitPathsFrom(size_t startNodeIndex, uint earliestStartInstant) {
+    return transitShortestPaths.getShortestPathsFrom(startNodeIndex, earliestStartInstant);
+}
+
+TransitShortestPath
+Graph::getShortestTransitPathToYFromTime(size_t startNodeIndex, uint earliestStartInstant, size_t goalNode) {
+    return transitShortestPaths.getShortestPathToYFromTime(startNodeIndex, earliestStartInstant, goalNode);
+}
diff --git a/src/instance/graph/Graph.h b/src/instance/graph/Graph.h
index cdf1951..2898418 100644
--- a/src/instance/graph/Graph.h
+++ b/src/instance/graph/Graph.h
@@ -186,6 +186,10 @@ public:
     void computeAndUpdateClosestStations();
     void computeAndUpdateShortestTransitPaths();
 
+    [[nodiscard]] const TransitShortestPathContainer &getTransitShortestPaths() const;
+    const std::pair<size_t, std::vector<TransitShortestPath>>& getShortestTransitPathsFrom(size_t startNodeIndex, uint earliestStartInstant);
+    TransitShortestPath getShortestTransitPathToYFromTime(size_t startNodeIndex, uint earliestStartInstant, size_t goalNode);
+
     void linkAllPTNodes();
 };
 
-- 
GitLab


From 92167bc2fe25d483da660a747c3c634e216e479e Mon Sep 17 00:00:00 2001
From: Romain BERNARD <romain.bernard@uca.fr>
Date: Fri, 6 Sep 2024 17:13:33 +0200
Subject: [PATCH 270/327] functions const-correctness

---
 src/ShortestPath/Transit/TransitShortestPathContainer.cpp | 6 +++---
 src/ShortestPath/Transit/TransitShortestPathContainer.h   | 4 ++--
 src/instance/graph/Graph.cpp                              | 4 ++--
 src/instance/graph/Graph.h                                | 4 ++--
 4 files changed, 9 insertions(+), 9 deletions(-)

diff --git a/src/ShortestPath/Transit/TransitShortestPathContainer.cpp b/src/ShortestPath/Transit/TransitShortestPathContainer.cpp
index 0dc3dbd..058bad5 100644
--- a/src/ShortestPath/Transit/TransitShortestPathContainer.cpp
+++ b/src/ShortestPath/Transit/TransitShortestPathContainer.cpp
@@ -25,8 +25,8 @@ void TransitShortestPathContainer::addShortestPathCollection(size_t startNodeInd
     container[startNodeIndex].emplace_back(startingInstant, shortestPathList);
 }
 
-std::pair<size_t, std::vector<TransitShortestPath>>&
-TransitShortestPathContainer::getShortestPathsFrom(size_t startNodeIndex, uint earliestStartInstant) {
+const std::pair<size_t, std::vector<TransitShortestPath>> &
+TransitShortestPathContainer::getShortestPathsFrom(size_t startNodeIndex, uint earliestStartInstant) const {
     const auto& iterator = std::ranges::lower_bound(container[startNodeIndex],
                                             std::pair<size_t , std::vector<TransitShortestPath>>(earliestStartInstant, {}));
 
@@ -34,7 +34,7 @@ TransitShortestPathContainer::getShortestPathsFrom(size_t startNodeIndex, uint e
 }
 
 TransitShortestPath
-TransitShortestPathContainer::getShortestPathToYFromTime(size_t startNodeIndex, uint earliestStartInstant, size_t goalNode) {
+TransitShortestPathContainer::getShortestPathToYFromTime(size_t startNodeIndex, uint earliestStartInstant, size_t goalNode) const {
     auto [startNode, shortestPathsVector] = getShortestPathsFrom(startNodeIndex, earliestStartInstant);
     //Check if destination vector size is the same as the container's which means we have a cell for every graph node => O(1) access
     if(shortestPathsVector.size() == container.size())  {
diff --git a/src/ShortestPath/Transit/TransitShortestPathContainer.h b/src/ShortestPath/Transit/TransitShortestPathContainer.h
index 90c09da..22730ce 100644
--- a/src/ShortestPath/Transit/TransitShortestPathContainer.h
+++ b/src/ShortestPath/Transit/TransitShortestPathContainer.h
@@ -19,8 +19,8 @@ public:
     explicit TransitShortestPathContainer(size_t size) { container.resize(size); }
     void addShortestPathCollection(size_t startNodeIndex, const std::pair<size_t , std::vector<TransitShortestPath>>& shortestPathList);
     void addShortestPathCollection(size_t startNodeIndex, uint startingInstant, size_t graphSize, const TransitStateContainer& algorithmResultStates);
-    std::pair<size_t, std::vector<TransitShortestPath>>& getShortestPathsFrom(size_t startNodeIndex, uint earliestStartInstant);
-    TransitShortestPath getShortestPathToYFromTime(size_t startNodeIndex, uint earliestStartInstant, size_t goalNode);
+    [[nodiscard]] const std::pair<size_t, std::vector<TransitShortestPath>> & getShortestPathsFrom(size_t startNodeIndex, uint earliestStartInstant) const;
+    [[nodiscard]] TransitShortestPath getShortestPathToYFromTime(size_t startNodeIndex, uint earliestStartInstant, size_t goalNode) const;
 };
 
 
diff --git a/src/instance/graph/Graph.cpp b/src/instance/graph/Graph.cpp
index 1820bd0..87b8c7a 100644
--- a/src/instance/graph/Graph.cpp
+++ b/src/instance/graph/Graph.cpp
@@ -394,11 +394,11 @@ const TransitShortestPathContainer &Graph::getTransitShortestPaths() const {
 }
 
 const std::pair<size_t, std::vector<TransitShortestPath>> &
-Graph::getShortestTransitPathsFrom(size_t startNodeIndex, uint earliestStartInstant) {
+Graph::getShortestTransitPathsFrom(size_t startNodeIndex, uint earliestStartInstant) const {
     return transitShortestPaths.getShortestPathsFrom(startNodeIndex, earliestStartInstant);
 }
 
 TransitShortestPath
-Graph::getShortestTransitPathToYFromTime(size_t startNodeIndex, uint earliestStartInstant, size_t goalNode) {
+Graph::getShortestTransitPathToYFromTime(size_t startNodeIndex, uint earliestStartInstant, size_t goalNode) const {
     return transitShortestPaths.getShortestPathToYFromTime(startNodeIndex, earliestStartInstant, goalNode);
 }
diff --git a/src/instance/graph/Graph.h b/src/instance/graph/Graph.h
index 2898418..fec74d4 100644
--- a/src/instance/graph/Graph.h
+++ b/src/instance/graph/Graph.h
@@ -187,8 +187,8 @@ public:
     void computeAndUpdateShortestTransitPaths();
 
     [[nodiscard]] const TransitShortestPathContainer &getTransitShortestPaths() const;
-    const std::pair<size_t, std::vector<TransitShortestPath>>& getShortestTransitPathsFrom(size_t startNodeIndex, uint earliestStartInstant);
-    TransitShortestPath getShortestTransitPathToYFromTime(size_t startNodeIndex, uint earliestStartInstant, size_t goalNode);
+    const std::pair<size_t, std::vector<TransitShortestPath>>& getShortestTransitPathsFrom(size_t startNodeIndex, uint earliestStartInstant) const;
+    TransitShortestPath getShortestTransitPathToYFromTime(size_t startNodeIndex, uint earliestStartInstant, size_t goalNode) const;
 
     void linkAllPTNodes();
 };
-- 
GitLab


From 6ab0f4e3c320e5643012690311cc997ada73522d Mon Sep 17 00:00:00 2001
From: Romain BERNARD <romain.bernard@uca.fr>
Date: Mon, 9 Sep 2024 19:24:50 +0200
Subject: [PATCH 271/327] make best transit insertion generic for entry/exit
 use cases

---
 .../Heuristics/SimpleModularHeuristic.cpp      | 18 +++++++++++-------
 .../Heuristics/SimpleModularHeuristic.h        |  5 ++++-
 2 files changed, 15 insertions(+), 8 deletions(-)

diff --git a/src/algorithm/Multimodal/Heuristics/SimpleModularHeuristic.cpp b/src/algorithm/Multimodal/Heuristics/SimpleModularHeuristic.cpp
index 113dace..62ce371 100644
--- a/src/algorithm/Multimodal/Heuristics/SimpleModularHeuristic.cpp
+++ b/src/algorithm/Multimodal/Heuristics/SimpleModularHeuristic.cpp
@@ -54,26 +54,30 @@ uint SimpleModularHeuristic::getMaxEntryConstraint(const Request &request, size_
  */
 Request SimpleModularHeuristic::insertBestTransitEntryInRoute(const Request &baseRequest, size_t baseRequestId) {
     std::vector<TransitAccess> entriesAccessList = getBestTransitEntriesList(baseRequest);
-    return insertBestTransitEntryInRoute(baseRequest, entriesAccessList, baseRequestId);
+    return insertBestTransitAccessInRoute(baseRequest, entriesAccessList, baseRequestId, true);
 }
 
 /**
- * Generates a vector of requests from the given entries list before starting the entry subrequest insertion process <br>
+ * Generates a vector of requests from the given access list before starting the entry subrequest insertion process <br>
  * The insertion process first tries best insertions without creating a new vehicles in order of the best entries list.
  * If none result in a valid insertion, we insert the first subrequest (supposedly the better one) in a new vehicle
- * @param baseRequest const ref to the request we use as our base to generate subrequest frm the best entries list
+ * @param baseRequest const ref to the request we use as our base to generate subrequests from the sorted best access list
  * @param entriesAccessList A list of best entries, preferably ordered from best to worst and sized according to the max number of candidates we want to try inserting
  * @param baseRequestId ID/index in the request vector for our base request
  * @return The subrequest successfully inserted in our route. This method's caller needs to add this request to its main request vector
  */
-Request SimpleModularHeuristic::insertBestTransitEntryInRoute(const Request &baseRequest, const std::vector<TransitAccess>& entriesAccessList, size_t baseRequestId) {
+const Request &
+SimpleModularHeuristic::insertBestTransitAccessInRoute(const Request &baseRequest,
+                                                       const std::vector<TransitAccess> &entriesAccessList,
+                                                       size_t baseRequestId, bool isEntry) {
     std::vector<Request> entrySubRequestsList;
-    entrySubRequestsList.reserve(Constants::MAX_TRANSIT_ENTRY_CANDIDATES); //Init entry subrequests list to the appropriate size
+    size_t maxSize = isEntry ? Constants::MAX_TRANSIT_ENTRY_CANDIDATES : Constants::MAX_TRANSIT_EXIT_CANDIDATES;
+    entrySubRequestsList.reserve(maxSize); //Init entry subrequests list to the appropriate size
     //Generate subrequests from best transit entries
     for(auto const& access : entriesAccessList) {
-        entrySubRequestsList.emplace_back(*_graph, baseRequest, access, true);
+        entrySubRequestsList.emplace_back(*_graph, baseRequest, access, isEntry);
     }
-    return insertBestTransitAccessInRoute(entrySubRequestsList, baseRequestId, true);
+    return insertBestTransitAccessInRoute(entrySubRequestsList, baseRequestId, isEntry);
 }
 
 /**
diff --git a/src/algorithm/Multimodal/Heuristics/SimpleModularHeuristic.h b/src/algorithm/Multimodal/Heuristics/SimpleModularHeuristic.h
index 7ec22da..861861a 100644
--- a/src/algorithm/Multimodal/Heuristics/SimpleModularHeuristic.h
+++ b/src/algorithm/Multimodal/Heuristics/SimpleModularHeuristic.h
@@ -47,7 +47,9 @@ public:
 private:
 
     Request insertBestTransitEntryInRoute(const Request &baseRequest, size_t baseRequestId);
-    Request insertBestTransitEntryInRoute(const Request &baseRequest, const std::vector<TransitAccess>& entriesAccessList, size_t baseRequestId);
+
+    const Request &insertBestTransitAccessInRoute(const Request &baseRequest, const std::vector<TransitAccess> &entriesAccessList,
+                                   size_t baseRequestId, bool isEntry);
     const Request &insertBestTransitAccessInRoute(const std::vector<Request> &accessSubRequestsList,
                                                   size_t baseRequestId, bool isEntry);
 
@@ -117,6 +119,7 @@ protected:
      */ //TODO: try other scoring functions (current other idea : T(exitNode, destinationNode) * exitTime; alpha*T(exitNode, destinationNode) + exitTime)
     [[nodiscard]] double getTransitExitScore(const Request& baseRequest, const TransitAccess& exitData);
 
+    //Keep those getters/setters protected as no other member should access or modify these objects
     [[nodiscard]] const Graph *getGraph() const;
     void setGraph(const Graph *graph);
 
-- 
GitLab


From 18246c04460b7f31d14edf74c4ae02ee49868f19 Mon Sep 17 00:00:00 2001
From: Romain BERNARD <romain.bernard@uca.fr>
Date: Mon, 9 Sep 2024 19:25:44 +0200
Subject: [PATCH 272/327] implement best transit exits generation and insertion

---
 .../Heuristics/SimpleModularHeuristic.cpp     | 57 +++++++++++++++++--
 .../Heuristics/SimpleModularHeuristic.h       | 51 ++++++++++++++---
 2 files changed, 95 insertions(+), 13 deletions(-)

diff --git a/src/algorithm/Multimodal/Heuristics/SimpleModularHeuristic.cpp b/src/algorithm/Multimodal/Heuristics/SimpleModularHeuristic.cpp
index 62ce371..3a74f6d 100644
--- a/src/algorithm/Multimodal/Heuristics/SimpleModularHeuristic.cpp
+++ b/src/algorithm/Multimodal/Heuristics/SimpleModularHeuristic.cpp
@@ -4,6 +4,8 @@
 
 #include "SimpleModularHeuristic.h"
 
+using transit_order_function = std::function<bool(SimpleModularHeuristic::ScoredTransitAccess, SimpleModularHeuristic::ScoredTransitAccess)>;
+
 std::vector<TransitAccess> SimpleModularHeuristic::getBestTransitEntriesList(const Request &baseRequest) const {
     const auto& bestStationsIndexVector = _graph->getNode(
             baseRequest.getOriginNodeIndex()).getBestStationsNodeIdxVector();
@@ -81,12 +83,13 @@ SimpleModularHeuristic::insertBestTransitAccessInRoute(const Request &baseReques
 }
 
 /**
- * The insertion process first tries best insertions without creating a new vehicles in order of the best entries list.
- * If none result in a valid insertion, we insert the first subrequest (supposedly the better one) in a new vehicle
+ * The insertion process first tries best insertions without creating a new vehicles in order of the best entries list. <br>
+ * If none result in a valid insertion, we insert the first subrequest (supposedly the better one) in a new vehicle. <br>
+ * While doing these insertions, the route and global request vector is updated with the appropriate request so that no inconsistencies in data structures happen
  * @param accessSubRequestsList A list of entry subrequest candidates, preferably ordered from best to worst candidate, but the list order is implementation dependant
  * @param baseRequestId ID/index in the request vector for our base request
  * @param isEntry true iff the given access requests are transit entry requests
- * @return The subrequest successfully inserted in our route. This method's caller needs to add this request to its main request vector
+ * @return The subrequest successfully inserted in our route
  */
 const Request &
 SimpleModularHeuristic::insertBestTransitAccessInRoute(const std::vector<Request> &accessSubRequestsList,
@@ -151,9 +154,17 @@ const Request& SimpleModularHeuristic::getSubrequest(size_t requestId, bool isEn
     return (*_requestsVect)[getSubrequestIndex(requestId, isEntry)];
 }
 
-double SimpleModularHeuristic::getTransitExitScore(const Request &baseRequest, const TransitAccess &exitData) {
-    return _graph->getShortestSAEVPath(exitData.getAccessNodeIdx(), baseRequest.getDestinationNodeIndex())
-           + exitData.getAccessTimestamp();
+double SimpleModularHeuristic::getTransitExitScore(const Request &baseRequest, const TransitAccess &exitData) const {
+    return getTransitExitScore(exitData.getAccessNodeIdx(), baseRequest.getDestinationNodeIndex(), exitData.getAccessTimestamp());
+}
+
+double SimpleModularHeuristic::getTransitExitScore(size_t transitExitNodeIndex, size_t requestDestinationNodeIndex, uint transitExitTimestamp) const {
+    return _graph->getShortestSAEVPath(transitExitNodeIndex, requestDestinationNodeIndex) + transitExitTimestamp;
+}
+
+transit_order_function
+SimpleModularHeuristic::getScoredTransitExitOrderer() {
+    return [](SimpleModularHeuristic::ScoredTransitAccess lhs, SimpleModularHeuristic::ScoredTransitAccess rhs) { return lhs.score < rhs.score; };
 }
 
 uint SimpleModularHeuristic::getMinExitConstraint(size_t baseRequestId, const TransitAccess &exitData) {
@@ -164,3 +175,37 @@ uint SimpleModularHeuristic::getMaxExitConstraint(size_t baseRequestId, const Tr
     const Request& baseRequest = (*_requestsVect)[baseRequestId];
     return baseRequest.getMaxArrivalTw() - _graph->getShortestSAEVPath(exitData.getAccessNodeIdx(), baseRequest.getDestinationNodeIndex());
 }
+
+std::vector<TransitAccess>
+SimpleModularHeuristic::getBestTransitExitsList(size_t baseRequestId) {
+    const Request& baseRequest = (*_requestsVect)[baseRequestId];
+    const SAEVKeyPoint& entrySubRequestOriginKP = _route->getEntrySubRequestOrigin(baseRequestId);
+    return getBestTransitExitsList(baseRequest, entrySubRequestOriginKP);
+}
+
+std::vector<TransitAccess>
+SimpleModularHeuristic::getBestTransitExitsList(const Request &baseRequest, const SAEVKeyPoint &entrySubRequestOriginKP) const {
+    std::vector<SimpleModularHeuristic::ScoredTransitAccess> scoreTransitExits;
+    //Get departure time/shortest transit paths list from the entry sub request's max time (this means we take the first transit available after max arrival)
+    //TODO : study other approaches (e.g check for a faster max arrival if it's valid and allows better paths. This would require propagation => costly)
+    const auto& [departureTime, shortestTransitPaths] = _graph->getShortestTransitPathsFrom(entrySubRequestOriginKP.getCounterpart()->getNodeIndex(),
+                                                                   entrySubRequestOriginKP.getCounterpart()->getMaxTw());
+
+    //Iterate over the best stations saved prior
+    for(const auto& shortestTransitPath : shortestTransitPaths) {
+        if(shortestTransitPath.getArrivalTime() >= 0) {
+            TransitAccess exit{shortestTransitPath.getArrivalNode(),  (uint) shortestTransitPath.getArrivalTime()};
+            scoreTransitExits.emplace_back(exit, getTransitExitScore(baseRequest, exit));
+        }
+    }
+
+    //Sort and truncate transit exits list while removing score data that's unnecessary in later steps
+    std::ranges::sort(scoreTransitExits, getScoredTransitExitOrderer());
+    std::vector<TransitAccess> truncatedTransitExitsList{scoreTransitExits.begin(), scoreTransitExits.begin() + Constants::MAX_TRANSIT_EXIT_CANDIDATES};
+    return truncatedTransitExitsList;
+}
+
+Request SimpleModularHeuristic::insertBestTransitExitsInRoute(const Request &baseRequest, size_t baseRequestId) {
+    std::vector<TransitAccess> exitAccessList = getBestTransitExitsList(baseRequestId);
+    return insertBestTransitAccessInRoute(baseRequest, exitAccessList, baseRequestId, false);
+}
diff --git a/src/algorithm/Multimodal/Heuristics/SimpleModularHeuristic.h b/src/algorithm/Multimodal/Heuristics/SimpleModularHeuristic.h
index 861861a..2f44eb0 100644
--- a/src/algorithm/Multimodal/Heuristics/SimpleModularHeuristic.h
+++ b/src/algorithm/Multimodal/Heuristics/SimpleModularHeuristic.h
@@ -8,6 +8,7 @@
 
 #include <cstddef>
 #include <vector>
+#include <float.h>
 #include "../../../instance/requests/Request.h"
 #include "../../../routes/vehicle/SAEVRoute.h"
 #include "TransitAccess.h"
@@ -22,6 +23,11 @@
 #endif
 
 class SimpleModularHeuristic {
+public:
+    struct ScoredTransitAccess : public TransitAccess {
+        double score{DBL_MAX};
+        explicit ScoredTransitAccess(const TransitAccess& access, double scr) : TransitAccess(access), score(scr) {}
+    };
 private:
     const Graph* _graph{nullptr};
     SAEVRoute* _route{nullptr};
@@ -32,6 +38,9 @@ private:
     FRIEND_TEST(MultimodalInsertionHeuristicDebug, DebugBaseInstance);
     FRIEND_TEST(MultimodalInsertionHeuristicDebug, DebugInstanceAlain);
 
+
+    using transit_order_function = std::function<bool(ScoredTransitAccess, ScoredTransitAccess)>;
+
 //Public interface to interact with the modular heuristic
 public:
     SimpleModularHeuristic(const Graph *graph, SAEVRoute *route, std::vector<Request>* requestsVect) : _graph(graph), _route(route),
@@ -47,14 +56,14 @@ public:
 private:
 
     Request insertBestTransitEntryInRoute(const Request &baseRequest, size_t baseRequestId);
+    Request insertBestTransitExitsInRoute(const Request &baseRequest, size_t baseRequestId);
+
 
     const Request &insertBestTransitAccessInRoute(const Request &baseRequest, const std::vector<TransitAccess> &entriesAccessList,
                                    size_t baseRequestId, bool isEntry);
     const Request &insertBestTransitAccessInRoute(const std::vector<Request> &accessSubRequestsList,
                                                   size_t baseRequestId, bool isEntry);
 
-    void insertBestTransitExitsInRoute(const std::vector<Request>& baseRequestsList, const std::vector<TransitAccess>& transitEntriesList);
-
     //Best candidates function
     /**
      * Creates and returns a vector of TransitAccess objects representing possible
@@ -77,15 +86,31 @@ private:
      * in a vehicle. <br>
      * <br>
      * This vector is sorted according to the sort function the class was initialized with
-     * (default = t' + T(y,Dr)) and has max size Constants::MAX_TRANSIT_EXIT_CANDIDATES.
+     * (default = t' + T(y,Dr)). It does not guarantee a max size of Constants::MAX_TRANSIT_EXIT_CANDIDATES.
      * There can be less, or even 0 elements if no candidate has a transit departure tmax in
      * getMinEntryConstraint <= tmax <= getMaxEntryConstraint
      *
-     * @param transitEntryRequest the transit entry sub-request we wish to find potential exits from
+     * @param baseRequestId id of the base request for which we look for best exits
      * @return A vector consisting of all valid TransitAccess objects wrt the entry request's state
      * and the min/max entry constraints. If no valid access is found, we return an empty vector.
      */
-     std::vector<TransitAccess> getBestTransitExitsList(Request transitEntryRequest);
+    std::vector<TransitAccess> getBestTransitExitsList(size_t baseRequestId);
+    /**
+    * Creates and returns a vector of TransitAccess objects representing possible
+    * transit entries that can be converted to Request objects to try and insert them
+    * in a vehicle. <br>
+    * <br>
+    * This vector is sorted according to the sort function the class was initialized with
+    * (default = t' + T(y,Dr)). It does not guarantee a max size of Constants::MAX_TRANSIT_EXIT_CANDIDATES.
+    * There can be less, or even 0 elements if no candidate has a transit departure tmax in
+    * getMinEntryConstraint <= tmax <= getMaxEntryConstraint
+    *
+    * @param baseRequestId id of the base request for which we look for best exits
+    * @return A vector consisting of all valid TransitAccess objects wrt the entry request's state
+    * and the min/max entry constraints. If no valid access is found, we return an empty vector.
+    */
+    [[nodiscard]] std::vector<TransitAccess>
+    getBestTransitExitsList(const Request &baseRequest, const SAEVKeyPoint &entrySubRequestOriginKP) const;
 
 //Protected member function for overriding as we make this more modular
 protected:
@@ -112,12 +137,21 @@ protected:
     /**
      * Base implementation of a sorting score (lower is better) for exit candidates.
      * This implementation scores via T(exitNode, destinationNode) + exitTime to try and
-     * incentivize early and/or close access points
+     * incentivize early and/or close access points. <br> <br>
+     * Override this function to alter exit candidates ordering via the score function <br>
+     * /!\ Be mindful that vectors are sorted in ascending order, so invert the score or override getScoredTransitExitOrderer if you want greater values first /!\
      * @param baseRequest the base request, required to get the destination
      * @param exitData exit data containing the exit point and timestamp
      * @return A score allowing to sort transit exits in ascending score order
      */ //TODO: try other scoring functions (current other idea : T(exitNode, destinationNode) * exitTime; alpha*T(exitNode, destinationNode) + exitTime)
-    [[nodiscard]] double getTransitExitScore(const Request& baseRequest, const TransitAccess& exitData);
+    [[nodiscard]] double getTransitExitScore(const Request& baseRequest, const TransitAccess& exitData) const;
+    /**
+     * This function returns an orderer function used to sort the transit exit priority queue. <br> <br>
+     * Only override this function if you need a more involved kind of sort function that can't be made by simply overriding getTransitExitScore. <br>
+     * /!\ Be mindful that vectors are sorted in ascending order, so invert the order if you want greater values first /!\
+     * @return Returns a function taking in argument two ScoredTransitAccess objects and returning a true if lhs is to be ordered before rhs, false otherwise
+     */
+    [[nodiscard]] static transit_order_function getScoredTransitExitOrderer() ;
 
     //Keep those getters/setters protected as no other member should access or modify these objects
     [[nodiscard]] const Graph *getGraph() const;
@@ -131,6 +165,9 @@ protected:
     [[nodiscard]] size_t getSubrequestIndex(size_t requestId, bool isEntry) const;
 
     const Request &getSubrequest(size_t requestId, bool isEntry);
+
+    [[nodiscard]] double getTransitExitScore(size_t transitExitNodeIndex, size_t requestDestinationNodeIndex,
+                               uint transitExitTimestamp) const;
 };
 
 
-- 
GitLab


From d8804306849745ca3765c0747368e1d96af12a5f Mon Sep 17 00:00:00 2001
From: Romain BERNARD <romain.bernard@uca.fr>
Date: Tue, 10 Sep 2024 10:58:11 +0200
Subject: [PATCH 273/327] fix cases with size lower than
 max_transit_exit_candidate

---
 .../Multimodal/Heuristics/SimpleModularHeuristic.cpp  | 11 ++++++-----
 1 file changed, 6 insertions(+), 5 deletions(-)

diff --git a/src/algorithm/Multimodal/Heuristics/SimpleModularHeuristic.cpp b/src/algorithm/Multimodal/Heuristics/SimpleModularHeuristic.cpp
index 3a74f6d..72ecc9c 100644
--- a/src/algorithm/Multimodal/Heuristics/SimpleModularHeuristic.cpp
+++ b/src/algorithm/Multimodal/Heuristics/SimpleModularHeuristic.cpp
@@ -185,8 +185,8 @@ SimpleModularHeuristic::getBestTransitExitsList(size_t baseRequestId) {
 
 std::vector<TransitAccess>
 SimpleModularHeuristic::getBestTransitExitsList(const Request &baseRequest, const SAEVKeyPoint &entrySubRequestOriginKP) const {
-    std::vector<SimpleModularHeuristic::ScoredTransitAccess> scoreTransitExits;
-    //Get departure time/shortest transit paths list from the entry sub request's max time (this means we take the first transit available after max arrival)
+    std::vector<SimpleModularHeuristic::ScoredTransitAccess> scoredTransitExits;
+    //Get departure time/shortest transit paths list from the entry sub request's max time (this means we take the first transit available after current max arrival)
     //TODO : study other approaches (e.g check for a faster max arrival if it's valid and allows better paths. This would require propagation => costly)
     const auto& [departureTime, shortestTransitPaths] = _graph->getShortestTransitPathsFrom(entrySubRequestOriginKP.getCounterpart()->getNodeIndex(),
                                                                    entrySubRequestOriginKP.getCounterpart()->getMaxTw());
@@ -195,13 +195,14 @@ SimpleModularHeuristic::getBestTransitExitsList(const Request &baseRequest, cons
     for(const auto& shortestTransitPath : shortestTransitPaths) {
         if(shortestTransitPath.getArrivalTime() >= 0) {
             TransitAccess exit{shortestTransitPath.getArrivalNode(),  (uint) shortestTransitPath.getArrivalTime()};
-            scoreTransitExits.emplace_back(exit, getTransitExitScore(baseRequest, exit));
+            scoredTransitExits.emplace_back(exit, getTransitExitScore(baseRequest, exit));
         }
     }
 
     //Sort and truncate transit exits list while removing score data that's unnecessary in later steps
-    std::ranges::sort(scoreTransitExits, getScoredTransitExitOrderer());
-    std::vector<TransitAccess> truncatedTransitExitsList{scoreTransitExits.begin(), scoreTransitExits.begin() + Constants::MAX_TRANSIT_EXIT_CANDIDATES};
+    std::ranges::sort(scoredTransitExits, getScoredTransitExitOrderer());
+    uint finalVectorSize = std::min(scoredTransitExits.size(), Constants::MAX_TRANSIT_EXIT_CANDIDATES);
+    std::vector<TransitAccess> truncatedTransitExitsList{scoredTransitExits.begin(), scoredTransitExits.begin() + finalVectorSize};
     return truncatedTransitExitsList;
 }
 
-- 
GitLab


From 54863583f86bdee23a2c74b1e5b0b20fec7356b1 Mon Sep 17 00:00:00 2001
From: Romain BERNARD <romain.bernard@uca.fr>
Date: Tue, 10 Sep 2024 10:59:44 +0200
Subject: [PATCH 274/327] only set _arrivalTime if there's a valid path,
 otherwise keep default -1 value

---
 src/ShortestPath/Transit/TransitShortestPath.h | 6 ++++--
 1 file changed, 4 insertions(+), 2 deletions(-)

diff --git a/src/ShortestPath/Transit/TransitShortestPath.h b/src/ShortestPath/Transit/TransitShortestPath.h
index cf22868..7aa5d13 100644
--- a/src/ShortestPath/Transit/TransitShortestPath.h
+++ b/src/ShortestPath/Transit/TransitShortestPath.h
@@ -15,9 +15,11 @@ private:
 public:
     TransitShortestPath() = default;
 
-    explicit TransitShortestPath(const TransitAlgorithmState& state) : _arrivalTime(state.getInstant()) {
-        if(state.getNbConnections() > 0)
+    explicit TransitShortestPath(const TransitAlgorithmState& state) {
+        if(state.getNbConnections() > 0) {
             _keyPoints = state.getConnections();
+            _arrivalTime = state.getInstant();
+        }
     }
 
     /**
-- 
GitLab


From 50321c58e7fe6245dd9a121811e3da6804f27b3b Mon Sep 17 00:00:00 2001
From: Romain BERNARD <romain.bernard@uca.fr>
Date: Tue, 10 Sep 2024 16:01:39 +0200
Subject: [PATCH 275/327] remove some currently useless members of the Request
 class

---
 src/instance/requests/Request.cpp | 29 ++---------------------------
 src/instance/requests/Request.h   | 21 ---------------------
 2 files changed, 2 insertions(+), 48 deletions(-)

diff --git a/src/instance/requests/Request.cpp b/src/instance/requests/Request.cpp
index a693fab..4919fb0 100644
--- a/src/instance/requests/Request.cpp
+++ b/src/instance/requests/Request.cpp
@@ -9,14 +9,14 @@
 Request::Request(const size_t departureNodeIndex, const size_t arrivalNodeIndex, const TimeWindow &arrivalTw,
                  const uint deltaTime, const uint weight) : _originNodeIndex(departureNodeIndex),
                                                             _destinationNodeIndex(arrivalNodeIndex), _arrivalTW(arrivalTw),
-                                                            _deltaTime(deltaTime), _weight(weight), _currentDeltaTime(deltaTime) {
+                                                            _deltaTime(deltaTime), _weight(weight) {
     _departureTW = _arrivalTW - deltaTime;
 }
 
 Request::Request(const size_t departureNodeIndex, const size_t arrivalNodeIndex, const TimeWindow &arrivalTw,
                  const uint deltaTime, const uint weight, const Graph& graph) :
         _originNodeIndex(departureNodeIndex), _destinationNodeIndex(arrivalNodeIndex),
-        _arrivalTW(arrivalTw), _deltaTime(deltaTime), _weight(weight), _currentDeltaTime(deltaTime) {
+        _arrivalTW(arrivalTw), _deltaTime(deltaTime), _weight(weight) {
     _departureTW.min = _arrivalTW.min - deltaTime;
     _departureTW.max = _arrivalTW.max - graph.getShortestSAEVPath(departureNodeIndex, arrivalNodeIndex);
 }
@@ -115,18 +115,6 @@ uint Request::getWeight() const {
     return _weight;
 }
 
-uint Request::getCurrentDeltaTime() const {
-    return _currentDeltaTime;
-}
-
-uint Request::getRequestServiceStart() const {
-    return _requestServiceStart;
-}
-
-uint Request::getRequestServiceEnd() const {
-    return _requestServiceEnd;
-}
-
 const RequestRoute &Request::getCurrentRoute() const {
     return _currentRoute;
 }
@@ -156,19 +144,6 @@ uint Request::getMaxArrivalTw() const {
 //-----------------------------
 //---------- Setters ----------
 //-----------------------------
-
-void Request::setCurrentDeltaTime(int currentDeltaTime) {
-    _currentDeltaTime = currentDeltaTime;
-}
-
-void Request::setRequestServiceStart(int requestServiceStart) {
-    _requestServiceStart = requestServiceStart;
-}
-
-void Request::setRequestServiceEnd(int requestServiceEnd) {
-    _requestServiceEnd = requestServiceEnd;
-}
-
 void Request::setCurrentRoute(const RequestRoute &currentRoute) {
     _currentRoute = currentRoute;
 }
diff --git a/src/instance/requests/Request.h b/src/instance/requests/Request.h
index 8e4f08d..51ef41e 100644
--- a/src/instance/requests/Request.h
+++ b/src/instance/requests/Request.h
@@ -23,15 +23,6 @@ private:
     uint _weight; //How much space the requests takes in the vehicle (defaults to 1)
 
     //Request helpful members (used for constraint propagation and remember the current state of the _request)
-    uint _currentDeltaTime; //deltaTime - currentRouteDuration
-    /**
-     * Store the timestamp when this request effectively starts its route here once we planified its route in detail
-     */
-    uint _requestServiceStart;
-    /**
-     * Store the timestamp when this request effectively ends its route here once we planified its route in detail
-     */
-    uint _requestServiceEnd;
     /**
      * This object divides our request's route in four key points for each step in the user's path:<br>
      * SAEV departure -> Transit entrance -> Transit exit -> SAEV end <br>
@@ -60,9 +51,6 @@ public:
     [[nodiscard]] const TimeWindow &getArrivalTw() const;
     [[nodiscard]] uint getDeltaTime() const;
     [[nodiscard]] uint getWeight() const;
-    [[nodiscard]] uint getCurrentDeltaTime() const;
-    [[nodiscard]] uint getRequestServiceStart() const;
-    [[nodiscard]] uint getRequestServiceEnd() const;
     [[nodiscard]] const RequestRoute &getCurrentRoute() const;
     [[nodiscard]] const TimeWindow &getDepartureTw() const;
     [[nodiscard]] uint getMinDepartureTw() const;
@@ -71,9 +59,6 @@ public:
     [[nodiscard]] uint getMaxArrivalTw() const;
 
     //Setters
-    void setCurrentDeltaTime(int currentDeltaTime);
-    void setRequestServiceStart(int requestServiceStart);
-    void setRequestServiceEnd(int requestServiceEnd);
     void setCurrentRoute(const RequestRoute &currentRoute);
     void setDepartureTw(const TimeWindow &departureTw);
 
@@ -81,12 +66,6 @@ public:
     [[nodiscard]] int getNodeIndex(int routeIndex) const;
     void setNodeIndex(int routeIndex, int nodeIndex);
 
-    [[nodiscard]] int getArrivalInstant(int routeIndex) const;
-    void setArrivalInstant(int routeIndex, int arrivalInstant);
-
-    [[nodiscard]] int getDepartureInstant(int routeIndex) const;
-    void setDepartureInstant(int routeIndex, int departureInstant);
-
     [[nodiscard]] const SAEVehicle *getSAEV(int routeIndex) const;
     void setSAEV(int routeIndex, SAEVehicle *saev);
 
-- 
GitLab


From 90612e560d959936ac5403da42fae54c8f4cd10e Mon Sep 17 00:00:00 2001
From: Romain BERNARD <romain.bernard@uca.fr>
Date: Tue, 10 Sep 2024 16:03:28 +0200
Subject: [PATCH 276/327] Add error handling to (sub)Request generation

---
 src/TimeWindow.h                  | 2 ++
 src/instance/requests/Request.cpp | 8 ++++++++
 2 files changed, 10 insertions(+)

diff --git a/src/TimeWindow.h b/src/TimeWindow.h
index 76dff6c..277b962 100644
--- a/src/TimeWindow.h
+++ b/src/TimeWindow.h
@@ -39,6 +39,8 @@ struct TimeWindow {
     TimeWindow operator-(const TimeWindow& rhs) const;
     TimeWindow& operator-=(const TimeWindow& rhs);
     TimeWindow& operator=(const TimeWindow& rhs) = default;
+
+    struct invalid_time_window_exception : std::exception {};
 };
 
 
diff --git a/src/instance/requests/Request.cpp b/src/instance/requests/Request.cpp
index 4919fb0..6b1bcf6 100644
--- a/src/instance/requests/Request.cpp
+++ b/src/instance/requests/Request.cpp
@@ -11,6 +11,9 @@ Request::Request(const size_t departureNodeIndex, const size_t arrivalNodeIndex,
                                                             _destinationNodeIndex(arrivalNodeIndex), _arrivalTW(arrivalTw),
                                                             _deltaTime(deltaTime), _weight(weight) {
     _departureTW = _arrivalTW - deltaTime;
+
+    if(_departureTW.min > _departureTW.max || _arrivalTW.min > _arrivalTW.max)
+        throw TimeWindow::invalid_time_window_exception();
 }
 
 Request::Request(const size_t departureNodeIndex, const size_t arrivalNodeIndex, const TimeWindow &arrivalTw,
@@ -19,6 +22,9 @@ Request::Request(const size_t departureNodeIndex, const size_t arrivalNodeIndex,
         _arrivalTW(arrivalTw), _deltaTime(deltaTime), _weight(weight) {
     _departureTW.min = _arrivalTW.min - deltaTime;
     _departureTW.max = _arrivalTW.max - graph.getShortestSAEVPath(departureNodeIndex, arrivalNodeIndex);
+
+    if(_departureTW.min > _departureTW.max || _arrivalTW.min > _arrivalTW.max)
+        throw TimeWindow::invalid_time_window_exception();
 }
 
 Request::Request(const DATRow& currentRow, const Graph& graph) {
@@ -63,6 +69,8 @@ Request::Request(const DATRow& currentRow, const Graph& graph) {
         _arrivalTW.min = _departureTW.min + graph.getShortestSAEVPath(_originNodeIndex, _destinationNodeIndex);
         _arrivalTW.max = _departureTW.max + _deltaTime;
     }
+    if(_departureTW.min > _departureTW.max || _arrivalTW.min > _arrivalTW.max)
+        throw TimeWindow::invalid_time_window_exception();
 }
 
 Request::Request(const DATRow& currentRow, double deltaRatio, const Graph& graph) : Request(currentRow, graph){
-- 
GitLab


From 7e9632690af50ca9b488c37e957a4f43570c61d2 Mon Sep 17 00:00:00 2001
From: Romain BERNARD <romain.bernard@uca.fr>
Date: Tue, 10 Sep 2024 16:05:28 +0200
Subject: [PATCH 277/327] Split entry/exit subrequest construction to
 accurately set the time window of exit requests

---
 .../Heuristics/SimpleModularHeuristic.cpp     | 23 ++++++----
 .../Heuristics/SimpleModularHeuristic.h       |  2 +-
 src/instance/requests/Request.cpp             | 42 ++++++++++++-------
 src/instance/requests/Request.h               | 21 +++++++++-
 4 files changed, 64 insertions(+), 24 deletions(-)

diff --git a/src/algorithm/Multimodal/Heuristics/SimpleModularHeuristic.cpp b/src/algorithm/Multimodal/Heuristics/SimpleModularHeuristic.cpp
index 72ecc9c..f9043b6 100644
--- a/src/algorithm/Multimodal/Heuristics/SimpleModularHeuristic.cpp
+++ b/src/algorithm/Multimodal/Heuristics/SimpleModularHeuristic.cpp
@@ -64,22 +64,31 @@ Request SimpleModularHeuristic::insertBestTransitEntryInRoute(const Request &bas
  * The insertion process first tries best insertions without creating a new vehicles in order of the best entries list.
  * If none result in a valid insertion, we insert the first subrequest (supposedly the better one) in a new vehicle
  * @param baseRequest const ref to the request we use as our base to generate subrequests from the sorted best access list
- * @param entriesAccessList A list of best entries, preferably ordered from best to worst and sized according to the max number of candidates we want to try inserting
+ * @param transitAccessList A list of best entries, preferably ordered from best to worst and sized according to the max number of candidates we want to try inserting
  * @param baseRequestId ID/index in the request vector for our base request
  * @return The subrequest successfully inserted in our route. This method's caller needs to add this request to its main request vector
  */
 const Request &
 SimpleModularHeuristic::insertBestTransitAccessInRoute(const Request &baseRequest,
-                                                       const std::vector<TransitAccess> &entriesAccessList,
+                                                       const std::vector<TransitAccess> &transitAccessList,
                                                        size_t baseRequestId, bool isEntry) {
-    std::vector<Request> entrySubRequestsList;
+    std::vector<Request> accessSubRequestsList;
     size_t maxSize = isEntry ? Constants::MAX_TRANSIT_ENTRY_CANDIDATES : Constants::MAX_TRANSIT_EXIT_CANDIDATES;
-    entrySubRequestsList.reserve(maxSize); //Init entry subrequests list to the appropriate size
+    accessSubRequestsList.reserve(maxSize); //Init entry subrequests list to the appropriate size
     //Generate subrequests from best transit entries
-    for(auto const& access : entriesAccessList) {
-        entrySubRequestsList.emplace_back(*_graph, baseRequest, access, isEntry);
+    for(auto const& access : transitAccessList) {
+        try {
+            if(isEntry)
+                accessSubRequestsList.emplace_back(*_graph, baseRequest, access);
+            else
+                accessSubRequestsList.emplace_back(*_graph, baseRequest, access,
+                                                   _route->getEntrySubRequestOrigin(baseRequestId));
+        }
+        catch(const TimeWindow::invalid_time_window_exception& e) {
+            DEBUG_MSG("Invalid Time Window during candidate sub request creation, it won't be added to the list");
+        }
     }
-    return insertBestTransitAccessInRoute(entrySubRequestsList, baseRequestId, isEntry);
+    return insertBestTransitAccessInRoute(accessSubRequestsList, baseRequestId, isEntry);
 }
 
 /**
diff --git a/src/algorithm/Multimodal/Heuristics/SimpleModularHeuristic.h b/src/algorithm/Multimodal/Heuristics/SimpleModularHeuristic.h
index 2f44eb0..16fc5ec 100644
--- a/src/algorithm/Multimodal/Heuristics/SimpleModularHeuristic.h
+++ b/src/algorithm/Multimodal/Heuristics/SimpleModularHeuristic.h
@@ -59,7 +59,7 @@ private:
     Request insertBestTransitExitsInRoute(const Request &baseRequest, size_t baseRequestId);
 
 
-    const Request &insertBestTransitAccessInRoute(const Request &baseRequest, const std::vector<TransitAccess> &entriesAccessList,
+    const Request &insertBestTransitAccessInRoute(const Request &baseRequest, const std::vector<TransitAccess> &transitAccessList,
                                    size_t baseRequestId, bool isEntry);
     const Request &insertBestTransitAccessInRoute(const std::vector<Request> &accessSubRequestsList,
                                                   size_t baseRequestId, bool isEntry);
diff --git a/src/instance/requests/Request.cpp b/src/instance/requests/Request.cpp
index 6b1bcf6..9cec884 100644
--- a/src/instance/requests/Request.cpp
+++ b/src/instance/requests/Request.cpp
@@ -206,25 +206,37 @@ std::string Request::to_string_export() const {
     return res;
 }
 
-Request::Request(const Graph& graph, const Request &baseRequest, const TransitAccess &access, bool isEntry) {
-    if(isEntry) {
-        _originNodeIndex = baseRequest.getOriginNodeIndex();
-        _destinationNodeIndex = access.getAccessNodeIdx();
+Request::Request(const Graph &graph, const Request &baseRequest, const TransitAccess &transitEntry) {
+    _originNodeIndex = baseRequest.getOriginNodeIndex();
+    _destinationNodeIndex = transitEntry.getAccessNodeIdx();
 
-        _departureTW = baseRequest.getDepartureTw();
+    _departureTW = baseRequest.getDepartureTw();
 
-        _arrivalTW.min = baseRequest.getDepartureTw().min + graph.getShortestSAEVPath(_originNodeIndex, access.getAccessNodeIdx());
-        _arrivalTW.max = access.getAccessTimestamp();
-    } else {
-        _originNodeIndex = access.getAccessNodeIdx();
-        _destinationNodeIndex = baseRequest.getDestinationNodeIndex();
+    _arrivalTW.min = baseRequest.getDepartureTw().min + graph.getShortestSAEVPath(_originNodeIndex, transitEntry.getAccessNodeIdx());
+    _arrivalTW.max = transitEntry.getAccessTimestamp();
 
-        _departureTW.min = access.getAccessTimestamp();
-        _departureTW.max = baseRequest.getArrivalTw().max - graph.getShortestSAEVPath(access.getAccessNodeIdx(), _destinationNodeIndex);
+    if(_departureTW.min > _departureTW.max || _arrivalTW.min > _arrivalTW.max)
+        throw TimeWindow::invalid_time_window_exception();
+
+    _transitTravelTimeRatio = baseRequest.getTransitTravelTimeRatio();
+    _deltaTime = UINT16_MAX;
+    _weight = baseRequest.getWeight();
+}
+
+Request::Request(const Graph &graph, const Request &baseRequest, const TransitAccess &transitExit,
+                 const SAEVKeyPoint &originSubRequestKeyPoint) {
+    _originNodeIndex = transitExit.getAccessNodeIdx();
+    _destinationNodeIndex = baseRequest.getDestinationNodeIndex();
+
+    _departureTW.min = transitExit.getAccessTimestamp();
+    _departureTW.max = baseRequest.getArrivalTw().max - graph.getShortestSAEVPath(transitExit.getAccessNodeIdx(), _destinationNodeIndex);
+
+    _arrivalTW.min = baseRequest.getArrivalTw().min;
+    _arrivalTW.max = originSubRequestKeyPoint.getMinTw() + baseRequest.getDeltaTime(); //Reduce max arrival TW to a value we are 100% sure is compatible with our current min departure time
+
+    if(_departureTW.min > _departureTW.max || _arrivalTW.min > _arrivalTW.max)
+        throw TimeWindow::invalid_time_window_exception();
 
-        _arrivalTW.min = baseRequest.getArrivalTw().min;
-        _arrivalTW.max = _departureTW.min + baseRequest.getDeltaTime(); //Reduce max arrival TW to a value we are 100% sure is compatible with our current min departure time
-    }
     _transitTravelTimeRatio = baseRequest.getTransitTravelTimeRatio();
     _deltaTime = UINT16_MAX;
     _weight = baseRequest.getWeight();
diff --git a/src/instance/requests/Request.h b/src/instance/requests/Request.h
index 51ef41e..8846e2d 100644
--- a/src/instance/requests/Request.h
+++ b/src/instance/requests/Request.h
@@ -11,6 +11,7 @@
 #include "../graph/Graph.h"
 #include "../../algorithm/Multimodal/Heuristics/TransitAccess.h"
 #include "../../utils/Constants.h"
+#include "../../routes/vehicle/SAEVKeyPoint.h"
 
 class Request {
 private:
@@ -41,7 +42,25 @@ public:
             const uint deltaTime, const uint weight, const Graph& graph);
     Request(const DATRow& currentRow, const Graph& graph);
     Request(const DATRow& currentRow, double deltaRatio, const Graph& graph);
-    Request(const Graph& graph, const Request &baseRequest, const TransitAccess &access, bool isEntry);
+    /**
+     * Entry sub request constructor, creating a new request from info on
+     * the base request and a transit entry candidate (entry node + max departure time)
+     * @param graph
+     * @param baseRequest
+     * @param transitEntry
+     */
+    Request(const Graph &graph, const Request &baseRequest, const TransitAccess &transitEntry);
+    /**
+     * Exit sub request constructor, creating a new request from info on
+     * the base request, a transit exit candidate (exit node + arrival time)
+     * and the current state of the entry sub request
+     * @param graph
+     * @param baseRequest
+     * @param transitExit
+     * @param originSubRequestKeyPoint
+     */
+    Request(const Graph &graph, const Request &baseRequest, const TransitAccess &transitExit,
+            const SAEVKeyPoint &originSubRequestKeyPoint);
 
     static std::vector<Request> getRequestsFromFile(const std::string& datFilePath, const Graph& graph);
 
-- 
GitLab


From ee00ba636e2af2115b51d67c7a70a8ac1ffa94f9 Mon Sep 17 00:00:00 2001
From: Romain BERNARD <romain.bernard@uca.fr>
Date: Tue, 10 Sep 2024 16:38:14 +0200
Subject: [PATCH 278/327] fix compilation

---
 src/routes/vehicle/SAEVKeyPoint.h | 6 +++++-
 1 file changed, 5 insertions(+), 1 deletion(-)

diff --git a/src/routes/vehicle/SAEVKeyPoint.h b/src/routes/vehicle/SAEVKeyPoint.h
index 1e6992c..9756957 100644
--- a/src/routes/vehicle/SAEVKeyPoint.h
+++ b/src/routes/vehicle/SAEVKeyPoint.h
@@ -8,7 +8,10 @@
 
 #include "../KeyPoint.h"
 #include "../../instance/graph/Graph.h"
-#include "../../instance/requests/Request.h"
+
+class Request;
+
+class SAEVehicle;
 
 class SAEVKeyPoint : public KeyPoint {
 private:
@@ -83,6 +86,7 @@ public:
 
     [[nodiscard]] std::string to_string() const override;
 };
+#include "../../instance/requests/Request.h"
 
 
 #endif //GREEDYALGORITHM_SAEVKEYPOINT_H
-- 
GitLab


From 6e2504ee375623dad83c915371c06427d3c09acd Mon Sep 17 00:00:00 2001
From: Romain BERNARD <romain.bernard@uca.fr>
Date: Tue, 10 Sep 2024 16:40:47 +0200
Subject: [PATCH 279/327] fix time slot choice in entry candidate selection

---
 src/algorithm/Multimodal/Heuristics/SimpleModularHeuristic.cpp | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/src/algorithm/Multimodal/Heuristics/SimpleModularHeuristic.cpp b/src/algorithm/Multimodal/Heuristics/SimpleModularHeuristic.cpp
index f9043b6..d861158 100644
--- a/src/algorithm/Multimodal/Heuristics/SimpleModularHeuristic.cpp
+++ b/src/algorithm/Multimodal/Heuristics/SimpleModularHeuristic.cpp
@@ -19,7 +19,7 @@ std::vector<TransitAccess> SimpleModularHeuristic::getBestTransitEntriesList(con
         for(const Node& bestStationNode = _graph->getNode(bestStationNodeIdx);
             const auto& lineStop : bestStationNode.getPTLinesSet()) {
             //Find the next passage lower or equal to our max entry time constraint
-            auto iterator = lineStop.findNextScheduledPassage(getMaxEntryConstraint(baseRequest, bestStationNodeIdx))--;
+            auto iterator = --lineStop.findNextScheduledPassage(getMaxEntryConstraint(baseRequest, bestStationNodeIdx))--;
             if(iterator != lineStop.getSchedule().end() && *iterator > maxDepartureTime //If we've found a valid time that's superior to our current max time
             && *iterator > getMinEntryConstraint(baseRequest, bestStationNodeIdx)) { //and respects min entry time, replace old value
                 maxDepartureTime = *iterator;
-- 
GitLab


From 7dfec669240a5adceab045aebdfc0952df180824 Mon Sep 17 00:00:00 2001
From: Romain BERNARD <romain.bernard@uca.fr>
Date: Wed, 11 Sep 2024 15:31:03 +0200
Subject: [PATCH 280/327] fix return type to prevent ref staleness

---
 .../Multimodal/Heuristics/SimpleModularHeuristic.cpp          | 4 ++--
 src/algorithm/Multimodal/Heuristics/SimpleModularHeuristic.h  | 4 ++--
 2 files changed, 4 insertions(+), 4 deletions(-)

diff --git a/src/algorithm/Multimodal/Heuristics/SimpleModularHeuristic.cpp b/src/algorithm/Multimodal/Heuristics/SimpleModularHeuristic.cpp
index d861158..b0c17a2 100644
--- a/src/algorithm/Multimodal/Heuristics/SimpleModularHeuristic.cpp
+++ b/src/algorithm/Multimodal/Heuristics/SimpleModularHeuristic.cpp
@@ -54,7 +54,7 @@ uint SimpleModularHeuristic::getMaxEntryConstraint(const Request &request, size_
  * @param baseRequestId ID/index in the request vector for our base request
  * @return The subrequest successfully inserted in our route. This method's caller needs to add this request to its main request vector
  */
-Request SimpleModularHeuristic::insertBestTransitEntryInRoute(const Request &baseRequest, size_t baseRequestId) {
+const Request & SimpleModularHeuristic::insertBestTransitEntryInRoute(const Request &baseRequest, size_t baseRequestId) {
     std::vector<TransitAccess> entriesAccessList = getBestTransitEntriesList(baseRequest);
     return insertBestTransitAccessInRoute(baseRequest, entriesAccessList, baseRequestId, true);
 }
@@ -215,7 +215,7 @@ SimpleModularHeuristic::getBestTransitExitsList(const Request &baseRequest, cons
     return truncatedTransitExitsList;
 }
 
-Request SimpleModularHeuristic::insertBestTransitExitsInRoute(const Request &baseRequest, size_t baseRequestId) {
+const Request & SimpleModularHeuristic::insertBestTransitExitsInRoute(const Request &baseRequest, size_t baseRequestId) {
     std::vector<TransitAccess> exitAccessList = getBestTransitExitsList(baseRequestId);
     return insertBestTransitAccessInRoute(baseRequest, exitAccessList, baseRequestId, false);
 }
diff --git a/src/algorithm/Multimodal/Heuristics/SimpleModularHeuristic.h b/src/algorithm/Multimodal/Heuristics/SimpleModularHeuristic.h
index 16fc5ec..491b91d 100644
--- a/src/algorithm/Multimodal/Heuristics/SimpleModularHeuristic.h
+++ b/src/algorithm/Multimodal/Heuristics/SimpleModularHeuristic.h
@@ -55,8 +55,8 @@ public:
 //Private members for heuristic internal functions we don't wish to see overriden
 private:
 
-    Request insertBestTransitEntryInRoute(const Request &baseRequest, size_t baseRequestId);
-    Request insertBestTransitExitsInRoute(const Request &baseRequest, size_t baseRequestId);
+    const Request & insertBestTransitEntryInRoute(const Request &baseRequest, size_t baseRequestId);
+    const Request & insertBestTransitExitsInRoute(const Request &baseRequest, size_t baseRequestId);
 
 
     const Request &insertBestTransitAccessInRoute(const Request &baseRequest, const std::vector<TransitAccess> &transitAccessList,
-- 
GitLab


From fb78b9ae2bd4f73dde759cc37300c8ed5a243750 Mon Sep 17 00:00:00 2001
From: Romain BERNARD <romain.bernard@uca.fr>
Date: Wed, 11 Sep 2024 17:58:49 +0200
Subject: [PATCH 281/327] automatically accept requests that don't actually
 need a vehicle (start and end on a same node)

---
 .../Heuristics/BestInsertionHeuristic.cpp     | 20 ++++++++++++-------
 src/routes/vehicle/SAEVRoute.cpp              |  7 +++++++
 2 files changed, 20 insertions(+), 7 deletions(-)

diff --git a/src/algorithm/DARP/Heuristics/BestInsertionHeuristic.cpp b/src/algorithm/DARP/Heuristics/BestInsertionHeuristic.cpp
index 0961619..38b52b4 100644
--- a/src/algorithm/DARP/Heuristics/BestInsertionHeuristic.cpp
+++ b/src/algorithm/DARP/Heuristics/BestInsertionHeuristic.cpp
@@ -56,12 +56,18 @@ size_t BestInsertionHeuristic::doBestRequestInsertionForRoute(SAEVKeyPoint &requ
 }
 
 SAEVRouteChangelist BestInsertionHeuristic::tryBestRequestInsertionInActiveVehicle(SAEVKeyPoint &requestKp, SAEVRoute &route) {
-    size_t vehicleId = 0;
-    BestInsertionQueue bestInsertions{requestKp};
-    //Iteratively try inserting in every active vehicle and the first inactive vehicle
-    do {
-        route.getBestFeasibleInsertionsQueue(bestInsertions, requestKp, vehicleId);
-    } while(++vehicleId <= route.getLastActiveVehicleId());
+    if(requestKp.getNodeIndex() == requestKp.getCounterpart()->getNodeIndex()) {
+        SAEVRouteChangelist res(&route, &requestKp);
+        res.setStatus(SAEVRouteChangelist::InsertionStatus::SUCCESS);
+        return res;
+    } else {
+        size_t vehicleId = 0;
+        BestInsertionQueue bestInsertions{requestKp};
+        //Iteratively try inserting in every active vehicle and the first inactive vehicle
+        do {
+            route.getBestFeasibleInsertionsQueue(bestInsertions, requestKp, vehicleId);
+        } while(++vehicleId <= route.getLastActiveVehicleId());
 
-    return tryVehicleBestInsertion(bestInsertions, route);
+        return tryVehicleBestInsertion(bestInsertions, route);
+    }
 }
diff --git a/src/routes/vehicle/SAEVRoute.cpp b/src/routes/vehicle/SAEVRoute.cpp
index 7daa464..dd08b69 100644
--- a/src/routes/vehicle/SAEVRoute.cpp
+++ b/src/routes/vehicle/SAEVRoute.cpp
@@ -140,6 +140,13 @@ SAEVRoute::tryAddRequest(SAEVKeyPoint &requestOriginKeyPoint, SAEVKeyPoint * ori
     const Request* request = requestOriginKeyPoint.getRequest();
     SAEVKeyPoint const* destinationSuccessor = destinationRequestPredecessorKP->getSuccessor();
 
+    //Check if this request actually needs a vehicle
+    if(requestOriginKeyPoint.getNodeIndex() == requestOriginKeyPoint.getCounterpart()->getNodeIndex()) {
+        SAEVRouteChangelist res(this, &requestOriginKeyPoint);
+        res.setStatus(SAEVRouteChangelist::InsertionStatus::SUCCESS);
+        return res;
+    }
+
     //Check vehicle capacity
     SAEVKeyPoint const* currentKP = originRequestPredecessorKP;
     do {
-- 
GitLab


From 3e9cd4efc270de86be1eb82a600d0402fbb0fc00 Mon Sep 17 00:00:00 2001
From: Romain BERNARD <romain.bernard@uca.fr>
Date: Wed, 11 Sep 2024 18:00:21 +0200
Subject: [PATCH 282/327] set exit subrequest arrival tw properly depending on
 if the transit entry required a vehicle or not

---
 src/instance/requests/Request.cpp | 5 ++++-
 1 file changed, 4 insertions(+), 1 deletion(-)

diff --git a/src/instance/requests/Request.cpp b/src/instance/requests/Request.cpp
index 9cec884..bfb1ad8 100644
--- a/src/instance/requests/Request.cpp
+++ b/src/instance/requests/Request.cpp
@@ -232,7 +232,10 @@ Request::Request(const Graph &graph, const Request &baseRequest, const TransitAc
     _departureTW.max = baseRequest.getArrivalTw().max - graph.getShortestSAEVPath(transitExit.getAccessNodeIdx(), _destinationNodeIndex);
 
     _arrivalTW.min = baseRequest.getArrivalTw().min;
-    _arrivalTW.max = originSubRequestKeyPoint.getMinTw() + baseRequest.getDeltaTime(); //Reduce max arrival TW to a value we are 100% sure is compatible with our current min departure time
+    if(originSubRequestKeyPoint.getNodeIndex() != originSubRequestKeyPoint.getCounterpart()->getNodeIndex())
+        _arrivalTW.max = originSubRequestKeyPoint.getMinTw() + baseRequest.getDeltaTime(); //Reduce max arrival TW to a value we are 100% sure is compatible with our current min departure time
+    else
+        _arrivalTW.max = std::min(baseRequest.getMinDepartureTw() + baseRequest.getDeltaTime(), baseRequest.getMaxArrivalTw()); //force earliest departure
 
     if(_departureTW.min > _departureTW.max || _arrivalTW.min > _arrivalTW.max)
         throw TimeWindow::invalid_time_window_exception();
-- 
GitLab


From 69956632e72b4eadf395d4da0cb490a93183d5a8 Mon Sep 17 00:00:00 2001
From: Romain BERNARD <romain.bernard@uca.fr>
Date: Wed, 11 Sep 2024 18:02:49 +0200
Subject: [PATCH 283/327] add transit shortest path arrival node (getArrival
 used to return the last connection)

---
 src/ShortestPath/Transit/TransitShortestPath.h | 4 +++-
 1 file changed, 3 insertions(+), 1 deletion(-)

diff --git a/src/ShortestPath/Transit/TransitShortestPath.h b/src/ShortestPath/Transit/TransitShortestPath.h
index 7aa5d13..067282d 100644
--- a/src/ShortestPath/Transit/TransitShortestPath.h
+++ b/src/ShortestPath/Transit/TransitShortestPath.h
@@ -12,12 +12,14 @@
 class TransitShortestPath : public ShortestPath<std::reference_wrapper<const LineStop>> {
 private:
     int _arrivalTime{-1};
+    int _arrivalNode{-1};
 public:
     TransitShortestPath() = default;
 
     explicit TransitShortestPath(const TransitAlgorithmState& state) {
         if(state.getNbConnections() > 0) {
             _keyPoints = state.getConnections();
+            _arrivalNode = state.getNodeIndex();
             _arrivalTime = state.getInstant();
         }
     }
@@ -55,7 +57,7 @@ public:
     }
 
     [[nodiscard]] size_t getArrivalNode() const {
-        return getArrival().get().getNodeIndex();
+        return _arrivalNode;
     }
 
     [[nodiscard]] int getArrivalTime() const { return _arrivalTime; }
-- 
GitLab


From 74da56c6a26aafdb95d90ff43acbdf28defe73fd Mon Sep 17 00:00:00 2001
From: Romain BERNARD <romain.bernard@uca.fr>
Date: Wed, 11 Sep 2024 18:33:13 +0200
Subject: [PATCH 284/327] give a more accurate max exit constraint for transit
 exit

---
 .../Heuristics/SimpleModularHeuristic.cpp     | 21 ++++++++++++-------
 .../Heuristics/SimpleModularHeuristic.h       | 13 +++++++-----
 2 files changed, 22 insertions(+), 12 deletions(-)

diff --git a/src/algorithm/Multimodal/Heuristics/SimpleModularHeuristic.cpp b/src/algorithm/Multimodal/Heuristics/SimpleModularHeuristic.cpp
index b0c17a2..d863437 100644
--- a/src/algorithm/Multimodal/Heuristics/SimpleModularHeuristic.cpp
+++ b/src/algorithm/Multimodal/Heuristics/SimpleModularHeuristic.cpp
@@ -105,7 +105,8 @@ SimpleModularHeuristic::insertBestTransitAccessInRoute(const std::vector<Request
                                                        size_t baseRequestId, bool isEntry) {
     for(const auto& subreq : accessSubRequestsList) {
         updateSubRequest(baseRequestId, subreq, isEntry);
-        SAEVRouteChangelist changeList = BestInsertionHeuristic::tryBestRequestInsertionInActiveVehicle(_route->getEntrySubRequestOrigin(baseRequestId), *_route);
+        SAEVRouteChangelist changeList = BestInsertionHeuristic::tryBestRequestInsertionInActiveVehicle(
+                _route->getEntrySubRequestOrigin(baseRequestId), *_route);
         //If we've found an insertion that doesn't create a vehicle, stop there
         if(changeList.success()) {
             DEBUG_MSG("ENTRY CANDIDATE SUCCESS : " + subreq.to_string());
@@ -176,24 +177,28 @@ SimpleModularHeuristic::getScoredTransitExitOrderer() {
     return [](SimpleModularHeuristic::ScoredTransitAccess lhs, SimpleModularHeuristic::ScoredTransitAccess rhs) { return lhs.score < rhs.score; };
 }
 
-uint SimpleModularHeuristic::getMinExitConstraint(size_t baseRequestId, const TransitAccess &exitData) {
+uint SimpleModularHeuristic::getMinExitConstraint(size_t baseRequestId, const SAEVKeyPoint &entrySubRequestOriginKP,
+                                                  size_t transitExitNodeIdx) const {
     return 0;
 }
 
-uint SimpleModularHeuristic::getMaxExitConstraint(size_t baseRequestId, const TransitAccess &exitData) {
+uint SimpleModularHeuristic::getMaxExitConstraint(size_t baseRequestId, const SAEVKeyPoint &entrySubRequestOriginKP,
+                                                  size_t transitExitNodeIdx) const {
     const Request& baseRequest = (*_requestsVect)[baseRequestId];
-    return baseRequest.getMaxArrivalTw() - _graph->getShortestSAEVPath(exitData.getAccessNodeIdx(), baseRequest.getDestinationNodeIndex());
+    return (entrySubRequestOriginKP.getMinTw() + baseRequest.getDeltaTime()) -
+           _graph->getShortestSAEVPath(transitExitNodeIdx, baseRequest.getDestinationNodeIndex());
 }
 
 std::vector<TransitAccess>
 SimpleModularHeuristic::getBestTransitExitsList(size_t baseRequestId) {
     const Request& baseRequest = (*_requestsVect)[baseRequestId];
     const SAEVKeyPoint& entrySubRequestOriginKP = _route->getEntrySubRequestOrigin(baseRequestId);
-    return getBestTransitExitsList(baseRequest, entrySubRequestOriginKP);
+    return getBestTransitExitsList(baseRequestId, baseRequest, entrySubRequestOriginKP);
 }
 
 std::vector<TransitAccess>
-SimpleModularHeuristic::getBestTransitExitsList(const Request &baseRequest, const SAEVKeyPoint &entrySubRequestOriginKP) const {
+SimpleModularHeuristic::getBestTransitExitsList(size_t baseRequestId, const Request &baseRequest,
+                                                const SAEVKeyPoint &entrySubRequestOriginKP) const {
     std::vector<SimpleModularHeuristic::ScoredTransitAccess> scoredTransitExits;
     //Get departure time/shortest transit paths list from the entry sub request's max time (this means we take the first transit available after current max arrival)
     //TODO : study other approaches (e.g check for a faster max arrival if it's valid and allows better paths. This would require propagation => costly)
@@ -202,7 +207,9 @@ SimpleModularHeuristic::getBestTransitExitsList(const Request &baseRequest, cons
 
     //Iterate over the best stations saved prior
     for(const auto& shortestTransitPath : shortestTransitPaths) {
-        if(shortestTransitPath.getArrivalTime() >= 0) {
+        //Check valid transit path + arrival node != starting point
+        if(shortestTransitPath.getArrivalTime() >= 0 && shortestTransitPath.getArrivalNode() != entryNodeIdx
+        && shortestTransitPath.getArrivalTime() < getMaxExitConstraint(baseRequestId, entrySubRequestOriginKP, shortestTransitPath.getArrivalNode())) {
             TransitAccess exit{shortestTransitPath.getArrivalNode(),  (uint) shortestTransitPath.getArrivalTime()};
             scoredTransitExits.emplace_back(exit, getTransitExitScore(baseRequest, exit));
         }
diff --git a/src/algorithm/Multimodal/Heuristics/SimpleModularHeuristic.h b/src/algorithm/Multimodal/Heuristics/SimpleModularHeuristic.h
index 491b91d..459d0fe 100644
--- a/src/algorithm/Multimodal/Heuristics/SimpleModularHeuristic.h
+++ b/src/algorithm/Multimodal/Heuristics/SimpleModularHeuristic.h
@@ -110,7 +110,8 @@ private:
     * and the min/max entry constraints. If no valid access is found, we return an empty vector.
     */
     [[nodiscard]] std::vector<TransitAccess>
-    getBestTransitExitsList(const Request &baseRequest, const SAEVKeyPoint &entrySubRequestOriginKP) const;
+    getBestTransitExitsList(size_t baseRequestId, const Request &baseRequest,
+                            const SAEVKeyPoint &entrySubRequestOriginKP) const;
 
 //Protected member function for overriding as we make this more modular
 protected:
@@ -122,18 +123,20 @@ protected:
      * Base implementation of min exit constraint.
      * This implementation is equivalent to no min constraint, as our subset of possible moves already filters our options a bit
      * @param baseRequestId Id of the base request for which we generate exit subrequests. Necessary to get data on base request and entry subrequest if necessary
-     * @param exitData Data containing the exit node and timestamp
+     * @param transitExitNodeIdx exit node index
      * @return 0
      */
-    [[nodiscard]] uint getMinExitConstraint(size_t baseRequestId, const TransitAccess &exitData);
+    [[nodiscard]] uint getMinExitConstraint(size_t baseRequestId, const SAEVKeyPoint &entrySubRequestOriginKP,
+                                            size_t transitExitNodeIdx) const;
     /**
      * Base implementation of max exit constraint.
      * This base implementation just checks for arrival validity wrt the base request's max time window
      * @param baseRequestId Id of the base request for which we generate exit subrequests. Necessary to get data on base request and entry subrequest if necessary
-     * @param exitData Data containing the exit node and timestamp
+     * @param transitExitNodeIdx exit node index
      * @return baseRequest.DestinationTW.max - T(exitData.Node, baseRequest.Destination)
      */
-    [[nodiscard]] uint getMaxExitConstraint(size_t baseRequestId, const TransitAccess &exitData);
+    [[nodiscard]] uint getMaxExitConstraint(size_t baseRequestId, const SAEVKeyPoint &entrySubRequestOriginKP,
+                                            size_t transitExitNodeIdx) const;
     /**
      * Base implementation of a sorting score (lower is better) for exit candidates.
      * This implementation scores via T(exitNode, destinationNode) + exitTime to try and
-- 
GitLab


From 3799e8119e0e499a53d6384defee368878f5f255 Mon Sep 17 00:00:00 2001
From: Romain BERNARD <romain.bernard@uca.fr>
Date: Wed, 11 Sep 2024 18:36:31 +0200
Subject: [PATCH 285/327] account for cases where the entry subrequest didn't
 require a vehicle (use min departure)

---
 .../Multimodal/Heuristics/SimpleModularHeuristic.cpp   | 10 ++++++++--
 1 file changed, 8 insertions(+), 2 deletions(-)

diff --git a/src/algorithm/Multimodal/Heuristics/SimpleModularHeuristic.cpp b/src/algorithm/Multimodal/Heuristics/SimpleModularHeuristic.cpp
index d863437..f433ce5 100644
--- a/src/algorithm/Multimodal/Heuristics/SimpleModularHeuristic.cpp
+++ b/src/algorithm/Multimodal/Heuristics/SimpleModularHeuristic.cpp
@@ -202,8 +202,14 @@ SimpleModularHeuristic::getBestTransitExitsList(size_t baseRequestId, const Requ
     std::vector<SimpleModularHeuristic::ScoredTransitAccess> scoredTransitExits;
     //Get departure time/shortest transit paths list from the entry sub request's max time (this means we take the first transit available after current max arrival)
     //TODO : study other approaches (e.g check for a faster max arrival if it's valid and allows better paths. This would require propagation => costly)
-    const auto& [departureTime, shortestTransitPaths] = _graph->getShortestTransitPathsFrom(entrySubRequestOriginKP.getCounterpart()->getNodeIndex(),
-                                                                   entrySubRequestOriginKP.getCounterpart()->getMaxTw());
+
+    size_t entryNodeIdx = entrySubRequestOriginKP.getCounterpart()->getNodeIndex();
+    uint transitMinDepartureTime = entrySubRequestOriginKP.getCounterpart()->getMaxTw();
+    if(entrySubRequestOriginKP.getNodeIndex() == entrySubRequestOriginKP.getCounterpart()->getNodeIndex()) {
+        transitMinDepartureTime = baseRequest.getMinDepartureTw(); //TODO: check with the team if this choice is fine
+    }
+    const auto& [departureTime, shortestTransitPaths] = _graph->getShortestTransitPathsFrom(entryNodeIdx,
+                                                                                            transitMinDepartureTime);
 
     //Iterate over the best stations saved prior
     for(const auto& shortestTransitPath : shortestTransitPaths) {
-- 
GitLab


From 292a2b33e24ab0da873ecc542e9c280dc1fd0d90 Mon Sep 17 00:00:00 2001
From: Romain BERNARD <romain.bernard@uca.fr>
Date: Wed, 11 Sep 2024 18:40:27 +0200
Subject: [PATCH 286/327] Add debug check for exit candidates generation

---
 src/algorithm/Multimodal/Heuristics/SimpleModularHeuristic.cpp | 1 +
 1 file changed, 1 insertion(+)

diff --git a/src/algorithm/Multimodal/Heuristics/SimpleModularHeuristic.cpp b/src/algorithm/Multimodal/Heuristics/SimpleModularHeuristic.cpp
index f433ce5..caa528c 100644
--- a/src/algorithm/Multimodal/Heuristics/SimpleModularHeuristic.cpp
+++ b/src/algorithm/Multimodal/Heuristics/SimpleModularHeuristic.cpp
@@ -220,6 +220,7 @@ SimpleModularHeuristic::getBestTransitExitsList(size_t baseRequestId, const Requ
             scoredTransitExits.emplace_back(exit, getTransitExitScore(baseRequest, exit));
         }
     }
+    assertm(!scoredTransitExits.empty(), ("No valid exit from the given entrance has been found for base request #" + std::to_string(baseRequestId)));
 
     //Sort and truncate transit exits list while removing score data that's unnecessary in later steps
     std::ranges::sort(scoredTransitExits, getScoredTransitExitOrderer());
-- 
GitLab


From d0d12477220bc7a5a27c91f02c247cf85ee23f5d Mon Sep 17 00:00:00 2001
From: Romain BERNARD <romain.bernard@uca.fr>
Date: Wed, 11 Sep 2024 18:44:35 +0200
Subject: [PATCH 287/327] remove duplicate --

---
 src/algorithm/Multimodal/Heuristics/SimpleModularHeuristic.cpp | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/src/algorithm/Multimodal/Heuristics/SimpleModularHeuristic.cpp b/src/algorithm/Multimodal/Heuristics/SimpleModularHeuristic.cpp
index caa528c..9e8d771 100644
--- a/src/algorithm/Multimodal/Heuristics/SimpleModularHeuristic.cpp
+++ b/src/algorithm/Multimodal/Heuristics/SimpleModularHeuristic.cpp
@@ -19,7 +19,7 @@ std::vector<TransitAccess> SimpleModularHeuristic::getBestTransitEntriesList(con
         for(const Node& bestStationNode = _graph->getNode(bestStationNodeIdx);
             const auto& lineStop : bestStationNode.getPTLinesSet()) {
             //Find the next passage lower or equal to our max entry time constraint
-            auto iterator = --lineStop.findNextScheduledPassage(getMaxEntryConstraint(baseRequest, bestStationNodeIdx))--;
+            auto iterator = --lineStop.findNextScheduledPassage(getMaxEntryConstraint(baseRequest, bestStationNodeIdx));
             if(iterator != lineStop.getSchedule().end() && *iterator > maxDepartureTime //If we've found a valid time that's superior to our current max time
             && *iterator > getMinEntryConstraint(baseRequest, bestStationNodeIdx)) { //and respects min entry time, replace old value
                 maxDepartureTime = *iterator;
-- 
GitLab


From 7b3c6c351e1457d26ddd4c84c122542dcc949e65 Mon Sep 17 00:00:00 2001
From: Romain BERNARD <romain.bernard@uca.fr>
Date: Wed, 11 Sep 2024 19:14:23 +0200
Subject: [PATCH 288/327] add checks to new transit line generation

---
 src/instance/graph/Graph.cpp | 13 ++++++-------
 src/instance/graph/Line.cpp  |  1 +
 2 files changed, 7 insertions(+), 7 deletions(-)

diff --git a/src/instance/graph/Graph.cpp b/src/instance/graph/Graph.cpp
index 87b8c7a..c04ae36 100644
--- a/src/instance/graph/Graph.cpp
+++ b/src/instance/graph/Graph.cpp
@@ -110,8 +110,8 @@ Graph::Graph(const std::string& datFilePath) {
 
     //-- Read Public transit line
     std::cout << currentRow.toString() << std::endl;
-    std::uniform_int_distribution<uint32_t> uint_dist10(1,10);
-    std::uniform_int_distribution<uint32_t> uint_dist60(1,60);
+    std::uniform_int_distribution<uint32_t> uint_dist10(1,5);
+    std::uniform_int_distribution<uint32_t> uint_dist60(1,10);
     while(infile >> currentRow && !currentRow[0].starts_with('#')) {
         this->parseLineRandomizedSchedule(currentRow, rng, uint_dist10, uint_dist60);
     }
@@ -294,11 +294,10 @@ void Graph::parseLineRandomizedSchedule(const DATRow& row, std::mt19937 rng,
         newLine.addTimetable(newTimetable);
         newTimetable.clear();
     }
-
-    this->addLine(newLine);
-
-    DEBUG_MSG("Created new line with nodes");
-
+    if(newLine.check()) {
+        this->addLine(newLine);
+        DEBUG_MSG("Created new line with nodes");
+    }
 }
 
 void Graph::createAndAddEdge(size_t edgeStartNodeIndex, size_t edgeEndNodeIndex, double length) {
diff --git a/src/instance/graph/Line.cpp b/src/instance/graph/Line.cpp
index aebd398..48b94f0 100644
--- a/src/instance/graph/Line.cpp
+++ b/src/instance/graph/Line.cpp
@@ -14,6 +14,7 @@ bool Line::checkSchedules() const{
 
     int precedingTimeStep = 0;
     int expectedScheduleSize = !_timetables.empty() ? _timetables[0].size() : 0;
+    checkResult &= expectedScheduleSize > 0;
     for(auto& schedule : _timetables)
     {
         precedingTimeStep = 0; //reinit first timestep to 0
-- 
GitLab


From a632a111167cc4bcc3c6274c0cd3cd461e3834ec Mon Sep 17 00:00:00 2001
From: Romain BERNARD <romain.bernard@uca.fr>
Date: Wed, 11 Sep 2024 19:19:46 +0200
Subject: [PATCH 289/327] fix checking the next scheduled passage wrt max entry
 constraint if no value is lower than it

---
 .../Heuristics/SimpleModularHeuristic.cpp           | 13 ++++++++-----
 1 file changed, 8 insertions(+), 5 deletions(-)

diff --git a/src/algorithm/Multimodal/Heuristics/SimpleModularHeuristic.cpp b/src/algorithm/Multimodal/Heuristics/SimpleModularHeuristic.cpp
index 9e8d771..aeed8ff 100644
--- a/src/algorithm/Multimodal/Heuristics/SimpleModularHeuristic.cpp
+++ b/src/algorithm/Multimodal/Heuristics/SimpleModularHeuristic.cpp
@@ -19,10 +19,13 @@ std::vector<TransitAccess> SimpleModularHeuristic::getBestTransitEntriesList(con
         for(const Node& bestStationNode = _graph->getNode(bestStationNodeIdx);
             const auto& lineStop : bestStationNode.getPTLinesSet()) {
             //Find the next passage lower or equal to our max entry time constraint
-            auto iterator = --lineStop.findNextScheduledPassage(getMaxEntryConstraint(baseRequest, bestStationNodeIdx));
-            if(iterator != lineStop.getSchedule().end() && *iterator > maxDepartureTime //If we've found a valid time that's superior to our current max time
-            && *iterator > getMinEntryConstraint(baseRequest, bestStationNodeIdx)) { //and respects min entry time, replace old value
-                maxDepartureTime = *iterator;
+            auto iterator = lineStop.findNextScheduledPassage(getMaxEntryConstraint(baseRequest, bestStationNodeIdx));
+            if(iterator != lineStop.getSchedule().cbegin() && iterator != lineStop.getSchedule().cend()) { //Iterator is invalid if it points to schedule end (no result) or begin (no result lower than our constraint)
+                --iterator; //Move iterator to the value that's under our max entry constraint
+                if(*iterator > maxDepartureTime //If we've found a valid time that's superior to our current max time
+                && *iterator > getMinEntryConstraint(baseRequest, bestStationNodeIdx)) { //and respects min entry time, replace old value
+                    maxDepartureTime = *iterator;
+                }
             }
         }
 
@@ -42,7 +45,7 @@ uint SimpleModularHeuristic::getMinEntryConstraint(const Request &request, size_
 }
 
 uint SimpleModularHeuristic::getMaxEntryConstraint(const Request &request, size_t ptEntryNodeIdx) const {
-    return (uint) std::floor(request.getMaxArrivalTw() - _graph->getShortestSAEVPath(ptEntryNodeIdx, request.getDestinationNodeIndex()) * request.getTransitTravelTimeRatio());
+    return request.getMaxArrivalTw() - ((uint) std::floor(_graph->getShortestSAEVPath(ptEntryNodeIdx, request.getDestinationNodeIndex()) * request.getTransitTravelTimeRatio()));
 }
 
 /**
-- 
GitLab


From 4e4fdc2eb9d9532c5abc7c0e587d772a65638303 Mon Sep 17 00:00:00 2001
From: Romain BERNARD <romain.bernard@uca.fr>
Date: Wed, 11 Sep 2024 19:31:47 +0200
Subject: [PATCH 290/327] add exit debug to tests

---
 test/src/MultimodalInsertionHeuristicDebug.cpp | 16 +++++++++++++++-
 1 file changed, 15 insertions(+), 1 deletion(-)

diff --git a/test/src/MultimodalInsertionHeuristicDebug.cpp b/test/src/MultimodalInsertionHeuristicDebug.cpp
index 476cb10..9068484 100644
--- a/test/src/MultimodalInsertionHeuristicDebug.cpp
+++ b/test/src/MultimodalInsertionHeuristicDebug.cpp
@@ -20,7 +20,7 @@ TEST(MultimodalInsertionHeuristicDebug, DebugBaseInstance) {
     INIT_TIMER
     Graph graphFromSingleFile(instancesPath + instanceFolder + datFile);
     graphFromSingleFile.computeAndUpdateShortestPathsMatrix(true);
-    RequestGenerationParameters genParams(1, 1.5, 15,30,240,600,290820241032L);
+    RequestGenerationParameters genParams(1, 1.5, 15,30,300,600,290820241032L);
     std::vector<Request> requests = RequestsGenerator::generateRequests(graphFromSingleFile, genParams);
 
     //Init instance
@@ -42,6 +42,13 @@ TEST(MultimodalInsertionHeuristicDebug, DebugBaseInstance) {
     }
     STOP_TIMER("Multimodal insertion (entry)")
     std::cout << "------------------End multimodal insertion (entry)-------------------" << std::endl << std::endl;
+    std::cout << "------------------Start multimodal insertion (exit)-------------------" << std::endl << std::endl;
+    START_TIMER
+    for(size_t i = 0; i < multimodalHeuristic.getNbBaseRquests(); ++i) {
+        multimodalHeuristic.insertBestTransitExitsInRoute(requests[i], i);
+    }
+    STOP_TIMER("Multimodal insertion (exit)")
+    std::cout << "------------------End multimodal insertion (exit)-------------------" << std::endl << std::endl;
 }
 
 TEST(MultimodalInsertionHeuristicDebug, DebugInstanceAlain) {
@@ -76,6 +83,13 @@ TEST(MultimodalInsertionHeuristicDebug, DebugInstanceAlain) {
     }
     STOP_TIMER("Multimodal insertion (entry)")
     std::cout << "------------------End multimodal insertion (entry)-------------------" << std::endl << std::endl;
+    std::cout << "------------------Start multimodal insertion (exit)-------------------" << std::endl << std::endl;
+    START_TIMER
+    for(size_t i = 0; i < multimodalHeuristic.getNbBaseRquests(); ++i) {
+        multimodalHeuristic.insertBestTransitExitsInRoute(requests[i], i);
+    }
+    STOP_TIMER("Multimodal insertion (exit)")
+    std::cout << "------------------End multimodal insertion (exit)-------------------" << std::endl << std::endl;
 }
 
 int main(int argc, char* argv[]) {
-- 
GitLab


From ac0603fcab25506ff559b5f77ef3622e24f30fb3 Mon Sep 17 00:00:00 2001
From: Romain BERNARD <romain.bernard@uca.fr>
Date: Thu, 12 Sep 2024 17:47:31 +0200
Subject: [PATCH 291/327] add unfulfilled entry/exit requests info

---
 .../Heuristics/SimpleModularHeuristic.cpp     | 31 ++++++++++++++++---
 .../Heuristics/SimpleModularHeuristic.h       | 25 +++++++++------
 2 files changed, 43 insertions(+), 13 deletions(-)

diff --git a/src/algorithm/Multimodal/Heuristics/SimpleModularHeuristic.cpp b/src/algorithm/Multimodal/Heuristics/SimpleModularHeuristic.cpp
index aeed8ff..b7a3468 100644
--- a/src/algorithm/Multimodal/Heuristics/SimpleModularHeuristic.cpp
+++ b/src/algorithm/Multimodal/Heuristics/SimpleModularHeuristic.cpp
@@ -119,10 +119,17 @@ SimpleModularHeuristic::insertBestTransitAccessInRoute(const std::vector<Request
         }
     }
 
-    //If no active vehicle insertion worked, do best insertion on a new vehicle with the first subrequest (supposedly it's the most advantageous)
-    DEBUG_MSG("CREATE VEHICLE");
-    updateSubRequest(baseRequestId, accessSubRequestsList[0], isEntry);
-    _route->insertRequestInNewVehicle(_route->getEntrySubRequestOrigin(baseRequestId));
+    if(accessSubRequestsList.empty()) { //If no valid subrequest was given, still create a fake subrequest and mention failure in the appropriate vector
+        DEBUG_MSG("UNFULFILLED SUBREQUEST");
+        updateSubRequest(baseRequestId, (*_requestsVect)[baseRequestId], isEntry);
+        updateUnfulfilledSubrequest(baseRequestId, isEntry, true);
+    } else {
+        //If no active vehicle insertion worked, do best insertion on a new vehicle with the first subrequest (supposedly it's the most advantageous)
+        DEBUG_MSG("CREATE VEHICLE");
+        updateSubRequest(baseRequestId, accessSubRequestsList[0], isEntry);
+        _route->insertRequestInNewVehicle(_route->getEntrySubRequestOrigin(baseRequestId));
+    }
+
     return getSubrequest(baseRequestId, isEntry);
 }
 
@@ -236,3 +243,19 @@ const Request & SimpleModularHeuristic::insertBestTransitExitsInRoute(const Requ
     std::vector<TransitAccess> exitAccessList = getBestTransitExitsList(baseRequestId);
     return insertBestTransitAccessInRoute(baseRequest, exitAccessList, baseRequestId, false);
 }
+
+void SimpleModularHeuristic::updateUnfulfilledSubrequest(size_t baseRequestId, bool isEntry, bool value) {
+    if(isEntry) {
+        _unfulfilledTransitEntry[baseRequestId] = value;
+    } else {
+        _unfulfilledTransitExit[baseRequestId] = value;
+    }
+}
+
+const std::vector<bool> &SimpleModularHeuristic::getUnfulfilledTransitExit() const {
+    return _unfulfilledTransitExit;
+}
+
+const std::vector<bool> &SimpleModularHeuristic::getUnfulfilledTransitEntry() const {
+    return _unfulfilledTransitEntry;
+}
diff --git a/src/algorithm/Multimodal/Heuristics/SimpleModularHeuristic.h b/src/algorithm/Multimodal/Heuristics/SimpleModularHeuristic.h
index 459d0fe..8f64f7c 100644
--- a/src/algorithm/Multimodal/Heuristics/SimpleModularHeuristic.h
+++ b/src/algorithm/Multimodal/Heuristics/SimpleModularHeuristic.h
@@ -23,28 +23,22 @@
 #endif
 
 class SimpleModularHeuristic {
-public:
-    struct ScoredTransitAccess : public TransitAccess {
-        double score{DBL_MAX};
-        explicit ScoredTransitAccess(const TransitAccess& access, double scr) : TransitAccess(access), score(scr) {}
-    };
 private:
     const Graph* _graph{nullptr};
     SAEVRoute* _route{nullptr};
     std::vector<Request>* _requestsVect{nullptr};
     size_t _nbBaseRquests;
+    std::vector<bool> _unfulfilledTransitEntry;
+    std::vector<bool> _unfulfilledTransitExit;
 
     //Add friend test classes to test inner workings without making the whole API public
     FRIEND_TEST(MultimodalInsertionHeuristicDebug, DebugBaseInstance);
     FRIEND_TEST(MultimodalInsertionHeuristicDebug, DebugInstanceAlain);
 
-
-    using transit_order_function = std::function<bool(ScoredTransitAccess, ScoredTransitAccess)>;
-
 //Public interface to interact with the modular heuristic
 public:
     SimpleModularHeuristic(const Graph *graph, SAEVRoute *route, std::vector<Request>* requestsVect) : _graph(graph), _route(route),
-    _requestsVect(requestsVect), _nbBaseRquests(requestsVect->size()) {}
+    _requestsVect(requestsVect), _nbBaseRquests(requestsVect->size()), _unfulfilledTransitEntry(_nbBaseRquests), _unfulfilledTransitExit(_nbBaseRquests) {}
 
     void multimodalRequestsInsertion(const std::vector<Request>& requestsToInsert);
 
@@ -52,6 +46,17 @@ public:
         return _nbBaseRquests;
     }
 
+    const std::vector<bool> &getUnfulfilledTransitExit() const;
+
+    const std::vector<bool> &getUnfulfilledTransitEntry() const;
+
+    //Define useful struct to order transit access objects
+    struct ScoredTransitAccess : public TransitAccess {
+        double score{DBL_MAX};
+        explicit ScoredTransitAccess(const TransitAccess& access, double scr) : TransitAccess(access), score(scr) {}
+    };
+    using transit_order_function = std::function<bool(ScoredTransitAccess, ScoredTransitAccess)>;
+
 //Private members for heuristic internal functions we don't wish to see overriden
 private:
 
@@ -171,6 +176,8 @@ protected:
 
     [[nodiscard]] double getTransitExitScore(size_t transitExitNodeIndex, size_t requestDestinationNodeIndex,
                                uint transitExitTimestamp) const;
+
+    void updateUnfulfilledSubrequest(size_t baseRequestId, bool isEntry, bool value);
 };
 
 
-- 
GitLab


From bc899050661dd1d301fd72b87b1644977a698186 Mon Sep 17 00:00:00 2001
From: Romain BERNARD <romain.bernard@uca.fr>
Date: Thu, 12 Sep 2024 17:49:10 +0200
Subject: [PATCH 292/327] add prefix to debug messages

---
 src/ShortestPath/Transit/TransitShortestPathPrecompute.cpp   | 2 +-
 src/ShortestPath/Transit/TransitStateContainer.h             | 2 +-
 src/algorithm/DARP/Heuristics/BestInsertionHeuristic.cpp     | 2 +-
 src/algorithm/Multimodal/Heuristics/SimpleModularHeuristic.h | 2 +-
 src/routes/vehicle/SAEVRoute.cpp                             | 2 +-
 5 files changed, 5 insertions(+), 5 deletions(-)

diff --git a/src/ShortestPath/Transit/TransitShortestPathPrecompute.cpp b/src/ShortestPath/Transit/TransitShortestPathPrecompute.cpp
index 5f592fb..b7087e2 100644
--- a/src/ShortestPath/Transit/TransitShortestPathPrecompute.cpp
+++ b/src/ShortestPath/Transit/TransitShortestPathPrecompute.cpp
@@ -8,7 +8,7 @@
 
 #ifdef DEBUG_TRANSIT_PRECOMPUTE
 #include <iostream>
-#define DEBUG_MSG(str) do { std::cout << str << std::endl; } while( false )
+#define DEBUG_MSG(str) do { std::cout << "[TRANSIT] " << str << std::endl; } while( false )
 #else
 #define DEBUG_MSG(str) do { } while ( false )
 #endif
diff --git a/src/ShortestPath/Transit/TransitStateContainer.h b/src/ShortestPath/Transit/TransitStateContainer.h
index 1cfb2a1..c503063 100644
--- a/src/ShortestPath/Transit/TransitStateContainer.h
+++ b/src/ShortestPath/Transit/TransitStateContainer.h
@@ -10,7 +10,7 @@
 
 #ifdef DEBUG_TRANSIT_PRECOMPUTE
 #include <iostream>
-#define DEBUG_MSG(str) do { std::cout << str << std::endl; } while( false )
+#define DEBUG_MSG(str) do { std::cout << "[TRANSIT] " << str << std::endl; } while( false )
 #else
 #define DEBUG_MSG(str) do { } while ( false )
 #endif
diff --git a/src/algorithm/DARP/Heuristics/BestInsertionHeuristic.cpp b/src/algorithm/DARP/Heuristics/BestInsertionHeuristic.cpp
index 38b52b4..378bf99 100644
--- a/src/algorithm/DARP/Heuristics/BestInsertionHeuristic.cpp
+++ b/src/algorithm/DARP/Heuristics/BestInsertionHeuristic.cpp
@@ -6,7 +6,7 @@
 
 #ifdef DEBUG_BEST_INSERTION_HEURISTIC
 #include <iostream>
-#define DEBUG_MSG(str) do { std::cout << str << std::endl; } while( false )
+#define DEBUG_MSG(str) do { std::cout << "[BEST INSERTION] " << str << std::endl; } while( false )
 #else
 #define DEBUG_MSG(str) do { } while ( false )
 #endif
diff --git a/src/algorithm/Multimodal/Heuristics/SimpleModularHeuristic.h b/src/algorithm/Multimodal/Heuristics/SimpleModularHeuristic.h
index 8f64f7c..57848ad 100644
--- a/src/algorithm/Multimodal/Heuristics/SimpleModularHeuristic.h
+++ b/src/algorithm/Multimodal/Heuristics/SimpleModularHeuristic.h
@@ -17,7 +17,7 @@
 
 #ifdef DEBUG_MULTIMODAL_HEURISTIC
 #include <iostream>
-#define DEBUG_MSG(str) do { std::cout << str << std::endl; } while( false )
+#define DEBUG_MSG(str) do { std::cout << "[SMH] " << str << std::endl; } while( false )
 #else
 #define DEBUG_MSG(str) do { } while ( false )
 #endif
diff --git a/src/routes/vehicle/SAEVRoute.cpp b/src/routes/vehicle/SAEVRoute.cpp
index dd08b69..ccdd0b1 100644
--- a/src/routes/vehicle/SAEVRoute.cpp
+++ b/src/routes/vehicle/SAEVRoute.cpp
@@ -9,7 +9,7 @@
 
 #ifdef DEBUG_CONSTRAINT_PROPAGATION
 #include <iostream>
-#define DEBUG_MSG(str) do { std::cout << str << std::endl; } while( false )
+#define DEBUG_MSG(str) do { std::cout << "[PROPAG] " << str << std::endl; } while( false )
 #else
 #define DEBUG_MSG(str) do { } while ( false )
 #endif
-- 
GitLab


From 57eed9e3862be671d211442c4305c1a4352c1827 Mon Sep 17 00:00:00 2001
From: Romain BERNARD <romain.bernard@uca.fr>
Date: Thu, 12 Sep 2024 18:41:59 +0200
Subject: [PATCH 293/327] add isEntryFulfilled method TODO: handle diverse
 fail/unfulfilled cases wrt list size, isEntry etc

---
 src/algorithm/DARP/Heuristics/BestInsertionHeuristic.cpp    | 2 +-
 .../Multimodal/Heuristics/SimpleModularHeuristic.cpp        | 6 +++++-
 .../Multimodal/Heuristics/SimpleModularHeuristic.h          | 2 ++
 3 files changed, 8 insertions(+), 2 deletions(-)

diff --git a/src/algorithm/DARP/Heuristics/BestInsertionHeuristic.cpp b/src/algorithm/DARP/Heuristics/BestInsertionHeuristic.cpp
index 378bf99..c067ef8 100644
--- a/src/algorithm/DARP/Heuristics/BestInsertionHeuristic.cpp
+++ b/src/algorithm/DARP/Heuristics/BestInsertionHeuristic.cpp
@@ -43,7 +43,7 @@ size_t BestInsertionHeuristic::doBestRequestInsertionForRoute(SAEVKeyPoint &requ
     size_t vehicleId = 0;
     bool insertionSuccess{false};
     //Iteratively try inserting in every active vehicle and the first inactive vehicle
-    do {
+    do { //TODO: improve this to mutualize best insertions amongst best vehicles ?
         insertionSuccess = tryVehicleBestInsertion(requestKp, vehicleId, route).success();
     } while(!insertionSuccess && ++vehicleId <= route.getLastActiveVehicleId() + 1);
 
diff --git a/src/algorithm/Multimodal/Heuristics/SimpleModularHeuristic.cpp b/src/algorithm/Multimodal/Heuristics/SimpleModularHeuristic.cpp
index b7a3468..e42e56f 100644
--- a/src/algorithm/Multimodal/Heuristics/SimpleModularHeuristic.cpp
+++ b/src/algorithm/Multimodal/Heuristics/SimpleModularHeuristic.cpp
@@ -127,7 +127,7 @@ SimpleModularHeuristic::insertBestTransitAccessInRoute(const std::vector<Request
         //If no active vehicle insertion worked, do best insertion on a new vehicle with the first subrequest (supposedly it's the most advantageous)
         DEBUG_MSG("CREATE VEHICLE");
         updateSubRequest(baseRequestId, accessSubRequestsList[0], isEntry);
-        _route->insertRequestInNewVehicle(_route->getEntrySubRequestOrigin(baseRequestId));
+        _route->insertRequestInNewVehicle(_route->getExitSubRequestOrigin(baseRequestId));
     }
 
     return getSubrequest(baseRequestId, isEntry);
@@ -259,3 +259,7 @@ const std::vector<bool> &SimpleModularHeuristic::getUnfulfilledTransitExit() con
 const std::vector<bool> &SimpleModularHeuristic::getUnfulfilledTransitEntry() const {
     return _unfulfilledTransitEntry;
 }
+
+bool SimpleModularHeuristic::isEntryFulfilled(size_t baseRequestId) {
+    return !_unfulfilledTransitEntry[baseRequestId];
+}
diff --git a/src/algorithm/Multimodal/Heuristics/SimpleModularHeuristic.h b/src/algorithm/Multimodal/Heuristics/SimpleModularHeuristic.h
index 57848ad..e06ec5b 100644
--- a/src/algorithm/Multimodal/Heuristics/SimpleModularHeuristic.h
+++ b/src/algorithm/Multimodal/Heuristics/SimpleModularHeuristic.h
@@ -178,6 +178,8 @@ protected:
                                uint transitExitTimestamp) const;
 
     void updateUnfulfilledSubrequest(size_t baseRequestId, bool isEntry, bool value);
+
+    bool isEntryFulfilled(size_t baseRequestId);
 };
 
 
-- 
GitLab


From 2a1aa8c2488340952e9a2959aefe345649dfa6ee Mon Sep 17 00:00:00 2001
From: Romain BERNARD <romain.bernard@uca.fr>
Date: Fri, 13 Sep 2024 17:23:47 +0200
Subject: [PATCH 294/327] stop using base requests vector to save subrequests
 generated by the algorithm (it used to create multiple side effects wrt
 request pointers and how we access base/sub requests)

---
 .../Heuristics/SimpleModularHeuristic.cpp     | 31 +++++++++----------
 .../Heuristics/SimpleModularHeuristic.h       | 23 +++++++++-----
 2 files changed, 29 insertions(+), 25 deletions(-)

diff --git a/src/algorithm/Multimodal/Heuristics/SimpleModularHeuristic.cpp b/src/algorithm/Multimodal/Heuristics/SimpleModularHeuristic.cpp
index e42e56f..4a44088 100644
--- a/src/algorithm/Multimodal/Heuristics/SimpleModularHeuristic.cpp
+++ b/src/algorithm/Multimodal/Heuristics/SimpleModularHeuristic.cpp
@@ -150,28 +150,17 @@ void SimpleModularHeuristic::setRoute(SAEVRoute *route) {
 }
 
 void SimpleModularHeuristic::updateSubRequest(size_t requestId, const Request &request, bool isEntry) {
-    size_t subRequestIndex = getSubrequestIndex(requestId, isEntry);
-    if((_requestsVect->size() - 1) < subRequestIndex) {
-        _requestsVect->emplace_back(request);
-        assertm((_requestsVect->size() - 1) == subRequestIndex,"A request seems to have been missed or doesn't have any subrequest defined");
-    } else {
-        (*_requestsVect)[subRequestIndex] = request;
-    }
-
-    std::vector<Request>& requestVectRef = *_requestsVect;
-    _route->getEntrySubRequestOrigin(requestId).setRequest(&requestVectRef[subRequestIndex]);
-    _route->getEntrySubRequestDestination(requestId).setRequest(&requestVectRef[subRequestIndex]);
-}
-
-size_t SimpleModularHeuristic::getSubrequestIndex(size_t requestId, bool isEntry) const {
     if(isEntry)
-        return _nbBaseRquests + requestId;
+        _entrySubRequests[requestId] = request;
     else
-        return _nbBaseRquests*2 + requestId;
+        _exitSubRequests[requestId] = request;
+
+    _route->getEntrySubRequestOrigin(requestId).setRequest(&getSubrequest(requestId, isEntry));
+    _route->getEntrySubRequestDestination(requestId).setRequest(&getSubrequest(requestId, isEntry));
 }
 
 const Request& SimpleModularHeuristic::getSubrequest(size_t requestId, bool isEntry) {
-    return (*_requestsVect)[getSubrequestIndex(requestId, isEntry)];
+    return isEntry ? _entrySubRequests[requestId] : _exitSubRequests[requestId];
 }
 
 double SimpleModularHeuristic::getTransitExitScore(const Request &baseRequest, const TransitAccess &exitData) const {
@@ -263,3 +252,11 @@ const std::vector<bool> &SimpleModularHeuristic::getUnfulfilledTransitEntry() co
 bool SimpleModularHeuristic::isEntryFulfilled(size_t baseRequestId) {
     return !_unfulfilledTransitEntry[baseRequestId];
 }
+
+const std::vector<Request> &SimpleModularHeuristic::getEntrySubRequests() const {
+    return _entrySubRequests;
+}
+
+const std::vector<Request> &SimpleModularHeuristic::getExitSubRequests() const {
+    return _exitSubRequests;
+}
diff --git a/src/algorithm/Multimodal/Heuristics/SimpleModularHeuristic.h b/src/algorithm/Multimodal/Heuristics/SimpleModularHeuristic.h
index e06ec5b..065dcc2 100644
--- a/src/algorithm/Multimodal/Heuristics/SimpleModularHeuristic.h
+++ b/src/algorithm/Multimodal/Heuristics/SimpleModularHeuristic.h
@@ -24,10 +24,14 @@
 
 class SimpleModularHeuristic {
 private:
+    //Exterior members
     const Graph* _graph{nullptr};
-    SAEVRoute* _route{nullptr};
-    std::vector<Request>* _requestsVect{nullptr};
-    size_t _nbBaseRquests;
+    const std::vector<Request>* _requestsVect{nullptr};
+    SAEVRoute* _route{nullptr}; //_route is a pointer here to decorrelate the route from the algorithm and facilitate using multiple modules on the same route
+
+    std::vector<Request> _entrySubRequests;
+    std::vector<Request> _exitSubRequests;
+
     std::vector<bool> _unfulfilledTransitEntry;
     std::vector<bool> _unfulfilledTransitExit;
 
@@ -37,18 +41,21 @@ private:
 
 //Public interface to interact with the modular heuristic
 public:
-    SimpleModularHeuristic(const Graph *graph, SAEVRoute *route, std::vector<Request>* requestsVect) : _graph(graph), _route(route),
-    _requestsVect(requestsVect), _nbBaseRquests(requestsVect->size()), _unfulfilledTransitEntry(_nbBaseRquests), _unfulfilledTransitExit(_nbBaseRquests) {}
+    SimpleModularHeuristic(const Graph *graph, SAEVRoute *route, std::vector<Request> const* requestsVect) : _graph(graph), _requestsVect(requestsVect),
+    _route(route), _entrySubRequests(requestsVect->size()), _exitSubRequests(requestsVect->size()),
+    _unfulfilledTransitEntry(requestsVect->size()), _unfulfilledTransitExit(requestsVect->size()) {}
 
     void multimodalRequestsInsertion(const std::vector<Request>& requestsToInsert);
 
     [[nodiscard]] size_t getNbBaseRquests() const {
-        return _nbBaseRquests;
+        return _requestsVect->size();
     }
 
-    const std::vector<bool> &getUnfulfilledTransitExit() const;
+    [[nodiscard]] const std::vector<Request> &getEntrySubRequests() const;
+    [[nodiscard]] const std::vector<Request> &getExitSubRequests() const;
 
-    const std::vector<bool> &getUnfulfilledTransitEntry() const;
+    [[nodiscard]] const std::vector<bool> &getUnfulfilledTransitEntry() const;
+    [[nodiscard]] const std::vector<bool> &getUnfulfilledTransitExit() const;
 
     //Define useful struct to order transit access objects
     struct ScoredTransitAccess : public TransitAccess {
-- 
GitLab


From 137d78b5992d393e7a6dca936e1a0bdfdf4ae154 Mon Sep 17 00:00:00 2001
From: Romain BERNARD <romain.bernard@uca.fr>
Date: Tue, 17 Sep 2024 16:57:46 +0200
Subject: [PATCH 295/327] separate bound propagation method from insertion
 method to allow propagating changes from a given bound queue

---
 src/routes/vehicle/SAEVRoute.cpp | 16 ++++++++++++----
 src/routes/vehicle/SAEVRoute.h   | 12 ++++++++++++
 2 files changed, 24 insertions(+), 4 deletions(-)

diff --git a/src/routes/vehicle/SAEVRoute.cpp b/src/routes/vehicle/SAEVRoute.cpp
index ccdd0b1..b3053fc 100644
--- a/src/routes/vehicle/SAEVRoute.cpp
+++ b/src/routes/vehicle/SAEVRoute.cpp
@@ -218,14 +218,15 @@ SAEVRoute::doNeighbouringTWChecks(const SAEVKeyPoint &originKP, const SAEVKeyPoi
 SAEVRouteChangelist SAEVRoute::insertRequestWithPropagation(SAEVKeyPoint &originKP, SAEVKeyPoint * originRequestPredecessorKP,
                                                             SAEVKeyPoint * destinationRequestPredecessorKP) {
     //Init changelist and detour score
-    SAEVRouteChangelist changelist{this, &originKP, originRequestPredecessorKP, destinationRequestPredecessorKP, SAEVRouteChangelist::InsertionStatus::FAILURE_MIN};
+    SAEVRouteChangelist changelist{this, &originKP, originRequestPredecessorKP, destinationRequestPredecessorKP,
+                                   SAEVRouteChangelist::InsertionStatus::FAILURE_MIN};
     double detourScore = getDetourScore(originKP, originRequestPredecessorKP, destinationRequestPredecessorKP);
     //Properly insert the request to facilitate constraint propagation
     insertRequest(originKP, originRequestPredecessorKP, destinationRequestPredecessorKP);
 
     //Initialize bound propagation signal queue (each item signals a modification done on one of a KeyPoint
-    std::queue<std::pair<Bound, SAEVKeyPoint *>> boundPropagationQueue{};
-    SAEVKeyPoint * destinationKP = originKP.getCounterpart();
+    std::queue<std::pair<int, SAEVKeyPoint *>> boundPropagationQueue{};
+    SAEVKeyPoint *destinationKP = originKP.getCounterpart();
     boundPropagationQueue.emplace(Min, originKP.getPredecessor());
     boundPropagationQueue.emplace(Max, originKP.getSuccessor());
     boundPropagationQueue.emplace(Min, destinationKP->getPredecessor());
@@ -235,6 +236,14 @@ SAEVRouteChangelist SAEVRoute::insertRequestWithPropagation(SAEVKeyPoint &origin
     boundPropagationQueue.emplace(Min, destinationKP);
     boundPropagationQueue.emplace(Max, destinationKP);
 
+    doBoundPropagation(boundPropagationQueue, changelist);
+    changelist.setScore(detourScore);
+    return changelist;
+}
+
+
+SAEVRouteChangelist SAEVRoute::doBoundPropagation(std::queue<std::pair<int, SAEVKeyPoint *>> &boundPropagationQueue,
+                                                  SAEVRouteChangelist &changelist) {
     //Pre-init variables used in the loop
     int oldValue;
     int newValue;
@@ -311,7 +320,6 @@ SAEVRouteChangelist SAEVRoute::insertRequestWithPropagation(SAEVKeyPoint &origin
     }
 
     changelist.setStatus(SAEVRouteChangelist::InsertionStatus::SUCCESS);
-    changelist.setScore(detourScore);
     return changelist;
 }
 
diff --git a/src/routes/vehicle/SAEVRoute.h b/src/routes/vehicle/SAEVRoute.h
index f9ce97a..18016d8 100644
--- a/src/routes/vehicle/SAEVRoute.h
+++ b/src/routes/vehicle/SAEVRoute.h
@@ -124,6 +124,18 @@ public:
      */
     SAEVRouteChangelist insertRequestWithPropagation(SAEVKeyPoint &originKP, SAEVKeyPoint * originRequestPredecessorKP, SAEVKeyPoint * destinationRequestPredecessorKP);
 
+    /**
+     * Executes the bound propagation algorithm, starting from the given bound propagation queue.
+     * Each item in the queue references which bound (Min/Max) and what key point was affected, and from there we verify bounds for each predecessor/successor
+     *
+     * If the bounds become infeasible (min > max), then the propagation stops with a changelist with score= +Infinity and changes will be immediately reverted.
+     * Otherwise, it's the responsibility of this method's callers to revert changes if wanted (or to defer this responsibility to its caller)
+     *
+     * @param boundPropagationQueue a (Bound/Keypoint) pair queue giving a list of starting points for propagation. Typically when inserting a key point, the queue contains two items (one for each bound)
+     * @return A change list with every min/max bound change made during the insert procedure and a score estimating insertion quality (lower is better)
+     */ // FIXME: not a fan of using int instead of the Bound enum here, but I can't forward-declare it since it's part of SAEVRouteChange
+    SAEVRouteChangelist doBoundPropagation(std::queue<std::pair<int, SAEVKeyPoint *>> &boundPropagationQueue,
+                                           SAEVRouteChangelist &changelist);
     /**
      * Returns a score value equivalent to the detour implied by insertion of a request after the two given key point indexes.
      * The specific case of origin/destination being inserted one after another is taken into account
-- 
GitLab


From f9fff3f9d860df808a4ce8277fa31f958ba90020 Mon Sep 17 00:00:00 2001
From: Romain BERNARD <romain.bernard@uca.fr>
Date: Tue, 17 Sep 2024 17:05:16 +0200
Subject: [PATCH 296/327] null safety in change lists

---
 src/routes/vehicle/propagation/SAEVRouteChangelist.cpp | 6 ++++--
 1 file changed, 4 insertions(+), 2 deletions(-)

diff --git a/src/routes/vehicle/propagation/SAEVRouteChangelist.cpp b/src/routes/vehicle/propagation/SAEVRouteChangelist.cpp
index d2e0885..535941b 100644
--- a/src/routes/vehicle/propagation/SAEVRouteChangelist.cpp
+++ b/src/routes/vehicle/propagation/SAEVRouteChangelist.cpp
@@ -21,7 +21,8 @@ void SAEVRouteChangelist::emplace_back(SAEVKeyPoint &kp, Bound bound, uint value
 }
 
 void SAEVRouteChangelist::applyChanges() {
-    if(_status < InsertionStatus::FAILURE_PRECONDITION_TW) {
+    if(_requestOriginKeyPoint != nullptr && _originPredecessorKP != nullptr
+    && _destinationPredecessorKP != nullptr && _status < InsertionStatus::FAILURE_PRECONDITION_TW) {
         _routePtr->insertRequest(*_requestOriginKeyPoint, _originPredecessorKP, _destinationPredecessorKP);
     }
     for(SAEVRouteChange change : _changelist) {
@@ -31,7 +32,8 @@ void SAEVRouteChangelist::applyChanges() {
 }
 
 void SAEVRouteChangelist::revertChanges() {
-    if(_status < InsertionStatus::FAILURE_PRECONDITION_TW) {
+    if(_requestOriginKeyPoint != nullptr && _originPredecessorKP != nullptr
+    && _destinationPredecessorKP != nullptr && _status < InsertionStatus::FAILURE_PRECONDITION_TW) {
         _routePtr->removeRequest(*_requestOriginKeyPoint);
     }
     for(SAEVRouteChange change : _changelist) {
-- 
GitLab


From d59d501d4c87e8d87f1fcc6f2669cf355a641492 Mon Sep 17 00:00:00 2001
From: Romain BERNARD <romain.bernard@uca.fr>
Date: Tue, 17 Sep 2024 17:32:08 +0200
Subject: [PATCH 297/327] add removal with propagation functions, resetting
 bounds and recomputing propagation

---
 src/routes/vehicle/SAEVKeyPoint.cpp | 10 +++++++
 src/routes/vehicle/SAEVKeyPoint.h   |  5 ++++
 src/routes/vehicle/SAEVRoute.cpp    | 42 ++++++++++++++++++++++++++++-
 src/routes/vehicle/SAEVRoute.h      | 25 ++++++++++++++++-
 4 files changed, 80 insertions(+), 2 deletions(-)

diff --git a/src/routes/vehicle/SAEVKeyPoint.cpp b/src/routes/vehicle/SAEVKeyPoint.cpp
index ccdbc68..9094b70 100644
--- a/src/routes/vehicle/SAEVKeyPoint.cpp
+++ b/src/routes/vehicle/SAEVKeyPoint.cpp
@@ -126,3 +126,13 @@ std::string SAEVKeyPoint::to_string() const {
     return "(nodeIdx=" + std::to_string(getNodeIndex()) + ", Type=" + nodeType +
     + "TW=[" + std::to_string(getMinTw()) + ";" + std::to_string(getMaxTw()) + "])";
 }
+
+void SAEVKeyPoint::resetBounds() {
+    if(isOrigin()) {
+        _minTW = _requestPointer->getMinDepartureTw();
+        _maxTW = _requestPointer->getMaxDepartureTw();
+    } else {
+        _minTW = _requestPointer->getMinArrivalTw();
+        _maxTW = _requestPointer->getMaxArrivalTw();
+    }
+}
diff --git a/src/routes/vehicle/SAEVKeyPoint.h b/src/routes/vehicle/SAEVKeyPoint.h
index 9756957..f8bcaf7 100644
--- a/src/routes/vehicle/SAEVKeyPoint.h
+++ b/src/routes/vehicle/SAEVKeyPoint.h
@@ -85,6 +85,11 @@ public:
     [[nodiscard]] int getDeltaTime() const;
 
     [[nodiscard]] std::string to_string() const override;
+
+    /**
+     * Resets the keypoint's min/max bounds to the linked request's original bounds
+     */
+    void resetBounds();
 };
 #include "../../instance/requests/Request.h"
 
diff --git a/src/routes/vehicle/SAEVRoute.cpp b/src/routes/vehicle/SAEVRoute.cpp
index b3053fc..818a394 100644
--- a/src/routes/vehicle/SAEVRoute.cpp
+++ b/src/routes/vehicle/SAEVRoute.cpp
@@ -324,7 +324,7 @@ SAEVRouteChangelist SAEVRoute::doBoundPropagation(std::queue<std::pair<int, SAEV
 }
 
 double SAEVRoute::getDetourScore(const SAEVKeyPoint &originKP, const SAEVKeyPoint * originRequestPredecessorKP,
-                                 const SAEVKeyPoint * destinationRequestPredecessorKP) {
+                                 const SAEVKeyPoint * destinationRequestPredecessorKP) const {
     double score;
     const SAEVKeyPoint* destinationKP = originKP.getCounterpart();
     const SAEVKeyPoint* originSuccKP = originRequestPredecessorKP->getSuccessor();
@@ -525,3 +525,43 @@ std::string SAEVRoute::to_string() {
     return res;
 }
 
+SAEVRouteChangelist SAEVRoute::removeRequestWithPropagation(SAEVKeyPoint &originKP) {
+    //save ref to part of the route we have to update before removing
+    //FIXME : best would be to link to depot/vehicle to directly start from the origin depot instead of having two whiles
+    SAEVKeyPoint const* originPredKp = originKP.getPredecessor();
+    assertm(originPredKp != nullptr, "Trying to remove a key point that's not in any route");
+    //Actually remove request
+    removeRequest(originKP);
+
+    std::queue<std::pair<int, SAEVKeyPoint*>> propagationQueue;
+    //Now iterate over predecessor KPs to reset their bounds and add to propagation queue
+    SAEVKeyPoint* currentKP = originPredKp->getPredecessor();
+    while (currentKP != nullptr) {
+        currentKP->resetBounds();
+        propagationQueue.emplace(Min, currentKP);
+        propagationQueue.emplace(Max, currentKP);
+        currentKP = currentKP->getPredecessor();
+    }
+    //Do the same over successor KPs to be fully done with the
+    currentKP = originPredKp->getSuccessor();
+    while (currentKP != nullptr) {
+        currentKP->resetBounds();
+        propagationQueue.emplace(Min, currentKP);
+        propagationQueue.emplace(Max, currentKP);
+        currentKP = currentKP->getSuccessor();
+    }
+
+    SAEVRouteChangelist changelist{this, nullptr};
+    doBoundPropagation(propagationQueue, changelist);
+    return changelist;
+}
+
+SAEVRouteChangelist SAEVRoute::removeRequestWithPropagation(size_t requestId, bool isEntry) {
+    SAEVKeyPoint& originKeyPoint = isEntry ? getEntrySubRequestOrigin(requestId) : getExitSubRequestOrigin(requestId);
+    return removeRequestWithPropagation(originKeyPoint);
+}
+
+SAEVRouteChangelist SAEVRoute::removeRequestWithPropagation(size_t requestId) {
+    return removeRequestWithPropagation(getRequestOrigin(requestId));
+}
+
diff --git a/src/routes/vehicle/SAEVRoute.h b/src/routes/vehicle/SAEVRoute.h
index 18016d8..3f08d5b 100644
--- a/src/routes/vehicle/SAEVRoute.h
+++ b/src/routes/vehicle/SAEVRoute.h
@@ -60,6 +60,29 @@ public:
      */
     void removeRequest(SAEVKeyPoint &originKp);
 
+    /**
+     * Removes a given base request from the route and does a complete reset and recomputing of bound propagations
+     * By nature of our propagation making bounds only smaller and no simple rule existing to make our bounds larger after removal,
+     * this method is highly inefficient computationally. A new propagation method or even modelling would be necessary to make it faster
+     * @param requestId a base request ID allowing us to find the origin keypoint to use as removal basis
+     */
+    SAEVRouteChangelist removeRequestWithPropagation(size_t requestId);
+    /**
+     * Removes a given entry/exit sub-request from the route and does a complete reset and recomputing of bound propagations
+     * By nature of our propagation making bounds only smaller and no simple rule existing to make our bounds larger after removal,
+     * this method is highly inefficient computationally. A new propagation method or even modelling would be necessary to make it faster
+     * @param requestId a base request ID allowing us to find the entry/exit subrequest to delete
+     * @param isEntry true iff the subrequest to delete
+     */
+    SAEVRouteChangelist removeRequestWithPropagation(size_t requestId, bool isEntry);
+    /**
+     * Removes a given request from the route and does a complete reset and recomputing of bound propagations
+     * By nature of our propagation making bounds only smaller and no simple rule existing to make our bounds larger after removal,
+     * this method is highly inefficient computationally. A new propagation method or even modelling would be necessary to make it faster
+     * @param originKP pointer to the origin key point of a given request to remove
+     */
+    SAEVRouteChangelist removeRequestWithPropagation(SAEVKeyPoint &originKP);
+
     /**
      * Updates weight in-between request's Origin/Destination (both included) to account for the given request's weight
      * ⚠️ Execute this function *after* adding the request to the route, as it assumes the request is part of the route
@@ -145,7 +168,7 @@ public:
      * @param destinationRequestPredecessorKP Identifier/index in the route key point vector for the request origin or destination that will precede our request's destination in the route
      * @return
      */
-    double getDetourScore(const SAEVKeyPoint &originKP, const SAEVKeyPoint * originRequestPredecessorKP, const SAEVKeyPoint * destinationRequestPredecessorKP);
+    double getDetourScore(const SAEVKeyPoint &originKP, const SAEVKeyPoint * originRequestPredecessorKP, const SAEVKeyPoint * destinationRequestPredecessorKP) const;
 
     BestInsertionQueue getBestInsertionsQueue(size_t requestId, size_t vehicleId);
     BestInsertionQueue getBestInsertionsQueue(SAEVKeyPoint &originKP, size_t vehicleId);
-- 
GitLab


From 39fd322ebbd16398a6f18d647323ec9747eac489 Mon Sep 17 00:00:00 2001
From: Romain BERNARD <romain.bernard@uca.fr>
Date: Tue, 17 Sep 2024 18:15:56 +0200
Subject: [PATCH 298/327] refactor move shortest path algorithms to the
 algorithm folder

---
 CMakeLists.txt                                | 40 +++++++++----------
 .../ShortestPath/ShortestPath.h               |  0
 .../Transit/TransitAlgorithmState.cpp         |  0
 .../Transit/TransitAlgorithmState.h           |  4 +-
 .../Transit/TransitShortestPath.h             |  2 +-
 .../Transit/TransitShortestPathContainer.cpp  |  0
 .../Transit/TransitShortestPathContainer.h    |  0
 .../Transit/TransitShortestPathPrecompute.cpp |  0
 .../Transit/TransitShortestPathPrecompute.h   |  2 +-
 .../Transit/TransitStateContainer.h           |  0
 .../Vehicle/ClosestDestinationsContainer.h    |  0
 .../Vehicle/MatrixShortestPathContainer.h     |  2 +-
 .../ShortestPath/Vehicle/VehicleDestination.h |  0
 .../ShortestPath/Vehicle/VehiclePathState.h   |  0
 .../Vehicle/VehicleShortestPath.h             |  4 +-
 .../VehicleShortestPathCalculation.cpp        |  2 +-
 .../Vehicle/VehicleShortestPathCalculation.h  |  2 +-
 test/CMakeLists.txt                           | 34 ++++++++--------
 test/src/BestInsertionHeuristicDebug.cpp      |  4 +-
 test/src/ConstraintPropagationDebug.cpp       |  6 +--
 test/src/TransitPreprocessDebug.cpp           |  4 +-
 21 files changed, 53 insertions(+), 53 deletions(-)
 rename src/{ => algorithm}/ShortestPath/ShortestPath.h (100%)
 rename src/{ => algorithm}/ShortestPath/Transit/TransitAlgorithmState.cpp (100%)
 rename src/{ => algorithm}/ShortestPath/Transit/TransitAlgorithmState.h (98%)
 rename src/{ => algorithm}/ShortestPath/Transit/TransitShortestPath.h (97%)
 rename src/{ => algorithm}/ShortestPath/Transit/TransitShortestPathContainer.cpp (100%)
 rename src/{ => algorithm}/ShortestPath/Transit/TransitShortestPathContainer.h (100%)
 rename src/{ => algorithm}/ShortestPath/Transit/TransitShortestPathPrecompute.cpp (100%)
 rename src/{ => algorithm}/ShortestPath/Transit/TransitShortestPathPrecompute.h (90%)
 rename src/{ => algorithm}/ShortestPath/Transit/TransitStateContainer.h (100%)
 rename src/{ => algorithm}/ShortestPath/Vehicle/ClosestDestinationsContainer.h (100%)
 rename src/{ => algorithm}/ShortestPath/Vehicle/MatrixShortestPathContainer.h (98%)
 rename src/{ => algorithm}/ShortestPath/Vehicle/VehicleDestination.h (100%)
 rename src/{ => algorithm}/ShortestPath/Vehicle/VehiclePathState.h (100%)
 rename src/{ => algorithm}/ShortestPath/Vehicle/VehicleShortestPath.h (93%)
 rename src/{ => algorithm}/ShortestPath/Vehicle/VehicleShortestPathCalculation.cpp (99%)
 rename src/{ => algorithm}/ShortestPath/Vehicle/VehicleShortestPathCalculation.h (98%)

diff --git a/CMakeLists.txt b/CMakeLists.txt
index fee3d65..3d5213d 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -29,14 +29,14 @@ add_executable(GreedyAlgorithm
         src/instance/graph/LineStop.h
         src/services/DatFile/DATRow.h
         src/utils/SearchAlgorithms.h
-        src/ShortestPath/ShortestPath.h
-        src/ShortestPath/Transit/TransitShortestPath.h
-        src/ShortestPath/Transit/TransitShortestPathPrecompute.cpp
-        src/ShortestPath/Transit/TransitShortestPathPrecompute.h
-        src/ShortestPath/Transit/TransitAlgorithmState.cpp
-        src/ShortestPath/Transit/TransitAlgorithmState.h
-        src/ShortestPath/Transit/TransitShortestPathContainer.cpp
-        src/ShortestPath/Transit/TransitShortestPathContainer.h
+        src/algorithm/ShortestPath/ShortestPath.h
+        src/algorithm/ShortestPath/Transit/TransitShortestPath.h
+        src/algorithm/ShortestPath/Transit/TransitShortestPathPrecompute.cpp
+        src/algorithm/ShortestPath/Transit/TransitShortestPathPrecompute.h
+        src/algorithm/ShortestPath/Transit/TransitAlgorithmState.cpp
+        src/algorithm/ShortestPath/Transit/TransitAlgorithmState.h
+        src/algorithm/ShortestPath/Transit/TransitShortestPathContainer.cpp
+        src/algorithm/ShortestPath/Transit/TransitShortestPathContainer.h
         src/routes/requests/RequestRoute.cpp
         src/routes/requests/RequestRoute.h
         src/routes/vehicle/SAEVRoute.cpp
@@ -97,13 +97,13 @@ add_executable(RequestGenerator
         src/utils/Globals.h
         src/algorithm/Multimodal/Heuristics/SimpleModularHeuristic.cpp
         src/algorithm/Multimodal/Heuristics/SimpleModularHeuristic.h
-        src/ShortestPath/Vehicle/VehicleShortestPath.h
-        src/ShortestPath/Vehicle/VehiclePathState.h
-        src/ShortestPath/Vehicle/VehicleShortestPathCalculation.cpp
-        src/ShortestPath/Vehicle/VehicleShortestPathCalculation.h
-        src/ShortestPath/Vehicle/MatrixShortestPathContainer.h
-        src/ShortestPath/Vehicle/ClosestDestinationsContainer.h
-        src/ShortestPath/Vehicle/VehicleDestination.h
+        src/algorithm/ShortestPath/Vehicle/VehicleShortestPath.h
+        src/algorithm/ShortestPath/Vehicle/VehiclePathState.h
+        src/algorithm/ShortestPath/Vehicle/VehicleShortestPathCalculation.cpp
+        src/algorithm/ShortestPath/Vehicle/VehicleShortestPathCalculation.h
+        src/algorithm/ShortestPath/Vehicle/MatrixShortestPathContainer.h
+        src/algorithm/ShortestPath/Vehicle/ClosestDestinationsContainer.h
+        src/algorithm/ShortestPath/Vehicle/VehicleDestination.h
 )
 
 add_executable(GraphGeneration
@@ -129,11 +129,11 @@ add_executable(GraphGeneration
         src/algorithm/DARP/Heuristics/BestInsertionHeuristic.h
         src/algorithm/Multimodal/Heuristics/SimpleModularHeuristic.cpp
         src/algorithm/Multimodal/Heuristics/SimpleModularHeuristic.h
-        src/ShortestPath/Vehicle/VehicleShortestPath.h
-        src/ShortestPath/Vehicle/VehiclePathState.h
-        src/ShortestPath/Vehicle/VehicleShortestPathCalculation.cpp
-        src/ShortestPath/Vehicle/VehicleShortestPathCalculation.h
-        src/ShortestPath/Vehicle/MatrixShortestPathContainer.h
+        src/algorithm/ShortestPath/Vehicle/VehicleShortestPath.h
+        src/algorithm/ShortestPath/Vehicle/VehiclePathState.h
+        src/algorithm/ShortestPath/Vehicle/VehicleShortestPathCalculation.cpp
+        src/algorithm/ShortestPath/Vehicle/VehicleShortestPathCalculation.h
+        src/algorithm/ShortestPath/Vehicle/MatrixShortestPathContainer.h
         src/algorithm/Multimodal/Heuristics/TransitAccess.h
 )
 
diff --git a/src/ShortestPath/ShortestPath.h b/src/algorithm/ShortestPath/ShortestPath.h
similarity index 100%
rename from src/ShortestPath/ShortestPath.h
rename to src/algorithm/ShortestPath/ShortestPath.h
diff --git a/src/ShortestPath/Transit/TransitAlgorithmState.cpp b/src/algorithm/ShortestPath/Transit/TransitAlgorithmState.cpp
similarity index 100%
rename from src/ShortestPath/Transit/TransitAlgorithmState.cpp
rename to src/algorithm/ShortestPath/Transit/TransitAlgorithmState.cpp
diff --git a/src/ShortestPath/Transit/TransitAlgorithmState.h b/src/algorithm/ShortestPath/Transit/TransitAlgorithmState.h
similarity index 98%
rename from src/ShortestPath/Transit/TransitAlgorithmState.h
rename to src/algorithm/ShortestPath/Transit/TransitAlgorithmState.h
index d3a544e..6409af4 100644
--- a/src/ShortestPath/Transit/TransitAlgorithmState.h
+++ b/src/algorithm/ShortestPath/Transit/TransitAlgorithmState.h
@@ -8,8 +8,8 @@
 
 #include <array>
 #include <cstdint>
-#include "../../instance/graph/LineStop.h"
-#include "../../utils/Constants.h"
+#include "../../../instance/graph/LineStop.h"
+#include "../../../utils/Constants.h"
 
 class TransitAlgorithmState {
 private:
diff --git a/src/ShortestPath/Transit/TransitShortestPath.h b/src/algorithm/ShortestPath/Transit/TransitShortestPath.h
similarity index 97%
rename from src/ShortestPath/Transit/TransitShortestPath.h
rename to src/algorithm/ShortestPath/Transit/TransitShortestPath.h
index 067282d..fc3ebcd 100644
--- a/src/ShortestPath/Transit/TransitShortestPath.h
+++ b/src/algorithm/ShortestPath/Transit/TransitShortestPath.h
@@ -6,7 +6,7 @@
 #define GREEDYALGORITHM_TRANSITSHORTESTPATH_H
 
 #include "../ShortestPath.h"
-#include "../../instance/graph/LineStop.h"
+#include "../../../instance/graph/LineStop.h"
 #include "TransitAlgorithmState.h"
 
 class TransitShortestPath : public ShortestPath<std::reference_wrapper<const LineStop>> {
diff --git a/src/ShortestPath/Transit/TransitShortestPathContainer.cpp b/src/algorithm/ShortestPath/Transit/TransitShortestPathContainer.cpp
similarity index 100%
rename from src/ShortestPath/Transit/TransitShortestPathContainer.cpp
rename to src/algorithm/ShortestPath/Transit/TransitShortestPathContainer.cpp
diff --git a/src/ShortestPath/Transit/TransitShortestPathContainer.h b/src/algorithm/ShortestPath/Transit/TransitShortestPathContainer.h
similarity index 100%
rename from src/ShortestPath/Transit/TransitShortestPathContainer.h
rename to src/algorithm/ShortestPath/Transit/TransitShortestPathContainer.h
diff --git a/src/ShortestPath/Transit/TransitShortestPathPrecompute.cpp b/src/algorithm/ShortestPath/Transit/TransitShortestPathPrecompute.cpp
similarity index 100%
rename from src/ShortestPath/Transit/TransitShortestPathPrecompute.cpp
rename to src/algorithm/ShortestPath/Transit/TransitShortestPathPrecompute.cpp
diff --git a/src/ShortestPath/Transit/TransitShortestPathPrecompute.h b/src/algorithm/ShortestPath/Transit/TransitShortestPathPrecompute.h
similarity index 90%
rename from src/ShortestPath/Transit/TransitShortestPathPrecompute.h
rename to src/algorithm/ShortestPath/Transit/TransitShortestPathPrecompute.h
index f4e25e9..22d8ddc 100644
--- a/src/ShortestPath/Transit/TransitShortestPathPrecompute.h
+++ b/src/algorithm/ShortestPath/Transit/TransitShortestPathPrecompute.h
@@ -6,7 +6,7 @@
 #define GREEDYALGORITHM_TRANSITSHORTESTPATHPRECOMPUTE_H
 
 #include "TransitShortestPath.h"
-#include "../../instance/graph/Graph.h"
+#include "../../../instance/graph/Graph.h"
 #include "TransitStateContainer.h"
 
 class TransitShortestPathPrecompute {
diff --git a/src/ShortestPath/Transit/TransitStateContainer.h b/src/algorithm/ShortestPath/Transit/TransitStateContainer.h
similarity index 100%
rename from src/ShortestPath/Transit/TransitStateContainer.h
rename to src/algorithm/ShortestPath/Transit/TransitStateContainer.h
diff --git a/src/ShortestPath/Vehicle/ClosestDestinationsContainer.h b/src/algorithm/ShortestPath/Vehicle/ClosestDestinationsContainer.h
similarity index 100%
rename from src/ShortestPath/Vehicle/ClosestDestinationsContainer.h
rename to src/algorithm/ShortestPath/Vehicle/ClosestDestinationsContainer.h
diff --git a/src/ShortestPath/Vehicle/MatrixShortestPathContainer.h b/src/algorithm/ShortestPath/Vehicle/MatrixShortestPathContainer.h
similarity index 98%
rename from src/ShortestPath/Vehicle/MatrixShortestPathContainer.h
rename to src/algorithm/ShortestPath/Vehicle/MatrixShortestPathContainer.h
index ea12887..f31224d 100644
--- a/src/ShortestPath/Vehicle/MatrixShortestPathContainer.h
+++ b/src/algorithm/ShortestPath/Vehicle/MatrixShortestPathContainer.h
@@ -9,7 +9,7 @@
 #include <vector>
 #include <cstdint>
 #include <algorithm>
-#include "../../utils/Globals.h"
+#include "../../../utils/Globals.h"
 
 class MatrixShortestPathContainer {
 private:
diff --git a/src/ShortestPath/Vehicle/VehicleDestination.h b/src/algorithm/ShortestPath/Vehicle/VehicleDestination.h
similarity index 100%
rename from src/ShortestPath/Vehicle/VehicleDestination.h
rename to src/algorithm/ShortestPath/Vehicle/VehicleDestination.h
diff --git a/src/ShortestPath/Vehicle/VehiclePathState.h b/src/algorithm/ShortestPath/Vehicle/VehiclePathState.h
similarity index 100%
rename from src/ShortestPath/Vehicle/VehiclePathState.h
rename to src/algorithm/ShortestPath/Vehicle/VehiclePathState.h
diff --git a/src/ShortestPath/Vehicle/VehicleShortestPath.h b/src/algorithm/ShortestPath/Vehicle/VehicleShortestPath.h
similarity index 93%
rename from src/ShortestPath/Vehicle/VehicleShortestPath.h
rename to src/algorithm/ShortestPath/Vehicle/VehicleShortestPath.h
index fad038d..918664e 100644
--- a/src/ShortestPath/Vehicle/VehicleShortestPath.h
+++ b/src/algorithm/ShortestPath/Vehicle/VehicleShortestPath.h
@@ -7,8 +7,8 @@
 
 #include <compare>
 #include "../ShortestPath.h"
-#include "../../instance/graph/Node.h"
-#include "../../utils/Globals.h"
+#include "../../../instance/graph/Node.h"
+#include "../../../utils/Globals.h"
 
 class VehicleShortestPath : public ShortestPath<size_t> {
 private:
diff --git a/src/ShortestPath/Vehicle/VehicleShortestPathCalculation.cpp b/src/algorithm/ShortestPath/Vehicle/VehicleShortestPathCalculation.cpp
similarity index 99%
rename from src/ShortestPath/Vehicle/VehicleShortestPathCalculation.cpp
rename to src/algorithm/ShortestPath/Vehicle/VehicleShortestPathCalculation.cpp
index 2994844..d7507cb 100644
--- a/src/ShortestPath/Vehicle/VehicleShortestPathCalculation.cpp
+++ b/src/algorithm/ShortestPath/Vehicle/VehicleShortestPathCalculation.cpp
@@ -5,7 +5,7 @@
 #include <queue>
 #include "VehicleShortestPathCalculation.h"
 #include "VehiclePathState.h"
-#include "../../utils/Constants.h"
+#include "../../../utils/Constants.h"
 
 std::vector<uint>
 VehicleShortestPathCalculation::computeShortestPathsFromNode(Graph &graph, size_t startingNodeIdx, bool useEdges) {
diff --git a/src/ShortestPath/Vehicle/VehicleShortestPathCalculation.h b/src/algorithm/ShortestPath/Vehicle/VehicleShortestPathCalculation.h
similarity index 98%
rename from src/ShortestPath/Vehicle/VehicleShortestPathCalculation.h
rename to src/algorithm/ShortestPath/Vehicle/VehicleShortestPathCalculation.h
index b7be764..6026714 100644
--- a/src/ShortestPath/Vehicle/VehicleShortestPathCalculation.h
+++ b/src/algorithm/ShortestPath/Vehicle/VehicleShortestPathCalculation.h
@@ -50,7 +50,7 @@ private:
 
     MatrixShortestPathContainer computeShortestPathsForGraph(Graph &graph);
 };
-#include "../../instance/graph/Graph.h"
+#include "../../../instance/graph/Graph.h"
 
 
 #endif //GREEDYALGORITHM_VEHICLESHORTESTPATHCALCULATION_H
diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt
index 021c6e1..5eb7e98 100644
--- a/test/CMakeLists.txt
+++ b/test/CMakeLists.txt
@@ -36,10 +36,10 @@ add_executable(Transit_Preprocess_DEB
         ../src/instance/graph/Line.h
         ../src/routes/KeyPoint.cpp
         ../src/routes/KeyPoint.h
-        ../src/ShortestPath/Transit/TransitShortestPathContainer.cpp
-        ../src/ShortestPath/Transit/TransitShortestPathContainer.h
-        ../src/ShortestPath/Transit/TransitShortestPathPrecompute.cpp
-        ../src/ShortestPath/Transit/TransitShortestPathPrecompute.h
+        ../src/algorithm/ShortestPath/Transit/TransitShortestPathContainer.cpp
+        ../src/algorithm/ShortestPath/Transit/TransitShortestPathContainer.h
+        ../src/algorithm/ShortestPath/Transit/TransitShortestPathPrecompute.cpp
+        ../src/algorithm/ShortestPath/Transit/TransitShortestPathPrecompute.h
         ../src/utils/Globals.h
         ../src/ShortestPath/Vehicle/VehicleShortestPathCalculation.cpp
         ../src/ShortestPath/Vehicle/VehicleShortestPathCalculation.h
@@ -79,11 +79,11 @@ add_executable(Constraint_Propag_DEB
         "../src/utils/Instance Generation/Requests/RequestGenerationParameters.h"
         "../src/utils/Instance Generation/Graph/OSRMGraphGenerator.h"
         ../src/utils/Constants.h
-        ../src/ShortestPath/Vehicle/VehiclePathState.h
-        ../src/ShortestPath/Vehicle/VehicleShortestPath.h
-        ../src/ShortestPath/Vehicle/VehicleShortestPathCalculation.h
-        ../src/ShortestPath/Vehicle/VehicleShortestPathCalculation.cpp
-        ../src/ShortestPath/Vehicle/MatrixShortestPathContainer.h
+        ../src/algorithm/ShortestPath/Vehicle/VehiclePathState.h
+        ../src/algorithm/ShortestPath/Vehicle/VehicleShortestPath.h
+        ../src/algorithm/ShortestPath/Vehicle/VehicleShortestPathCalculation.h
+        ../src/algorithm/ShortestPath/Vehicle/VehicleShortestPathCalculation.cpp
+        ../src/algorithm/ShortestPath/Vehicle/MatrixShortestPathContainer.h
 )
 
 add_executable(BestInsertionHeuristic_DEB
@@ -149,8 +149,8 @@ add_executable(GraphPreprocess_DEB
         ../src/routes/requests/RequestKeyPoint.h
         ../src/routes/requests/RequestRoute.cpp
         ../src/routes/requests/RequestRoute.h
-        ../src/ShortestPath/Vehicle/VehicleShortestPathCalculation.h
-        ../src/ShortestPath/Vehicle/VehicleShortestPathCalculation.cpp
+        ../src/algorithm/ShortestPath/Vehicle/VehicleShortestPathCalculation.h
+        ../src/algorithm/ShortestPath/Vehicle/VehicleShortestPathCalculation.cpp
         ../src/utils/Constants.h
 )
 
@@ -181,14 +181,14 @@ add_executable(MultimodalInsertionHeuristic_DEB
         ../src/routes/requests/RequestKeyPoint.h
         ../src/routes/requests/RequestRoute.cpp
         ../src/routes/requests/RequestRoute.h
-        ../src/ShortestPath/Vehicle/VehicleShortestPathCalculation.h
-        ../src/ShortestPath/Vehicle/VehicleShortestPathCalculation.cpp
-        ../src/ShortestPath/Transit/TransitShortestPathContainer.cpp
-        ../src/ShortestPath/Transit/TransitShortestPathContainer.h
-        ../src/ShortestPath/Transit/TransitShortestPathPrecompute.cpp
-        ../src/ShortestPath/Transit/TransitShortestPathPrecompute.h
         ../src/algorithm/Multimodal/Heuristics/SimpleModularHeuristic.cpp
         ../src/algorithm/Multimodal/Heuristics/SimpleModularHeuristic.h
+        ../src/algorithm/ShortestPath/Vehicle/VehicleShortestPathCalculation.h
+        ../src/algorithm/ShortestPath/Vehicle/VehicleShortestPathCalculation.cpp
+        ../src/algorithm/ShortestPath/Transit/TransitShortestPathContainer.cpp
+        ../src/algorithm/ShortestPath/Transit/TransitShortestPathContainer.h
+        ../src/algorithm/ShortestPath/Transit/TransitShortestPathPrecompute.cpp
+        ../src/algorithm/ShortestPath/Transit/TransitShortestPathPrecompute.h
         ../src/algorithm/Multimodal/Heuristics/TransitAccess.h
         ../src/algorithm/DARP/Heuristics/BestInsertionHeuristic.cpp
         ../src/algorithm/DARP/Heuristics/BestInsertionHeuristic.h
diff --git a/test/src/BestInsertionHeuristicDebug.cpp b/test/src/BestInsertionHeuristicDebug.cpp
index 9090967..63e98a7 100644
--- a/test/src/BestInsertionHeuristicDebug.cpp
+++ b/test/src/BestInsertionHeuristicDebug.cpp
@@ -4,8 +4,8 @@
 
 #include "../lib/googletest/googletest/include/gtest/gtest.h"
 #include "../../src/instance/graph/Graph.h"
-#include "../../src/ShortestPath/Transit/TransitShortestPathContainer.h"
-#include "../../src/ShortestPath/Transit/TransitShortestPathPrecompute.h"
+#include "../../src/algorithm/ShortestPath/Transit/TransitShortestPathContainer.h"
+#include "../../src/algorithm/ShortestPath/Transit/TransitShortestPathPrecompute.h"
 #include "../../src/instance/Instance.h"
 #include "../../src/routes/vehicle/SAEVRoute.h"
 #include "../../src/algorithm/DARP/Heuristics/BestInsertionHeuristic.h"
diff --git a/test/src/ConstraintPropagationDebug.cpp b/test/src/ConstraintPropagationDebug.cpp
index 116ff10..70a3b9f 100644
--- a/test/src/ConstraintPropagationDebug.cpp
+++ b/test/src/ConstraintPropagationDebug.cpp
@@ -4,12 +4,12 @@
 
 #include "../lib/googletest/googletest/include/gtest/gtest.h"
 #include "../../src/instance/graph/Graph.h"
-#include "../../src/ShortestPath/Transit/TransitShortestPathContainer.h"
-#include "../../src/ShortestPath/Transit/TransitShortestPathPrecompute.h"
+#include "../../src/algorithm/ShortestPath/Transit/TransitShortestPathContainer.h"
+#include "../../src/algorithm/ShortestPath/Transit/TransitShortestPathPrecompute.h"
 #include "../../src/instance/Instance.h"
 #include "../../src/routes/vehicle/SAEVRoute.h"
 #include "../../src/utils/Instance Generation/Requests/RequestsGenerator.h"
-#include "../../src/ShortestPath/Vehicle/VehicleShortestPathCalculation.h"
+#include "../../src/algorithm/ShortestPath/Vehicle/VehicleShortestPathCalculation.h"
 
 TEST(ConstraintPropagationDebug, DebugBaseInstance) {
     std::string instancesPath = "../../resources/test/instances/Constraint Propagation/";
diff --git a/test/src/TransitPreprocessDebug.cpp b/test/src/TransitPreprocessDebug.cpp
index 419efe7..e5d5bf3 100644
--- a/test/src/TransitPreprocessDebug.cpp
+++ b/test/src/TransitPreprocessDebug.cpp
@@ -4,8 +4,8 @@
 
 #include "../lib/googletest/googletest/include/gtest/gtest.h"
 #include "../../src/instance/graph/Graph.h"
-#include "../../src/ShortestPath/Transit/TransitShortestPathContainer.h"
-#include "../../src/ShortestPath/Transit/TransitShortestPathPrecompute.h"
+#include "../../src/algorithm/ShortestPath/Transit/TransitShortestPathContainer.h"
+#include "../../src/algorithm/ShortestPath/Transit/TransitShortestPathPrecompute.h"
 
 TEST(Transit_Preprocess_DEB, DebugFunction) {
     std::string instancesPath = "../../resources/test/instances/PT Shortest Path/";
-- 
GitLab


From fcc1d6d3cac762aac349904639c89fab9efaff51 Mon Sep 17 00:00:00 2001
From: Romain BERNARD <romain.bernard@uca.fr>
Date: Tue, 17 Sep 2024 18:17:19 +0200
Subject: [PATCH 299/327] rename heuristic to be slightly more descriptive

---
 CMakeLists.txt                                | 16 ++---
 ...tic.cpp => MultimodalModularHeuristic.cpp} | 60 +++++++++----------
 ...uristic.h => MultimodalModularHeuristic.h} | 10 ++--
 test/CMakeLists.txt                           |  8 +--
 .../src/MultimodalInsertionHeuristicDebug.cpp |  6 +-
 5 files changed, 50 insertions(+), 50 deletions(-)
 rename src/algorithm/Multimodal/Heuristics/{SimpleModularHeuristic.cpp => MultimodalModularHeuristic.cpp} (80%)
 rename src/algorithm/Multimodal/Heuristics/{SimpleModularHeuristic.h => MultimodalModularHeuristic.h} (96%)

diff --git a/CMakeLists.txt b/CMakeLists.txt
index 3d5213d..030fcb2 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -63,8 +63,8 @@ add_executable(GreedyAlgorithm
         src/routes/vehicle/BestInsertionQueue.h
         src/utils/Constants.h
         src/utils/Globals.h
-        src/algorithm/Multimodal/Heuristics/SimpleModularHeuristic.h
-        src/algorithm/Multimodal/Heuristics/SimpleModularHeuristic.cpp
+        src/algorithm/Multimodal/Heuristics/MultimodalModularHeuristic.h
+        src/algorithm/Multimodal/Heuristics/MultimodalModularHeuristic.cpp
         src/algorithm/Multimodal/Heuristics/TransitAccess.h
 )
 
@@ -95,8 +95,8 @@ add_executable(RequestGenerator
         "src/utils/Instance Generation/Requests/RequestGenerationParameters.h"
         "src/utils/Instance Generation/Graph/OSRMGraphGenerator.h"
         src/utils/Globals.h
-        src/algorithm/Multimodal/Heuristics/SimpleModularHeuristic.cpp
-        src/algorithm/Multimodal/Heuristics/SimpleModularHeuristic.h
+        src/algorithm/Multimodal/Heuristics/MultimodalModularHeuristic.cpp
+        src/algorithm/Multimodal/Heuristics/MultimodalModularHeuristic.h
         src/algorithm/ShortestPath/Vehicle/VehicleShortestPath.h
         src/algorithm/ShortestPath/Vehicle/VehiclePathState.h
         src/algorithm/ShortestPath/Vehicle/VehicleShortestPathCalculation.cpp
@@ -127,8 +127,8 @@ add_executable(GraphGeneration
         "src/utils/Instance Generation/Graph/PTLineGenerationParameters.h"
         src/algorithm/DARP/Heuristics/BestInsertionHeuristic.cpp
         src/algorithm/DARP/Heuristics/BestInsertionHeuristic.h
-        src/algorithm/Multimodal/Heuristics/SimpleModularHeuristic.cpp
-        src/algorithm/Multimodal/Heuristics/SimpleModularHeuristic.h
+        src/algorithm/Multimodal/Heuristics/MultimodalModularHeuristic.cpp
+        src/algorithm/Multimodal/Heuristics/MultimodalModularHeuristic.h
         src/algorithm/ShortestPath/Vehicle/VehicleShortestPath.h
         src/algorithm/ShortestPath/Vehicle/VehiclePathState.h
         src/algorithm/ShortestPath/Vehicle/VehicleShortestPathCalculation.cpp
@@ -141,5 +141,5 @@ target_include_directories(GreedyAlgorithm PRIVATE ${PYTHON_INCLUDE_DIRS})
 target_link_libraries(GreedyAlgorithm ${PYTHON_LIBRARIES})
 
 add_executable(ModularHeuristic_DEB
-        src/algorithm/Multimodal/Heuristics/SimpleModularHeuristic.h
-        src/algorithm/Multimodal/Heuristics/SimpleModularHeuristic.cpp)
+        src/algorithm/Multimodal/Heuristics/MultimodalModularHeuristic.h
+        src/algorithm/Multimodal/Heuristics/MultimodalModularHeuristic.cpp)
diff --git a/src/algorithm/Multimodal/Heuristics/SimpleModularHeuristic.cpp b/src/algorithm/Multimodal/Heuristics/MultimodalModularHeuristic.cpp
similarity index 80%
rename from src/algorithm/Multimodal/Heuristics/SimpleModularHeuristic.cpp
rename to src/algorithm/Multimodal/Heuristics/MultimodalModularHeuristic.cpp
index 4a44088..c250981 100644
--- a/src/algorithm/Multimodal/Heuristics/SimpleModularHeuristic.cpp
+++ b/src/algorithm/Multimodal/Heuristics/MultimodalModularHeuristic.cpp
@@ -2,11 +2,11 @@
 // Created by romain on 15/07/24.
 //
 
-#include "SimpleModularHeuristic.h"
+#include "MultimodalModularHeuristic.h"
 
-using transit_order_function = std::function<bool(SimpleModularHeuristic::ScoredTransitAccess, SimpleModularHeuristic::ScoredTransitAccess)>;
+using transit_order_function = std::function<bool(MultimodalModularHeuristic::ScoredTransitAccess, MultimodalModularHeuristic::ScoredTransitAccess)>;
 
-std::vector<TransitAccess> SimpleModularHeuristic::getBestTransitEntriesList(const Request &baseRequest) const {
+std::vector<TransitAccess> MultimodalModularHeuristic::getBestTransitEntriesList(const Request &baseRequest) const {
     const auto& bestStationsIndexVector = _graph->getNode(
             baseRequest.getOriginNodeIndex()).getBestStationsNodeIdxVector();
     std::vector<TransitAccess> results; //init results vector to the appropriate size
@@ -40,11 +40,11 @@ std::vector<TransitAccess> SimpleModularHeuristic::getBestTransitEntriesList(con
     return results;
 }
 
-uint SimpleModularHeuristic::getMinEntryConstraint(const Request &request, size_t ptEntryNodeIdx) const {
+uint MultimodalModularHeuristic::getMinEntryConstraint(const Request &request, size_t ptEntryNodeIdx) const {
     return request.getMinDepartureTw() + _graph->getShortestSAEVPath(request.getOriginNodeIndex(), ptEntryNodeIdx);
 }
 
-uint SimpleModularHeuristic::getMaxEntryConstraint(const Request &request, size_t ptEntryNodeIdx) const {
+uint MultimodalModularHeuristic::getMaxEntryConstraint(const Request &request, size_t ptEntryNodeIdx) const {
     return request.getMaxArrivalTw() - ((uint) std::floor(_graph->getShortestSAEVPath(ptEntryNodeIdx, request.getDestinationNodeIndex()) * request.getTransitTravelTimeRatio()));
 }
 
@@ -57,7 +57,7 @@ uint SimpleModularHeuristic::getMaxEntryConstraint(const Request &request, size_
  * @param baseRequestId ID/index in the request vector for our base request
  * @return The subrequest successfully inserted in our route. This method's caller needs to add this request to its main request vector
  */
-const Request & SimpleModularHeuristic::insertBestTransitEntryInRoute(const Request &baseRequest, size_t baseRequestId) {
+const Request & MultimodalModularHeuristic::insertBestTransitEntryInRoute(const Request &baseRequest, size_t baseRequestId) {
     std::vector<TransitAccess> entriesAccessList = getBestTransitEntriesList(baseRequest);
     return insertBestTransitAccessInRoute(baseRequest, entriesAccessList, baseRequestId, true);
 }
@@ -72,7 +72,7 @@ const Request & SimpleModularHeuristic::insertBestTransitEntryInRoute(const Requ
  * @return The subrequest successfully inserted in our route. This method's caller needs to add this request to its main request vector
  */
 const Request &
-SimpleModularHeuristic::insertBestTransitAccessInRoute(const Request &baseRequest,
+MultimodalModularHeuristic::insertBestTransitAccessInRoute(const Request &baseRequest,
                                                        const std::vector<TransitAccess> &transitAccessList,
                                                        size_t baseRequestId, bool isEntry) {
     std::vector<Request> accessSubRequestsList;
@@ -104,7 +104,7 @@ SimpleModularHeuristic::insertBestTransitAccessInRoute(const Request &baseReques
  * @return The subrequest successfully inserted in our route
  */
 const Request &
-SimpleModularHeuristic::insertBestTransitAccessInRoute(const std::vector<Request> &accessSubRequestsList,
+MultimodalModularHeuristic::insertBestTransitAccessInRoute(const std::vector<Request> &accessSubRequestsList,
                                                        size_t baseRequestId, bool isEntry) {
     for(const auto& subreq : accessSubRequestsList) {
         updateSubRequest(baseRequestId, subreq, isEntry);
@@ -133,23 +133,23 @@ SimpleModularHeuristic::insertBestTransitAccessInRoute(const std::vector<Request
     return getSubrequest(baseRequestId, isEntry);
 }
 
-const Graph *SimpleModularHeuristic::getGraph() const {
+const Graph *MultimodalModularHeuristic::getGraph() const {
     return _graph;
 }
 
-void SimpleModularHeuristic::setGraph(const Graph *graph) {
+void MultimodalModularHeuristic::setGraph(const Graph *graph) {
     _graph = graph;
 }
 
-SAEVRoute *SimpleModularHeuristic::getRoute() const {
+SAEVRoute *MultimodalModularHeuristic::getRoute() const {
     return _route;
 }
 
-void SimpleModularHeuristic::setRoute(SAEVRoute *route) {
+void MultimodalModularHeuristic::setRoute(SAEVRoute *route) {
     _route = route;
 }
 
-void SimpleModularHeuristic::updateSubRequest(size_t requestId, const Request &request, bool isEntry) {
+void MultimodalModularHeuristic::updateSubRequest(size_t requestId, const Request &request, bool isEntry) {
     if(isEntry)
         _entrySubRequests[requestId] = request;
     else
@@ -159,29 +159,29 @@ void SimpleModularHeuristic::updateSubRequest(size_t requestId, const Request &r
     _route->getEntrySubRequestDestination(requestId).setRequest(&getSubrequest(requestId, isEntry));
 }
 
-const Request& SimpleModularHeuristic::getSubrequest(size_t requestId, bool isEntry) {
+const Request& MultimodalModularHeuristic::getSubrequest(size_t requestId, bool isEntry) {
     return isEntry ? _entrySubRequests[requestId] : _exitSubRequests[requestId];
 }
 
-double SimpleModularHeuristic::getTransitExitScore(const Request &baseRequest, const TransitAccess &exitData) const {
+double MultimodalModularHeuristic::getTransitExitScore(const Request &baseRequest, const TransitAccess &exitData) const {
     return getTransitExitScore(exitData.getAccessNodeIdx(), baseRequest.getDestinationNodeIndex(), exitData.getAccessTimestamp());
 }
 
-double SimpleModularHeuristic::getTransitExitScore(size_t transitExitNodeIndex, size_t requestDestinationNodeIndex, uint transitExitTimestamp) const {
+double MultimodalModularHeuristic::getTransitExitScore(size_t transitExitNodeIndex, size_t requestDestinationNodeIndex, uint transitExitTimestamp) const {
     return _graph->getShortestSAEVPath(transitExitNodeIndex, requestDestinationNodeIndex) + transitExitTimestamp;
 }
 
 transit_order_function
-SimpleModularHeuristic::getScoredTransitExitOrderer() {
-    return [](SimpleModularHeuristic::ScoredTransitAccess lhs, SimpleModularHeuristic::ScoredTransitAccess rhs) { return lhs.score < rhs.score; };
+MultimodalModularHeuristic::getScoredTransitExitOrderer() {
+    return [](MultimodalModularHeuristic::ScoredTransitAccess lhs, MultimodalModularHeuristic::ScoredTransitAccess rhs) { return lhs.score < rhs.score; };
 }
 
-uint SimpleModularHeuristic::getMinExitConstraint(size_t baseRequestId, const SAEVKeyPoint &entrySubRequestOriginKP,
+uint MultimodalModularHeuristic::getMinExitConstraint(size_t baseRequestId, const SAEVKeyPoint &entrySubRequestOriginKP,
                                                   size_t transitExitNodeIdx) const {
     return 0;
 }
 
-uint SimpleModularHeuristic::getMaxExitConstraint(size_t baseRequestId, const SAEVKeyPoint &entrySubRequestOriginKP,
+uint MultimodalModularHeuristic::getMaxExitConstraint(size_t baseRequestId, const SAEVKeyPoint &entrySubRequestOriginKP,
                                                   size_t transitExitNodeIdx) const {
     const Request& baseRequest = (*_requestsVect)[baseRequestId];
     return (entrySubRequestOriginKP.getMinTw() + baseRequest.getDeltaTime()) -
@@ -189,16 +189,16 @@ uint SimpleModularHeuristic::getMaxExitConstraint(size_t baseRequestId, const SA
 }
 
 std::vector<TransitAccess>
-SimpleModularHeuristic::getBestTransitExitsList(size_t baseRequestId) {
+MultimodalModularHeuristic::getBestTransitExitsList(size_t baseRequestId) {
     const Request& baseRequest = (*_requestsVect)[baseRequestId];
     const SAEVKeyPoint& entrySubRequestOriginKP = _route->getEntrySubRequestOrigin(baseRequestId);
     return getBestTransitExitsList(baseRequestId, baseRequest, entrySubRequestOriginKP);
 }
 
 std::vector<TransitAccess>
-SimpleModularHeuristic::getBestTransitExitsList(size_t baseRequestId, const Request &baseRequest,
+MultimodalModularHeuristic::getBestTransitExitsList(size_t baseRequestId, const Request &baseRequest,
                                                 const SAEVKeyPoint &entrySubRequestOriginKP) const {
-    std::vector<SimpleModularHeuristic::ScoredTransitAccess> scoredTransitExits;
+    std::vector<MultimodalModularHeuristic::ScoredTransitAccess> scoredTransitExits;
     //Get departure time/shortest transit paths list from the entry sub request's max time (this means we take the first transit available after current max arrival)
     //TODO : study other approaches (e.g check for a faster max arrival if it's valid and allows better paths. This would require propagation => costly)
 
@@ -228,12 +228,12 @@ SimpleModularHeuristic::getBestTransitExitsList(size_t baseRequestId, const Requ
     return truncatedTransitExitsList;
 }
 
-const Request & SimpleModularHeuristic::insertBestTransitExitsInRoute(const Request &baseRequest, size_t baseRequestId) {
+const Request & MultimodalModularHeuristic::insertBestTransitExitsInRoute(const Request &baseRequest, size_t baseRequestId) {
     std::vector<TransitAccess> exitAccessList = getBestTransitExitsList(baseRequestId);
     return insertBestTransitAccessInRoute(baseRequest, exitAccessList, baseRequestId, false);
 }
 
-void SimpleModularHeuristic::updateUnfulfilledSubrequest(size_t baseRequestId, bool isEntry, bool value) {
+void MultimodalModularHeuristic::updateUnfulfilledSubrequest(size_t baseRequestId, bool isEntry, bool value) {
     if(isEntry) {
         _unfulfilledTransitEntry[baseRequestId] = value;
     } else {
@@ -241,22 +241,22 @@ void SimpleModularHeuristic::updateUnfulfilledSubrequest(size_t baseRequestId, b
     }
 }
 
-const std::vector<bool> &SimpleModularHeuristic::getUnfulfilledTransitExit() const {
+const std::vector<bool> &MultimodalModularHeuristic::getUnfulfilledTransitExit() const {
     return _unfulfilledTransitExit;
 }
 
-const std::vector<bool> &SimpleModularHeuristic::getUnfulfilledTransitEntry() const {
+const std::vector<bool> &MultimodalModularHeuristic::getUnfulfilledTransitEntry() const {
     return _unfulfilledTransitEntry;
 }
 
-bool SimpleModularHeuristic::isEntryFulfilled(size_t baseRequestId) {
+bool MultimodalModularHeuristic::isEntryFulfilled(size_t baseRequestId) {
     return !_unfulfilledTransitEntry[baseRequestId];
 }
 
-const std::vector<Request> &SimpleModularHeuristic::getEntrySubRequests() const {
+const std::vector<Request> &MultimodalModularHeuristic::getEntrySubRequests() const {
     return _entrySubRequests;
 }
 
-const std::vector<Request> &SimpleModularHeuristic::getExitSubRequests() const {
+const std::vector<Request> &MultimodalModularHeuristic::getExitSubRequests() const {
     return _exitSubRequests;
 }
diff --git a/src/algorithm/Multimodal/Heuristics/SimpleModularHeuristic.h b/src/algorithm/Multimodal/Heuristics/MultimodalModularHeuristic.h
similarity index 96%
rename from src/algorithm/Multimodal/Heuristics/SimpleModularHeuristic.h
rename to src/algorithm/Multimodal/Heuristics/MultimodalModularHeuristic.h
index 065dcc2..227b87d 100644
--- a/src/algorithm/Multimodal/Heuristics/SimpleModularHeuristic.h
+++ b/src/algorithm/Multimodal/Heuristics/MultimodalModularHeuristic.h
@@ -2,8 +2,8 @@
 // Created by romain on 15/07/24.
 //
 
-#ifndef GREEDYALGORITHM_SIMPLEMODULARHEURISTIC_H
-#define GREEDYALGORITHM_SIMPLEMODULARHEURISTIC_H
+#ifndef GREEDYALGORITHM_MULTIMODALMODULARHEURISTIC_H
+#define GREEDYALGORITHM_MULTIMODALMODULARHEURISTIC_H
 
 
 #include <cstddef>
@@ -22,7 +22,7 @@
 #define DEBUG_MSG(str) do { } while ( false )
 #endif
 
-class SimpleModularHeuristic {
+class MultimodalModularHeuristic {
 private:
     //Exterior members
     const Graph* _graph{nullptr};
@@ -41,7 +41,7 @@ private:
 
 //Public interface to interact with the modular heuristic
 public:
-    SimpleModularHeuristic(const Graph *graph, SAEVRoute *route, std::vector<Request> const* requestsVect) : _graph(graph), _requestsVect(requestsVect),
+    MultimodalModularHeuristic(const Graph *graph, SAEVRoute *route, std::vector<Request> const* requestsVect) : _graph(graph), _requestsVect(requestsVect),
     _route(route), _entrySubRequests(requestsVect->size()), _exitSubRequests(requestsVect->size()),
     _unfulfilledTransitEntry(requestsVect->size()), _unfulfilledTransitExit(requestsVect->size()) {}
 
@@ -190,4 +190,4 @@ protected:
 };
 
 
-#endif //GREEDYALGORITHM_SIMPLEMODULARHEURISTIC_H
+#endif //GREEDYALGORITHM_MULTIMODALMODULARHEURISTIC_H
diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt
index 5eb7e98..3554c1e 100644
--- a/test/CMakeLists.txt
+++ b/test/CMakeLists.txt
@@ -41,8 +41,8 @@ add_executable(Transit_Preprocess_DEB
         ../src/algorithm/ShortestPath/Transit/TransitShortestPathPrecompute.cpp
         ../src/algorithm/ShortestPath/Transit/TransitShortestPathPrecompute.h
         ../src/utils/Globals.h
-        ../src/ShortestPath/Vehicle/VehicleShortestPathCalculation.cpp
-        ../src/ShortestPath/Vehicle/VehicleShortestPathCalculation.h
+        ../src/algorithm/ShortestPath/Vehicle/VehicleShortestPathCalculation.cpp
+        ../src/algorithm/ShortestPath/Vehicle/VehicleShortestPathCalculation.h
 )
 
 
@@ -181,14 +181,14 @@ add_executable(MultimodalInsertionHeuristic_DEB
         ../src/routes/requests/RequestKeyPoint.h
         ../src/routes/requests/RequestRoute.cpp
         ../src/routes/requests/RequestRoute.h
-        ../src/algorithm/Multimodal/Heuristics/SimpleModularHeuristic.cpp
-        ../src/algorithm/Multimodal/Heuristics/SimpleModularHeuristic.h
         ../src/algorithm/ShortestPath/Vehicle/VehicleShortestPathCalculation.h
         ../src/algorithm/ShortestPath/Vehicle/VehicleShortestPathCalculation.cpp
         ../src/algorithm/ShortestPath/Transit/TransitShortestPathContainer.cpp
         ../src/algorithm/ShortestPath/Transit/TransitShortestPathContainer.h
         ../src/algorithm/ShortestPath/Transit/TransitShortestPathPrecompute.cpp
         ../src/algorithm/ShortestPath/Transit/TransitShortestPathPrecompute.h
+        ../src/algorithm/Multimodal/Heuristics/MultimodalModularHeuristic.cpp
+        ../src/algorithm/Multimodal/Heuristics/MultimodalModularHeuristic.h
         ../src/algorithm/Multimodal/Heuristics/TransitAccess.h
         ../src/algorithm/DARP/Heuristics/BestInsertionHeuristic.cpp
         ../src/algorithm/DARP/Heuristics/BestInsertionHeuristic.h
diff --git a/test/src/MultimodalInsertionHeuristicDebug.cpp b/test/src/MultimodalInsertionHeuristicDebug.cpp
index 9068484..ea91b2d 100644
--- a/test/src/MultimodalInsertionHeuristicDebug.cpp
+++ b/test/src/MultimodalInsertionHeuristicDebug.cpp
@@ -7,7 +7,7 @@
 #include "../../src/instance/Instance.h"
 #include "../../src/routes/vehicle/SAEVRoute.h"
 #include "../../src/utils/Timing.h"
-#include "../../src/algorithm/Multimodal/Heuristics/SimpleModularHeuristic.h"
+#include "../../src/algorithm/Multimodal/Heuristics/MultimodalModularHeuristic.h"
 #include "../../src/utils/Instance Generation/Requests/RequestsGenerator.h"
 
 TEST(MultimodalInsertionHeuristicDebug, DebugBaseInstance) {
@@ -26,7 +26,7 @@ TEST(MultimodalInsertionHeuristicDebug, DebugBaseInstance) {
     //Init instance
     Instance instance(requests,graphFromSingleFile,4);
     SAEVRoute routesContainer(graphFromSingleFile, requests, true);
-    SimpleModularHeuristic multimodalHeuristic(&graphFromSingleFile, &routesContainer, &requests);
+    MultimodalModularHeuristic multimodalHeuristic(&graphFromSingleFile, &routesContainer, &requests);
     STOP_TIMER("Instance parsing and init")
     std::cout << "------------------Fin parsing instance et route-------------------" << std::endl << std::endl;
 
@@ -67,7 +67,7 @@ TEST(MultimodalInsertionHeuristicDebug, DebugInstanceAlain) {
     //Init instance
     Instance instance(requests,graphFromSingleFile,4);
     SAEVRoute routesContainer(graphFromSingleFile, requests, true);
-    SimpleModularHeuristic multimodalHeuristic(&graphFromSingleFile, &routesContainer, &requests);
+    MultimodalModularHeuristic multimodalHeuristic(&graphFromSingleFile, &routesContainer, &requests);
     STOP_TIMER("Instance parsing and init")
     std::cout << "------------------Fin parsing instance et route-------------------" << std::endl << std::endl;
 
-- 
GitLab


From 3cd0a11f3a8aba9dcb9ac0afa8a148cd985a7743 Mon Sep 17 00:00:00 2001
From: Romain BERNARD <romain.bernard@uca.fr>
Date: Tue, 17 Sep 2024 18:40:15 +0200
Subject: [PATCH 300/327] make const

---
 src/routes/vehicle/propagation/SAEVRouteChangelist.cpp | 2 +-
 src/routes/vehicle/propagation/SAEVRouteChangelist.h   | 2 +-
 2 files changed, 2 insertions(+), 2 deletions(-)

diff --git a/src/routes/vehicle/propagation/SAEVRouteChangelist.cpp b/src/routes/vehicle/propagation/SAEVRouteChangelist.cpp
index 535941b..3bd9e14 100644
--- a/src/routes/vehicle/propagation/SAEVRouteChangelist.cpp
+++ b/src/routes/vehicle/propagation/SAEVRouteChangelist.cpp
@@ -102,6 +102,6 @@ void SAEVRouteChangelist::setVehicleId(size_t vehicleId) {
     _vehicleId = vehicleId;
 }
 
-bool SAEVRouteChangelist::success() {
+bool SAEVRouteChangelist::success() const {
     return _status == InsertionStatus::SUCCESS;
 }
diff --git a/src/routes/vehicle/propagation/SAEVRouteChangelist.h b/src/routes/vehicle/propagation/SAEVRouteChangelist.h
index 4541e85..fc7844b 100644
--- a/src/routes/vehicle/propagation/SAEVRouteChangelist.h
+++ b/src/routes/vehicle/propagation/SAEVRouteChangelist.h
@@ -74,7 +74,7 @@ public:
 
     [[nodiscard]] InsertionStatus getStatus() const;
     void setStatus(InsertionStatus status);
-    [[nodiscard]] bool success();
+    [[nodiscard]] bool success() const;
 
     [[nodiscard]] InsertionStatus getCurrentStatus() const;
     void setCurrentStatus(InsertionStatus currentStatus);
-- 
GitLab


From 0fca582c422c2fcafd8151cd7e10cb9b5bc44878 Mon Sep 17 00:00:00 2001
From: Romain BERNARD <romain.bernard@uca.fr>
Date: Tue, 17 Sep 2024 18:40:49 +0200
Subject: [PATCH 301/327] enrich docs

---
 .../Heuristics/MultimodalModularHeuristic.h   | 22 ++++++++++++++++---
 1 file changed, 19 insertions(+), 3 deletions(-)

diff --git a/src/algorithm/Multimodal/Heuristics/MultimodalModularHeuristic.h b/src/algorithm/Multimodal/Heuristics/MultimodalModularHeuristic.h
index 227b87d..7dfbe95 100644
--- a/src/algorithm/Multimodal/Heuristics/MultimodalModularHeuristic.h
+++ b/src/algorithm/Multimodal/Heuristics/MultimodalModularHeuristic.h
@@ -24,15 +24,33 @@
 
 class MultimodalModularHeuristic {
 private:
-    //Exterior members
+    //Exterior members that the algorithm references or acts upon
     const Graph* _graph{nullptr};
     const std::vector<Request>* _requestsVect{nullptr};
     SAEVRoute* _route{nullptr}; //_route is a pointer here to decorrelate the route from the algorithm and facilitate using multiple modules on the same route
 
+    /**
+     * Vector holding every entry sub request created to prevent refs staleness
+     * while letting the requests vector hold only the base requests \n
+     * \n
+     * Initialized with empty requests to match the number of base requests in the constructor
+     */
     std::vector<Request> _entrySubRequests;
+    /**
+     * Vector holding every exit sub request created to prevent refs staleness
+     * while letting the requests vector hold only the base requests\n
+     * \n
+     * Initialized with empty requests to match the number of base requests in the constructor
+     */
     std::vector<Request> _exitSubRequests;
 
+    /**
+     * Marks unfulfilled entry requests due to not finding a single viable candidate
+     */
     std::vector<bool> _unfulfilledTransitEntry;
+    /**
+     * Marks unfulfilled exit requests due to not finding a single viable candidate
+     */
     std::vector<bool> _unfulfilledTransitExit;
 
     //Add friend test classes to test inner workings without making the whole API public
@@ -177,8 +195,6 @@ protected:
 
     void updateSubRequest(size_t requestId, const Request &request, bool isEntry);
 
-    [[nodiscard]] size_t getSubrequestIndex(size_t requestId, bool isEntry) const;
-
     const Request &getSubrequest(size_t requestId, bool isEntry);
 
     [[nodiscard]] double getTransitExitScore(size_t transitExitNodeIndex, size_t requestDestinationNodeIndex,
-- 
GitLab


From 3d7164f997e793287360bc530ec01243613e4c27 Mon Sep 17 00:00:00 2001
From: Romain BERNARD <romain.bernard@uca.fr>
Date: Tue, 17 Sep 2024 18:42:02 +0200
Subject: [PATCH 302/327] if request was unfulfilled, emplace its ID for future
 reference to insert it via SAEV-only best insertion in the last step of
 algorithm

---
 .../Heuristics/MultimodalModularHeuristic.cpp          | 10 +++++++++-
 .../Multimodal/Heuristics/MultimodalModularHeuristic.h |  9 +++++++++
 2 files changed, 18 insertions(+), 1 deletion(-)

diff --git a/src/algorithm/Multimodal/Heuristics/MultimodalModularHeuristic.cpp b/src/algorithm/Multimodal/Heuristics/MultimodalModularHeuristic.cpp
index c250981..463d697 100644
--- a/src/algorithm/Multimodal/Heuristics/MultimodalModularHeuristic.cpp
+++ b/src/algorithm/Multimodal/Heuristics/MultimodalModularHeuristic.cpp
@@ -122,7 +122,11 @@ MultimodalModularHeuristic::insertBestTransitAccessInRoute(const std::vector<Req
     if(accessSubRequestsList.empty()) { //If no valid subrequest was given, still create a fake subrequest and mention failure in the appropriate vector
         DEBUG_MSG("UNFULFILLED SUBREQUEST");
         updateSubRequest(baseRequestId, (*_requestsVect)[baseRequestId], isEntry);
-        updateUnfulfilledSubrequest(baseRequestId, isEntry, true);
+        updateUnfulfilledSubrequest(baseRequestId, isEntry, true); //mark failures for debug/statistics
+        if(!isEntry) { //Exit subrequest : remove entry subrequest and add baseRequest to the "unfulfilled list"
+            _route->removeRequestWithPropagation(baseRequestId, true);
+        }
+        emplaceDARPRequest(baseRequestId);
     } else {
         //If no active vehicle insertion worked, do best insertion on a new vehicle with the first subrequest (supposedly it's the most advantageous)
         DEBUG_MSG("CREATE VEHICLE");
@@ -260,3 +264,7 @@ const std::vector<Request> &MultimodalModularHeuristic::getEntrySubRequests() co
 const std::vector<Request> &MultimodalModularHeuristic::getExitSubRequests() const {
     return _exitSubRequests;
 }
+
+void MultimodalModularHeuristic::emplaceDARPRequest(size_t baseRequestId) {
+    _darpRequestList.emplace_back(baseRequestId);
+}
diff --git a/src/algorithm/Multimodal/Heuristics/MultimodalModularHeuristic.h b/src/algorithm/Multimodal/Heuristics/MultimodalModularHeuristic.h
index 7dfbe95..0437dcd 100644
--- a/src/algorithm/Multimodal/Heuristics/MultimodalModularHeuristic.h
+++ b/src/algorithm/Multimodal/Heuristics/MultimodalModularHeuristic.h
@@ -53,6 +53,13 @@ private:
      */
     std::vector<bool> _unfulfilledTransitExit;
 
+    /**
+     * Vector containing every base request (referenced via its _requestsVect index) that needs to be fulfilled in SAEV-only DARP \n
+     * \n
+     * This includes non-multimodal requests and requests that couldn't be fulfilled in the entry/exit step of the multimodal procedure
+     */
+    std::vector<size_t> _darpRequestList;
+
     //Add friend test classes to test inner workings without making the whole API public
     FRIEND_TEST(MultimodalInsertionHeuristicDebug, DebugBaseInstance);
     FRIEND_TEST(MultimodalInsertionHeuristicDebug, DebugInstanceAlain);
@@ -203,6 +210,8 @@ protected:
     void updateUnfulfilledSubrequest(size_t baseRequestId, bool isEntry, bool value);
 
     bool isEntryFulfilled(size_t baseRequestId);
+
+    void emplaceDARPRequest(size_t baseRequestId);
 };
 
 
-- 
GitLab


From b3a5b07cb131bfbfb40d57036d478a3ce43fff62 Mon Sep 17 00:00:00 2001
From: Romain BERNARD <romain.bernard@uca.fr>
Date: Wed, 18 Sep 2024 16:20:50 +0200
Subject: [PATCH 303/327] add isMultimodal attribute (for now always true,
 TODO:add to request import format)

---
 src/instance/requests/Request.cpp | 8 ++++++++
 src/instance/requests/Request.h   | 4 ++++
 2 files changed, 12 insertions(+)

diff --git a/src/instance/requests/Request.cpp b/src/instance/requests/Request.cpp
index bfb1ad8..20effe1 100644
--- a/src/instance/requests/Request.cpp
+++ b/src/instance/requests/Request.cpp
@@ -267,3 +267,11 @@ double Request::computeTransitTravelTimeRatio(const Graph &graph, double travelT
     double deltaRatio = (graph.getShortestSAEVPath(_originNodeIndex, _destinationNodeIndex))/(double)_deltaTime;
     return computeTransitTravelTimeRatio(deltaRatio, travelTimeRatio);
 }
+
+bool Request::isMultimodal() const {
+    return _isMultimodal;
+}
+
+void Request::setIsMultimodal(bool isMultimodal) {
+    Request::_isMultimodal = isMultimodal;
+}
diff --git a/src/instance/requests/Request.h b/src/instance/requests/Request.h
index 8846e2d..cbfb917 100644
--- a/src/instance/requests/Request.h
+++ b/src/instance/requests/Request.h
@@ -22,6 +22,7 @@ private:
     TimeWindow _arrivalTW; //[min,max] time window for arrival to the destination node
     uint _deltaTime; //Base delta time, aka the maximum total duration of the path to serve this _request
     uint _weight; //How much space the requests takes in the vehicle (defaults to 1)
+    bool _isMultimodal{true}; //True iff the request accepts to be split by using the transit system
 
     //Request helpful members (used for constraint propagation and remember the current state of the _request)
     /**
@@ -91,6 +92,9 @@ public:
     [[nodiscard]] const LineStop *getLineStop(int routeIndex) const;
     void setLineStop(int routeIndex, LineStop *lineStop);
 
+    bool isMultimodal() const;
+    void setIsMultimodal(bool isMultimodal);
+
     void resetKeyPoint(int routeIndex);
 
     [[nodiscard]] double getTransitTravelTimeRatio() const;
-- 
GitLab


From 022eeba1aaf2d92bc8a5f257a6465e200a7f9a6d Mon Sep 17 00:00:00 2001
From: Romain BERNARD <romain.bernard@uca.fr>
Date: Wed, 18 Sep 2024 16:25:31 +0200
Subject: [PATCH 304/327] implement the public that chains all the steps of the
 algorithm

---
 .../Heuristics/MultimodalModularHeuristic.cpp | 34 +++++++++++++++++--
 .../Heuristics/MultimodalModularHeuristic.h   | 14 +++++++-
 2 files changed, 45 insertions(+), 3 deletions(-)

diff --git a/src/algorithm/Multimodal/Heuristics/MultimodalModularHeuristic.cpp b/src/algorithm/Multimodal/Heuristics/MultimodalModularHeuristic.cpp
index 463d697..42264b9 100644
--- a/src/algorithm/Multimodal/Heuristics/MultimodalModularHeuristic.cpp
+++ b/src/algorithm/Multimodal/Heuristics/MultimodalModularHeuristic.cpp
@@ -119,7 +119,9 @@ MultimodalModularHeuristic::insertBestTransitAccessInRoute(const std::vector<Req
         }
     }
 
-    if(accessSubRequestsList.empty()) { //If no valid subrequest was given, still create a fake subrequest and mention failure in the appropriate vector
+    // If no valid candidate was given, still create a fake
+    // subrequest and mention failure in the appropriate vector
+    if(accessSubRequestsList.empty()) {
         DEBUG_MSG("UNFULFILLED SUBREQUEST");
         updateSubRequest(baseRequestId, (*_requestsVect)[baseRequestId], isEntry);
         updateUnfulfilledSubrequest(baseRequestId, isEntry, true); //mark failures for debug/statistics
@@ -128,7 +130,8 @@ MultimodalModularHeuristic::insertBestTransitAccessInRoute(const std::vector<Req
         }
         emplaceDARPRequest(baseRequestId);
     } else {
-        //If no active vehicle insertion worked, do best insertion on a new vehicle with the first subrequest (supposedly it's the most advantageous)
+        // If no active vehicle insertion worked, do best insertion on a new vehicle
+        // with the first subrequest (supposedly it's the most advantageous)
         DEBUG_MSG("CREATE VEHICLE");
         updateSubRequest(baseRequestId, accessSubRequestsList[0], isEntry);
         _route->insertRequestInNewVehicle(_route->getExitSubRequestOrigin(baseRequestId));
@@ -268,3 +271,30 @@ const std::vector<Request> &MultimodalModularHeuristic::getExitSubRequests() con
 void MultimodalModularHeuristic::emplaceDARPRequest(size_t baseRequestId) {
     _darpRequestList.emplace_back(baseRequestId);
 }
+
+void MultimodalModularHeuristic::doMultimodalRequestsInsertion() {
+    // Step 1
+    // Execute transit entry insertion procedure first, it'll mark every failed request
+    // and greedily insert the best compatible entry request
+    for(size_t requestId = 0; requestId < _requestsVect->size(); ++requestId) {
+        const Request& baseRequest = (*_requestsVect)[requestId];
+        if(baseRequest.isMultimodal())
+            insertBestTransitEntryInRoute(baseRequest, requestId);
+        else
+            emplaceDARPRequest(requestId);
+    }
+
+    // Step 2
+    // If the entry request was fulfilled, do the exit insertion procedure
+    // if this step fails (no compatible exit) undoes the entry insertion, which is a costly process
+    for(size_t requestId = 0; requestId < _requestsVect->size(); ++requestId) {
+        if(!_unfulfilledTransitEntry[requestId])
+            insertBestTransitExitsInRoute((*_requestsVect)[requestId], requestId);
+    }
+
+    // Step 3
+    // Do best request insertion for every unfulfilled multimodal request and non-multimodal request
+    for(size_t requestId : _darpRequestList) {
+        BestInsertionHeuristic::doBestRequestInsertionForRoute(_route->getRequestOrigin(requestId), *_route);
+    }
+}
diff --git a/src/algorithm/Multimodal/Heuristics/MultimodalModularHeuristic.h b/src/algorithm/Multimodal/Heuristics/MultimodalModularHeuristic.h
index 0437dcd..5d09984 100644
--- a/src/algorithm/Multimodal/Heuristics/MultimodalModularHeuristic.h
+++ b/src/algorithm/Multimodal/Heuristics/MultimodalModularHeuristic.h
@@ -70,7 +70,19 @@ public:
     _route(route), _entrySubRequests(requestsVect->size()), _exitSubRequests(requestsVect->size()),
     _unfulfilledTransitEntry(requestsVect->size()), _unfulfilledTransitExit(requestsVect->size()) {}
 
-    void multimodalRequestsInsertion(const std::vector<Request>& requestsToInsert);
+    /**
+     * Executes iteratively each steps of the algorithm :
+     * <ol>
+     *  <li> Iterate over all base requests to generate and insert transit entry sub-request </li>
+     *  <li> From those inserted entry sub-requests, find compatible exit candidates and try to insert them </li>
+     *  <li> Insert every non-multimodal base request or previously unsuccessful multimodal base request for which step 1 or 2 failed </li>
+     * </ol>
+     *
+     * If we fail step 1 or 2 for a multimodal request or the request is non-multimodal,
+     * it's added to a list of DARP requests to be fulfilled \n
+     * If we fail step 2 (no compatible exit available), remove the entry request and reset+propagate bounds
+     */
+    void doMultimodalRequestsInsertion();
 
     [[nodiscard]] size_t getNbBaseRquests() const {
         return _requestsVect->size();
-- 
GitLab


From dd9b05287d5ea6df355824044ad97ab696ee3b32 Mon Sep 17 00:00:00 2001
From: Romain BERNARD <romain.bernard@uca.fr>
Date: Wed, 18 Sep 2024 18:13:42 +0200
Subject: [PATCH 305/327] make old constructor deprecated

---
 src/instance/graph/Graph.cpp | 6 ++----
 src/instance/graph/Graph.h   | 1 +
 2 files changed, 3 insertions(+), 4 deletions(-)

diff --git a/src/instance/graph/Graph.cpp b/src/instance/graph/Graph.cpp
index c04ae36..6596630 100644
--- a/src/instance/graph/Graph.cpp
+++ b/src/instance/graph/Graph.cpp
@@ -48,8 +48,6 @@ Graph::Graph(const std::string& nodesFilePath, const std::string& edgesFilePath,
     //PT Lines instantiation
     std::mt19937 rng;
     rng.seed(123456789);
-    std::uniform_int_distribution<uint32_t> uint_dist10(1,10);
-    std::uniform_int_distribution<uint32_t> uint_dist60(1,60);
     std::ifstream ptLinesFile(ptLinesFilePath);
     assertm(!ptLinesFile.fail(), "Failed to open the given file");
     std::cout << "Lines instantiation" << std::endl;
@@ -58,10 +56,10 @@ Graph::Graph(const std::string& nodesFilePath, const std::string& edgesFilePath,
         //If no header, do the thing
         if(!static_cast<std::string>(row[0]).starts_with('#'))
         {
-            parseLineRandomizedSchedule(row, rng, uint_dist10, uint_dist60);
+            parseLineRandomizedSchedule(row, rng);
         }
-        linkAllPTNodes();
     }
+    linkAllPTNodes();
     std::cout << "test is done" << std::endl;
 }
 
diff --git a/src/instance/graph/Graph.h b/src/instance/graph/Graph.h
index fec74d4..050ee93 100644
--- a/src/instance/graph/Graph.h
+++ b/src/instance/graph/Graph.h
@@ -133,6 +133,7 @@ public:
      * @param edgeFilePath The file containing edge data (format for each line : start_node_index,end_node_index,edge_length)
      * @param ptLineFilePath
      */
+    [[deprecated("Replaced with the single file syntax for creating a graph via file")]]
     Graph(const std::string& nodeFilePath, const std::string& edgeFilePath, const std::string& ptLineFilePath);
 
     /**
-- 
GitLab


From bc4f5e1c050c4aa2cdf34448c61f9222a05eefa4 Mon Sep 17 00:00:00 2001
From: Romain BERNARD <romain.bernard@uca.fr>
Date: Wed, 18 Sep 2024 18:17:48 +0200
Subject: [PATCH 306/327] update PT Line parser format to control travel time +
 implement fixed schedule parsing and add parser docs

---
 src/instance/graph/Graph.cpp | 63 +++++++++++++++++++++++++++++-------
 src/instance/graph/Graph.h   | 43 ++++++++++++++++++++----
 2 files changed, 89 insertions(+), 17 deletions(-)

diff --git a/src/instance/graph/Graph.cpp b/src/instance/graph/Graph.cpp
index 6596630..9d6b9ec 100644
--- a/src/instance/graph/Graph.cpp
+++ b/src/instance/graph/Graph.cpp
@@ -108,11 +108,16 @@ Graph::Graph(const std::string& datFilePath) {
 
     //-- Read Public transit line
     std::cout << currentRow.toString() << std::endl;
-    std::uniform_int_distribution<uint32_t> uint_dist10(1,5);
-    std::uniform_int_distribution<uint32_t> uint_dist60(1,10);
-    while(infile >> currentRow && !currentRow[0].starts_with('#')) {
-        this->parseLineRandomizedSchedule(currentRow, rng, uint_dist10, uint_dist60);
+    if(currentRow[0].starts_with("#PT Line fixed")) {
+        while(infile >> currentRow && !currentRow[0].starts_with('#')) {
+            this->parseLineFixedSchedule(infile, currentRow);
+        }
+    } else {
+        while(infile >> currentRow && !currentRow[0].starts_with('#')) {
+            this->parseLineRandomizedSchedule(currentRow, rng);
+        }
     }
+
     //Make links once all lines are created to prevent stale refs
     this->linkAllPTNodes();
 }
@@ -249,11 +254,9 @@ void Graph::parseEdgeRow(const DATRow& row)
     }
 }
 
-void Graph::parseLineRandomizedSchedule(const DATRow& row, std::mt19937 rng,
-                                        std::uniform_int_distribution<uint32_t> travelTimeDistribution,
-                                        std::uniform_int_distribution<uint32_t> startTimeDistribution)
+void Graph::parseLineRandomizedSchedule(const DATRow& row, std::mt19937 rng)
 {
-    int startTime, endTime, frequency, currentNodeIdx;
+    int startTime, endTime, frequency, minTravelTime, maxTravelTime, currentNodeIdx;
     //add nodes for the line
     Line newLine = Line();
     //Give it an ID
@@ -265,7 +268,11 @@ void Graph::parseLineRandomizedSchedule(const DATRow& row, std::mt19937 rng,
     std::from_chars(row[0].data(), row[0].data() + row[0].size(), frequency);
     std::from_chars(row[1].data(), row[1].data() + row[1].size(), startTime);
     std::from_chars(row[2].data(), row[2].data() + row[2].size(), endTime);
-    int currentTime = startTime + startTimeDistribution(rng); //random startTime time with 60min max offset
+    std::from_chars(row[3].data(), row[3].data() + row[3].size(), minTravelTime);
+    std::from_chars(row[4].data(), row[4].data() + row[4].size(), maxTravelTime);
+    std::uniform_int_distribution<uint32_t> travelTimeDistribution(minTravelTime,maxTravelTime);
+
+    int currentTime = startTime;
     while(currentTime + frequency < endTime)
     {
         timeTable.push_back(currentTime + frequency);
@@ -282,7 +289,7 @@ void Graph::parseLineRandomizedSchedule(const DATRow& row, std::mt19937 rng,
     //Create subsequent timetables according to preceding timetable and travel time
     for(size_t i = 1; i < newLine.getNodes().size(); ++i)
     {
-        int travelTime = travelTimeDistribution(rng); //FIXME travel time is randomized for now, we should get edge length if it exists I guess
+        uint travelTime = travelTimeDistribution(rng);
         std::vector<int> precedingTimeTable = newLine.getTimetable(i - 1);
         std::vector<int> newTimetable;
         newTimetable.reserve(precedingTimeTable.size()); //Reserve to improve foreach efficiency
@@ -292,9 +299,43 @@ void Graph::parseLineRandomizedSchedule(const DATRow& row, std::mt19937 rng,
         newLine.addTimetable(newTimetable);
         newTimetable.clear();
     }
+    //Check for errors
+    if(newLine.check()) {
+        this->addLine(newLine);
+        DEBUG_MSG("Created new line with randomized schedule");
+    }
+}
+
+void Graph::parseLineFixedSchedule(std::ifstream& infile, DATRow& row) {
+    Line newLine = Line();
+
+    // First line consists of the list of node indexes, add them all to the new line
+    uint currentNodeIdx;
+    for(uint i = 0; i < row.size(); ++i)
+    {
+        std::from_chars(row[i].data(), row[i].data() + row[i].size(), currentNodeIdx);
+        newLine.addNode(currentNodeIdx);
+    }
+
+    // Read schedule until hitting an empty line, used to separate individual lines to parse
+    std::vector<std::vector<int>> newSchedules;
+    while(infile >> row && !row[0].empty()) {
+        assertm(row.size() == newLine.size(), "Schedule size doesn't correspond to the number of nodes");
+        // Add the time to the appropriate station's schedule vector
+        for(uint stationIdx = 0; stationIdx < row.size(); ++stationIdx) {
+            newSchedules[stationIdx].emplace_back(std::stoi(row[stationIdx].data()));
+        }
+    }
+
+    //Add properly formatted timetables to the new line in station order
+    for(const std::vector<int>& stationSchedule : newSchedules) {
+        newLine.addTimetable(stationSchedule);
+    }
+
+    //Check for errors
     if(newLine.check()) {
         this->addLine(newLine);
-        DEBUG_MSG("Created new line with nodes");
+        DEBUG_MSG("Created new line with fixed schedule");
     }
 }
 
diff --git a/src/instance/graph/Graph.h b/src/instance/graph/Graph.h
index 050ee93..f1baeea 100644
--- a/src/instance/graph/Graph.h
+++ b/src/instance/graph/Graph.h
@@ -13,10 +13,11 @@
 
 #include "Node.h"
 #include "Edge.h"
-#include "../../ShortestPath/Vehicle/VehicleShortestPathCalculation.h"
+#include "../../utils/Globals.h"
 #include "../../utils/Constants.h"
-#include "../../ShortestPath/Transit/TransitShortestPathContainer.h"
-#include "../../ShortestPath/Transit/TransitShortestPathPrecompute.h"
+#include "../../algorithm/ShortestPath/Vehicle/VehicleShortestPathCalculation.h"
+#include "../../algorithm/ShortestPath/Transit/TransitShortestPathContainer.h"
+#include "../../algorithm/ShortestPath/Transit/TransitShortestPathPrecompute.h"
 
 class DATRow;
 class Graph {
@@ -34,11 +35,41 @@ private:
      * @return True if @this is properly referenced in the Line object at the expected index
      */
     bool checkLineToNodeLinks();
+    /**
+     * Parses and adds a node from the given row object to the graph.<br>
+     * Format : status,x_coordinate,y_coordinate
+     * @param row row extracted from the input file
+     */
     void parseNodeRow(const DATRow& row);
+    /**
+     * Parses and adds an edge from the given row object to the graph.<br>
+     * Format : start_node_idx,end_node_idx,length
+     * @param row row extracted from the input file
+     */
     void parseEdgeRow(const DATRow& row);
-    void parseLineRandomizedSchedule(const DATRow &row, std::mt19937 rng,
-                                     std::uniform_int_distribution<uint32_t> travelTimeDistribution,
-                                     std::uniform_int_distribution<uint32_t> startTimeDistribution);
+
+    /**
+     * Parses and adds a line to the graph from a given row object and reusing the given seeded rng engine.
+     * Uses the format : <br>
+     * frequency,start_time,end_time,min_travel_time,max_travel_time,node_0, ..., node_n
+     * @param row row containing the necessary info to generate a random line
+     * @param rng seeded random number generator
+     */
+    void parseLineRandomizedSchedule(const DATRow &row, std::mt19937 rng);
+
+    /**
+     * Parses and adds a line to the graph from the given row in given the following format : <br>
+     * node_0_idx, ... node_n_idx <br>
+     * node_0_pass_0_time, ... node_n_pass_0_time <br>
+     * ... <br>
+     * node_0_pass_m_time, ... node_n_pass_m_time <br>
+     * <br>
+     * /!\ each transit line to parse ends with an empty line
+     *
+     * @param infile input file stream, necessary to iterate over multiple lines in the function
+     * @param row the current DATrow object we reuse from other parsing functions
+     */
+    void parseLineFixedSchedule(std::ifstream& infile, DATRow& row);
 
 public:
     [[nodiscard]] const std::vector<Node> &getNodesVector() const {
-- 
GitLab


From 01575f862cffb77671ed131f0fb3d4f34ae0babe Mon Sep 17 00:00:00 2001
From: Romain BERNARD <romain.bernard@uca.fr>
Date: Wed, 18 Sep 2024 18:26:58 +0200
Subject: [PATCH 307/327] update instances to include travel time bounds

---
 .../DebugWeight/requests.dat                       |  2 +-
 .../Instance_Alain_140624/requests.dat             |  2 +-
 .../Instance_Alain_140624_2/requests.dat           |  2 +-
 .../basic_debug_instance/graph.dat                 |  4 ++--
 .../basic_debug_instance/requests.dat              |  2 +-
 .../instance_alain_140624/even_more_requests.dat   |  2 +-
 .../instance_alain_140624/graph.dat                | 14 +++++++-------
 .../instance_alain_140624/more_requests.dat        |  2 +-
 .../instance_alain_140624/requests.dat             |  2 +-
 .../basic_debug_instance/graph.dat                 |  4 ++--
 .../contiguous_lines_debug_instance/graph.dat      | 10 +++++-----
 .../cycling_line_debug_instance/graph.dat          |  2 +-
 .../graph.dat                                      | 12 ++++++------
 .../graph.dat                                      | 14 +++++++-------
 .../single_node_lines_debug_instance/graph.dat     |  8 ++++----
 .../two_lines_debug_instance/graph.dat             |  6 +++---
 .../graph preprocess/book example/graph.dat        |  4 ++--
 17 files changed, 46 insertions(+), 46 deletions(-)

diff --git a/resources/test/instances/BestInsertionHeuristic/DebugWeight/requests.dat b/resources/test/instances/BestInsertionHeuristic/DebugWeight/requests.dat
index b3170a4..43762eb 100644
--- a/resources/test/instances/BestInsertionHeuristic/DebugWeight/requests.dat
+++ b/resources/test/instances/BestInsertionHeuristic/DebugWeight/requests.dat
@@ -1,6 +1,6 @@
 #Global Params (delta ratio)
 1
-#Requests (origin_idx,destination_idx,min_tw_start,max_tw_start,min_tw_end,max_tw_end,delta baseline,capacity)
+#Requests (origin_idx,destination_idx,min_tw_start,max_tw_start,min_tw_end,max_tw_end,delta_time,capacity)
 1,2,1,5,,,30,4
 1,2,1,5,,,30,3
 1,2,1,5,,,30,1
diff --git a/resources/test/instances/Constraint Propagation/Instance_Alain_140624/requests.dat b/resources/test/instances/Constraint Propagation/Instance_Alain_140624/requests.dat
index d4e1219..db51b70 100644
--- a/resources/test/instances/Constraint Propagation/Instance_Alain_140624/requests.dat	
+++ b/resources/test/instances/Constraint Propagation/Instance_Alain_140624/requests.dat	
@@ -1,6 +1,6 @@
 #Global Params (delta ratio)
 1
-#Requests (origin_idx,destination_idx,min_tw_start,max_tw_start,min_tw_end,max_tw_end,delta baseline,capacity)
+#Requests (origin_idx,destination_idx,min_tw_start,max_tw_start,min_tw_end,max_tw_end,delta_time,capacity)
 1,2,3,6,,,16,1
 3,4,6,9,,,8,1
 5,6,11,13,,,18,1
diff --git a/resources/test/instances/Constraint Propagation/Instance_Alain_140624_2/requests.dat b/resources/test/instances/Constraint Propagation/Instance_Alain_140624_2/requests.dat
index 65b3a20..734f753 100644
--- a/resources/test/instances/Constraint Propagation/Instance_Alain_140624_2/requests.dat	
+++ b/resources/test/instances/Constraint Propagation/Instance_Alain_140624_2/requests.dat	
@@ -1,6 +1,6 @@
 #Global Params (delta ratio)
 1
-#Requests (origin_idx,destination_idx,min_tw_start,max_tw_start,min_tw_end,max_tw_end,delta baseline,capacity)
+#Requests (origin_idx,destination_idx,min_tw_start,max_tw_start,min_tw_end,max_tw_end,delta_time,capacity)
 1,2,1,5,,,30,1
 3,4,10,12,,,15,1
 5,6,14,20,,,10,1
diff --git a/resources/test/instances/Constraint Propagation/basic_debug_instance/graph.dat b/resources/test/instances/Constraint Propagation/basic_debug_instance/graph.dat
index 110d845..033b4c0 100644
--- a/resources/test/instances/Constraint Propagation/basic_debug_instance/graph.dat	
+++ b/resources/test/instances/Constraint Propagation/basic_debug_instance/graph.dat	
@@ -10,7 +10,7 @@ work,1,1
 10,0,20,10
 10,20,0,10
 20,10,10,0
-#PT line format : freq (min), start_time, end_time, node_1, ..., node_n
-15,340,560,1,2
+#PT line format : frequency,start_time,end_time,min_travel_time,max_travel_time,node_0, ..., node_n
+15,340,560,1,5,1,2
 #Depot node index
 0
\ No newline at end of file
diff --git a/resources/test/instances/Constraint Propagation/basic_debug_instance/requests.dat b/resources/test/instances/Constraint Propagation/basic_debug_instance/requests.dat
index 59a584e..9826720 100644
--- a/resources/test/instances/Constraint Propagation/basic_debug_instance/requests.dat	
+++ b/resources/test/instances/Constraint Propagation/basic_debug_instance/requests.dat	
@@ -1,6 +1,6 @@
 #Global Params (delta ratio)
 1
-#Requests (origin_idx,destination_idx,min,max,delta baseline,capacity)
+#Requests (origin_idx,destination_idx,min,max,delta_time,capacity)
 0,3,510,540,30,1
 1,2,520,545,25,1
 #Expected result for end route D->R1.O->R2.O->R1.D->R2.D->D : [495;515],[505;520],[515;535],[525;545]
\ No newline at end of file
diff --git a/resources/test/instances/MultimodalHeuristic/instance_alain_140624/even_more_requests.dat b/resources/test/instances/MultimodalHeuristic/instance_alain_140624/even_more_requests.dat
index 6099ca0..c1dac90 100644
--- a/resources/test/instances/MultimodalHeuristic/instance_alain_140624/even_more_requests.dat
+++ b/resources/test/instances/MultimodalHeuristic/instance_alain_140624/even_more_requests.dat
@@ -1,6 +1,6 @@
 #Global Params (delta ratio)
 1
-#Requests (origin_idx,destination_idx,min_tw_start,max_tw_start,min_tw_end,max_tw_end,delta baseline,capacity)
+#Requests (origin_idx,destination_idx,min_tw_start,max_tw_start,min_tw_end,max_tw_end,delta_time,capacity)
 1,2,3,6,,,16,1
 3,4,6,9,,,8,1
 5,6,11,13,,,18,1
diff --git a/resources/test/instances/MultimodalHeuristic/instance_alain_140624/graph.dat b/resources/test/instances/MultimodalHeuristic/instance_alain_140624/graph.dat
index 8f87fdf..778e676 100644
--- a/resources/test/instances/MultimodalHeuristic/instance_alain_140624/graph.dat
+++ b/resources/test/instances/MultimodalHeuristic/instance_alain_140624/graph.dat
@@ -32,10 +32,10 @@
 11,12,4
 12,10,2
 10,0,3
-#PT line format : freq (min), start_time, end_time, node_1, ..., node_n
-5,2,40,1,3,5,6
-5,3,40,6,5,3,1
-3,6,40,7,8,2,12,10,6,0
-3,5,40,0,6,10,12,2,8,7
-4,9,40,14,3,11,9,0,15,6
-4,9,40,6,15,0,9,11,3,14
\ No newline at end of file
+#PT line format : frequency,start_time,end_time,min_travel_time,max_travel_time,node_0, ..., node_n
+5,2,40,1,5,1,3,5,6
+5,3,40,1,5,6,5,3,1
+3,6,40,1,5,7,8,2,12,10,6,0
+3,5,40,1,5,0,6,10,12,2,8,7
+4,9,40,1,5,14,3,11,9,0,15,6
+4,9,40,1,5,6,15,0,9,11,3,14
\ No newline at end of file
diff --git a/resources/test/instances/MultimodalHeuristic/instance_alain_140624/more_requests.dat b/resources/test/instances/MultimodalHeuristic/instance_alain_140624/more_requests.dat
index 12d7cf0..99519c2 100644
--- a/resources/test/instances/MultimodalHeuristic/instance_alain_140624/more_requests.dat
+++ b/resources/test/instances/MultimodalHeuristic/instance_alain_140624/more_requests.dat
@@ -1,6 +1,6 @@
 #Global Params (delta ratio)
 1
-#Requests (origin_idx,destination_idx,min_tw_start,max_tw_start,min_tw_end,max_tw_end,delta baseline,capacity)
+#Requests (origin_idx,destination_idx,min_tw_start,max_tw_start,min_tw_end,max_tw_end,delta_time,capacity)
 1,2,3,6,,,16,1
 3,4,6,9,,,8,1
 5,6,11,13,,,18,1
diff --git a/resources/test/instances/MultimodalHeuristic/instance_alain_140624/requests.dat b/resources/test/instances/MultimodalHeuristic/instance_alain_140624/requests.dat
index d4e1219..db51b70 100644
--- a/resources/test/instances/MultimodalHeuristic/instance_alain_140624/requests.dat
+++ b/resources/test/instances/MultimodalHeuristic/instance_alain_140624/requests.dat
@@ -1,6 +1,6 @@
 #Global Params (delta ratio)
 1
-#Requests (origin_idx,destination_idx,min_tw_start,max_tw_start,min_tw_end,max_tw_end,delta baseline,capacity)
+#Requests (origin_idx,destination_idx,min_tw_start,max_tw_start,min_tw_end,max_tw_end,delta_time,capacity)
 1,2,3,6,,,16,1
 3,4,6,9,,,8,1
 5,6,11,13,,,18,1
diff --git a/resources/test/instances/PT Shortest Path/basic_debug_instance/graph.dat b/resources/test/instances/PT Shortest Path/basic_debug_instance/graph.dat
index 97764d4..a3797f7 100644
--- a/resources/test/instances/PT Shortest Path/basic_debug_instance/graph.dat	
+++ b/resources/test/instances/PT Shortest Path/basic_debug_instance/graph.dat	
@@ -17,5 +17,5 @@
 4,5,2
 5,6,3
 6,7,2
-#PT line format : freq (min), start_time, end_time, node_1, ..., node_n
-15,340,560,3,4,5,6
\ No newline at end of file
+#PT line format : frequency,start_time,end_time,min_travel_time,max_travel_time,node_0, ..., node_n
+15,340,560,1,5,3,4,5,6
\ No newline at end of file
diff --git a/resources/test/instances/PT Shortest Path/contiguous_lines_debug_instance/graph.dat b/resources/test/instances/PT Shortest Path/contiguous_lines_debug_instance/graph.dat
index 67e8ad8..81c2e0e 100644
--- a/resources/test/instances/PT Shortest Path/contiguous_lines_debug_instance/graph.dat	
+++ b/resources/test/instances/PT Shortest Path/contiguous_lines_debug_instance/graph.dat	
@@ -17,8 +17,8 @@
 4,5,2
 5,6,3
 6,7,2
-#PT line format : freq (min), start_time, end_time, node_1, ..., node_n
-15,340,560,3,4,5,6
-15,340,560,6,5,4,3
-30,360,580,2,3,4,5,6,7
-30,240,580,7,6,5,4,3,2
\ No newline at end of file
+#PT line format : frequency,start_time,end_time,min_travel_time,max_travel_time,node_0, ..., node_n
+15,340,560,1,5,3,4,5,6
+15,340,560,1,5,6,5,4,3
+30,360,580,1,5,2,3,4,5,6,7
+30,240,580,1,5,7,6,5,4,3,2
\ No newline at end of file
diff --git a/resources/test/instances/PT Shortest Path/cycling_line_debug_instance/graph.dat b/resources/test/instances/PT Shortest Path/cycling_line_debug_instance/graph.dat
index 5e6abe1..5b703a3 100644
--- a/resources/test/instances/PT Shortest Path/cycling_line_debug_instance/graph.dat	
+++ b/resources/test/instances/PT Shortest Path/cycling_line_debug_instance/graph.dat	
@@ -18,4 +18,4 @@
 5,6,3
 6,7,2
 #PT line format : freq (min), start_time, end_time, node_1, ..., node_n
-30,240,580,7,6,7,5,4,3,2,7
\ No newline at end of file
+30,240,580,1,5,7,6,7,5,4,3,2,7
\ No newline at end of file
diff --git a/resources/test/instances/PT Shortest Path/multiple_crossing_lines_debug_instance/graph.dat b/resources/test/instances/PT Shortest Path/multiple_crossing_lines_debug_instance/graph.dat
index 4cdc53d..c023fff 100644
--- a/resources/test/instances/PT Shortest Path/multiple_crossing_lines_debug_instance/graph.dat	
+++ b/resources/test/instances/PT Shortest Path/multiple_crossing_lines_debug_instance/graph.dat	
@@ -18,9 +18,9 @@
 5,6,3
 6,7,2
 #PT line format : freq (min), start_time, end_time, node_1, ..., node_n
-15,340,560,3,4,5,6
-15,340,560,6,5,4,3
-30,360,580,2,3,4,5,6,7
-30,240,580,7,6,5,4,3,2
-30,290,580,0,4,1
-30,290,580,1,4,0
\ No newline at end of file
+15,340,560,1,5,3,4,5,6
+15,340,560,1,5,6,5,4,3
+30,360,580,1,5,2,3,4,5,6,7
+30,240,580,1,5,7,6,5,4,3,2
+30,290,580,1,5,0,4,1
+30,290,580,1,5,1,4,0
\ No newline at end of file
diff --git a/resources/test/instances/PT Shortest Path/multiple_cycling_lines_debug_instance/graph.dat b/resources/test/instances/PT Shortest Path/multiple_cycling_lines_debug_instance/graph.dat
index 6b69917..05ce249 100644
--- a/resources/test/instances/PT Shortest Path/multiple_cycling_lines_debug_instance/graph.dat	
+++ b/resources/test/instances/PT Shortest Path/multiple_cycling_lines_debug_instance/graph.dat	
@@ -18,10 +18,10 @@
 5,6,3
 6,7,2
 #PT line format : freq (min), start_time, end_time, node_1, ..., node_n
-15,340,560,3,4,5,6,3
-15,340,560,6,5,4,3,6
-30,360,580,2,3,4,5,6,7,2
-30,240,580,7,6,5,4,3,2,7
-30,240,580,7,6,7,5,4,3,2,7
-30,290,580,0,4,1,0
-30,290,580,1,4,0,1
\ No newline at end of file
+15,340,560,1,5,3,4,5,6,3
+15,340,560,1,5,6,5,4,3,6
+30,360,580,1,5,2,3,4,5,6,7,2
+30,240,580,1,5,7,6,5,4,3,2,7
+30,240,580,1,5,7,6,7,5,4,3,2,7
+30,290,580,1,5,0,4,1,0
+30,290,580,1,5,1,4,0,1
\ No newline at end of file
diff --git a/resources/test/instances/PT Shortest Path/single_node_lines_debug_instance/graph.dat b/resources/test/instances/PT Shortest Path/single_node_lines_debug_instance/graph.dat
index 971382a..5c0c715 100644
--- a/resources/test/instances/PT Shortest Path/single_node_lines_debug_instance/graph.dat	
+++ b/resources/test/instances/PT Shortest Path/single_node_lines_debug_instance/graph.dat	
@@ -17,7 +17,7 @@
 4,5,2
 5,6,3
 6,7,2
-#PT line format : freq (min), start_time, end_time, node_1, ..., node_n
-15,340,560,3,3,3,3,3,3,3,3,3
-15,340,560,7,7,7,7,7,7,7,7
-30,360,580,2,3,4,5,6,7
\ No newline at end of file
+#PT line format : frequency,start_time,end_time,min_travel_time,max_travel_time,node_0, ..., node_n
+15,340,560,1,5,3,3,3,3,3,3,3,3,3
+15,340,560,1,5,7,7,7,7,7,7,7,7
+30,360,580,1,5,2,3,4,5,6,7
\ No newline at end of file
diff --git a/resources/test/instances/PT Shortest Path/two_lines_debug_instance/graph.dat b/resources/test/instances/PT Shortest Path/two_lines_debug_instance/graph.dat
index 813e885..7b7103b 100644
--- a/resources/test/instances/PT Shortest Path/two_lines_debug_instance/graph.dat	
+++ b/resources/test/instances/PT Shortest Path/two_lines_debug_instance/graph.dat	
@@ -17,6 +17,6 @@
 4,5,2
 5,6,3
 6,7,2
-#PT line format : freq (min), start_time, end_time, node_1, ..., node_n
-15,340,560,3,4,5,6
-30,360,580,0,1,2,3,7
\ No newline at end of file
+#PT line format : frequency,start_time,end_time,min_travel_time,max_travel_time,node_0, ..., node_n
+15,340,560,1,5,3,4,5,6
+30,360,580,1,5,0,1,2,3,7
\ No newline at end of file
diff --git a/resources/test/instances/graph preprocess/book example/graph.dat b/resources/test/instances/graph preprocess/book example/graph.dat
index f12c12d..1969ed8 100644
--- a/resources/test/instances/graph preprocess/book example/graph.dat	
+++ b/resources/test/instances/graph preprocess/book example/graph.dat	
@@ -12,7 +12,7 @@ work,2,1
 -1,3,0,-1,2
 -1,-1,-1,0,4
 7,-1,-1,6,0
-#PT line format : freq (min), start_time, end_time, node_1, ..., node_n
-15,340,560,1,2
+#PT line format : frequency,start_time,end_time,min_travel_time,max_travel_time,node_0, ..., node_n
+15,340,560,1,5,1,2
 #Depot node index
 0
\ No newline at end of file
-- 
GitLab


From 1adf1be6b57d4360b28992955f36156191c27a7c Mon Sep 17 00:00:00 2001
From: Romain BERNARD <romain.bernard@uca.fr>
Date: Wed, 18 Sep 2024 18:50:03 +0200
Subject: [PATCH 308/327] add new debug instance

---
 .../basic debug multimodal/graph.dat          | 17 +++++++++
 .../basic debug multimodal/requests.dat       |  4 +++
 .../src/MultimodalInsertionHeuristicDebug.cpp | 36 +++++++++++++++++--
 3 files changed, 55 insertions(+), 2 deletions(-)
 create mode 100644 resources/test/instances/MultimodalHeuristic/basic debug multimodal/graph.dat
 create mode 100644 resources/test/instances/MultimodalHeuristic/basic debug multimodal/requests.dat

diff --git a/resources/test/instances/MultimodalHeuristic/basic debug multimodal/graph.dat b/resources/test/instances/MultimodalHeuristic/basic debug multimodal/graph.dat
new file mode 100644
index 0000000..f7acda2
--- /dev/null
+++ b/resources/test/instances/MultimodalHeuristic/basic debug multimodal/graph.dat	
@@ -0,0 +1,17 @@
+#Params (seed)
+123456789
+#Nodes format : status (work, leisure, residential),x,y
+,0,0
+,8,4
+,1,1
+,3,3
+#Edges start,end,length
+0,3,30
+#PT line fixed
+1,2
+10,15
+20,25
+30,35
+40,45
+50,55
+60,65
\ No newline at end of file
diff --git a/resources/test/instances/MultimodalHeuristic/basic debug multimodal/requests.dat b/resources/test/instances/MultimodalHeuristic/basic debug multimodal/requests.dat
new file mode 100644
index 0000000..35ee223
--- /dev/null
+++ b/resources/test/instances/MultimodalHeuristic/basic debug multimodal/requests.dat	
@@ -0,0 +1,4 @@
+#Global Params (delta ratio)
+2
+#Requests (origin_idx,destination_idx,min_tw_start,max_tw_start,min_tw_end,max_tw_end,delta_time,capacity)
+0,3,10,30,40,60,,1
\ No newline at end of file
diff --git a/test/src/MultimodalInsertionHeuristicDebug.cpp b/test/src/MultimodalInsertionHeuristicDebug.cpp
index ea91b2d..b21989d 100644
--- a/test/src/MultimodalInsertionHeuristicDebug.cpp
+++ b/test/src/MultimodalInsertionHeuristicDebug.cpp
@@ -10,6 +10,38 @@
 #include "../../src/algorithm/Multimodal/Heuristics/MultimodalModularHeuristic.h"
 #include "../../src/utils/Instance Generation/Requests/RequestsGenerator.h"
 
+TEST(MultimodalInsertionHeuristicDebug, DebugBasicInstance) {
+    std::string instancesPath = "../../resources/test/instances/MultimodalHeuristic/";
+    std::string instanceName = "basic debug multimodal/";
+    std::string graphFile = "graph.dat";
+    std::string requestsFile = "requests.dat";
+
+
+    //Parse graph
+    INIT_TIMER
+    Graph graphFromSingleFile(instancesPath + instanceName + graphFile);
+    std::vector<Request> requests = Request::getRequestsFromFile(instancesPath + instanceName + requestsFile, graphFromSingleFile);
+
+    //Init instance
+    Instance instance(requests,graphFromSingleFile,4);
+    SAEVRoute routesContainer(graphFromSingleFile, requests, true);
+    MultimodalModularHeuristic multimodalHeuristic(&graphFromSingleFile, &routesContainer, &requests);
+    STOP_TIMER("Instance parsing and init")
+    std::cout << "------------------Fin parsing instance et route-------------------" << std::endl << std::endl;
+
+    std::cout << "------------------Start preprocessings-------------------" << std::endl << std::endl;
+    START_TIMER
+    graphFromSingleFile.computeAndUpdateShortestTransitPaths();
+    STOP_TIMER("Preprocess")
+    std::cout << "------------------End preprocessings-------------------" << std::endl << std::endl;
+    std::cout << "------------------Start multimodal insertion-------------------" << std::endl << std::endl;
+    START_TIMER
+    graphFromSingleFile.computeAndUpdateShortestPathsMatrix(true);
+    multimodalHeuristic.doMultimodalRequestsInsertion();
+    STOP_TIMER("Multimodal insertion")
+    std::cout << "------------------End multimodal insertion-------------------" << std::endl << std::endl;
+}
+
 TEST(MultimodalInsertionHeuristicDebug, DebugBaseInstance) {
     std::string instancesPath = "../../resources/test/instances/PT Shortest Path/";
     std::string instanceFolder = "contiguous_lines_debug_instance/";
@@ -19,7 +51,7 @@ TEST(MultimodalInsertionHeuristicDebug, DebugBaseInstance) {
     //Parse graph
     INIT_TIMER
     Graph graphFromSingleFile(instancesPath + instanceFolder + datFile);
-    graphFromSingleFile.computeAndUpdateShortestPathsMatrix(true);
+    graphFromSingleFile.computeAndUpdateShortestPathsMatrix(true); //compute shortest paths before generating requests since we need shortest paths
     RequestGenerationParameters genParams(1, 1.5, 15,30,300,600,290820241032L);
     std::vector<Request> requests = RequestsGenerator::generateRequests(graphFromSingleFile, genParams);
 
@@ -61,7 +93,7 @@ TEST(MultimodalInsertionHeuristicDebug, DebugInstanceAlain) {
     //Parse graph
     INIT_TIMER
     Graph graphFromSingleFile(instancesPath + instanceFolder + graphDatFile);
-    graphFromSingleFile.computeAndUpdateShortestPathsMatrix(true);
+    graphFromSingleFile.computeAndUpdateShortestPathsMatrix(true);  //compute shortest paths before generating requests since we need shortest paths
     std::vector<Request> requests = Request::getRequestsFromFile(instancesPath + instanceFolder + requestDatFile, graphFromSingleFile);
 
     //Init instance
-- 
GitLab


From 7667106e953f3c3ac12429a1cbe6d7d3de99784c Mon Sep 17 00:00:00 2001
From: Romain BERNARD <romain.bernard@uca.fr>
Date: Wed, 18 Sep 2024 18:50:14 +0200
Subject: [PATCH 309/327] fix path

---
 src/instance/graph/Node.h | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/src/instance/graph/Node.h b/src/instance/graph/Node.h
index 7285f81..2700a28 100644
--- a/src/instance/graph/Node.h
+++ b/src/instance/graph/Node.h
@@ -10,7 +10,7 @@
 #include <set>
 #include <unordered_map>
 #include <vector>
-#include "../../ShortestPath/Vehicle/ClosestDestinationsContainer.h"
+#include "../../algorithm/ShortestPath/Vehicle/ClosestDestinationsContainer.h"
 
 /**
  * Status used to qualify nodes as places with different goals (work, leisure, residential)
-- 
GitLab


From cf8aa4c4614f61b592e56156f12b4ee6f574cd5b Mon Sep 17 00:00:00 2001
From: Romain BERNARD <romain.bernard@uca.fr>
Date: Thu, 19 Sep 2024 17:11:59 +0200
Subject: [PATCH 310/327] add class architecture TODO

---
 .../Multimodal/Heuristics/MultimodalModularHeuristic.h       | 5 +++++
 1 file changed, 5 insertions(+)

diff --git a/src/algorithm/Multimodal/Heuristics/MultimodalModularHeuristic.h b/src/algorithm/Multimodal/Heuristics/MultimodalModularHeuristic.h
index 5d09984..324b046 100644
--- a/src/algorithm/Multimodal/Heuristics/MultimodalModularHeuristic.h
+++ b/src/algorithm/Multimodal/Heuristics/MultimodalModularHeuristic.h
@@ -29,6 +29,11 @@ private:
     const std::vector<Request>* _requestsVect{nullptr};
     SAEVRoute* _route{nullptr}; //_route is a pointer here to decorrelate the route from the algorithm and facilitate using multiple modules on the same route
 
+    //TODO: Move the diverse components (min/max constraints, get best entries/exits list etc) to their own classes to be used as delegates/decorator-like pattern
+    //      This would have the added benefit of easier customisation. Just have a common "apply()" function, and give useful data in constructor
+    //      => every inheritor just has an apply() method, used here, returning the appropriate data,
+    //         but child class constructor can be free to have all the data we want
+
     /**
      * Vector holding every entry sub request created to prevent refs staleness
      * while letting the requests vector hold only the base requests \n
-- 
GitLab


From 2bd52af0a54558781a09b978f25b9990098a35aa Mon Sep 17 00:00:00 2001
From: Romain BERNARD <romain.bernard@uca.fr>
Date: Thu, 19 Sep 2024 17:12:45 +0200
Subject: [PATCH 311/327] redefine debug messages to use the appropriate macro

---
 .../Heuristics/MultimodalModularHeuristic.cpp          | 10 +++++-----
 .../Multimodal/Heuristics/MultimodalModularHeuristic.h |  4 ++--
 2 files changed, 7 insertions(+), 7 deletions(-)

diff --git a/src/algorithm/Multimodal/Heuristics/MultimodalModularHeuristic.cpp b/src/algorithm/Multimodal/Heuristics/MultimodalModularHeuristic.cpp
index 42264b9..df97c77 100644
--- a/src/algorithm/Multimodal/Heuristics/MultimodalModularHeuristic.cpp
+++ b/src/algorithm/Multimodal/Heuristics/MultimodalModularHeuristic.cpp
@@ -88,7 +88,7 @@ MultimodalModularHeuristic::insertBestTransitAccessInRoute(const Request &baseRe
                                                    _route->getEntrySubRequestOrigin(baseRequestId));
         }
         catch(const TimeWindow::invalid_time_window_exception& e) {
-            DEBUG_MSG("Invalid Time Window during candidate sub request creation, it won't be added to the list");
+            DEBUG_MMH_MSG("Invalid Time Window during candidate sub request creation, it won't be added to the list");
         }
     }
     return insertBestTransitAccessInRoute(accessSubRequestsList, baseRequestId, isEntry);
@@ -112,17 +112,17 @@ MultimodalModularHeuristic::insertBestTransitAccessInRoute(const std::vector<Req
                 _route->getEntrySubRequestOrigin(baseRequestId), *_route);
         //If we've found an insertion that doesn't create a vehicle, stop there
         if(changeList.success()) {
-            DEBUG_MSG("ENTRY CANDIDATE SUCCESS : " + subreq.to_string());
+            DEBUG_MMH_MSG("ENTRY CANDIDATE SUCCESS : " + subreq.to_string());
             return getSubrequest(baseRequestId, isEntry);
         } else {
-            DEBUG_MSG("ENTRY CANDIDATE FAILURE : " + subreq.to_string());
+            DEBUG_MMH_MSG("ENTRY CANDIDATE FAILURE : " + subreq.to_string());
         }
     }
 
     // If no valid candidate was given, still create a fake
     // subrequest and mention failure in the appropriate vector
     if(accessSubRequestsList.empty()) {
-        DEBUG_MSG("UNFULFILLED SUBREQUEST");
+        DEBUG_MMH_MSG(std::string("UNFULFILLED SUBREQUEST ") + (isEntry ? "ENTRY" : "EXIT"));
         updateSubRequest(baseRequestId, (*_requestsVect)[baseRequestId], isEntry);
         updateUnfulfilledSubrequest(baseRequestId, isEntry, true); //mark failures for debug/statistics
         if(!isEntry) { //Exit subrequest : remove entry subrequest and add baseRequest to the "unfulfilled list"
@@ -132,7 +132,7 @@ MultimodalModularHeuristic::insertBestTransitAccessInRoute(const std::vector<Req
     } else {
         // If no active vehicle insertion worked, do best insertion on a new vehicle
         // with the first subrequest (supposedly it's the most advantageous)
-        DEBUG_MSG("CREATE VEHICLE");
+        DEBUG_MMH_MSG("CREATE VEHICLE");
         updateSubRequest(baseRequestId, accessSubRequestsList[0], isEntry);
         _route->insertRequestInNewVehicle(_route->getExitSubRequestOrigin(baseRequestId));
     }
diff --git a/src/algorithm/Multimodal/Heuristics/MultimodalModularHeuristic.h b/src/algorithm/Multimodal/Heuristics/MultimodalModularHeuristic.h
index 324b046..94d3f61 100644
--- a/src/algorithm/Multimodal/Heuristics/MultimodalModularHeuristic.h
+++ b/src/algorithm/Multimodal/Heuristics/MultimodalModularHeuristic.h
@@ -17,9 +17,9 @@
 
 #ifdef DEBUG_MULTIMODAL_HEURISTIC
 #include <iostream>
-#define DEBUG_MSG(str) do { std::cout << "[SMH] " << str << std::endl; } while( false )
+#define DEBUG_MMH_MSG(str) do { std::cout << "[MMH] " << str << std::endl; } while( false )
 #else
-#define DEBUG_MSG(str) do { } while ( false )
+#define DEBUG_MMH_MSG(str) do { } while ( false )
 #endif
 
 class MultimodalModularHeuristic {
-- 
GitLab


From 4ab3e4782f80a32a1d676987cf445f91aac4fb68 Mon Sep 17 00:00:00 2001
From: Romain BERNARD <romain.bernard@uca.fr>
Date: Thu, 19 Sep 2024 17:13:40 +0200
Subject: [PATCH 312/327] limit risks of overflow

---
 .../ShortestPath/Vehicle/VehicleShortestPathCalculation.cpp | 6 +++---
 1 file changed, 3 insertions(+), 3 deletions(-)

diff --git a/src/algorithm/ShortestPath/Vehicle/VehicleShortestPathCalculation.cpp b/src/algorithm/ShortestPath/Vehicle/VehicleShortestPathCalculation.cpp
index d7507cb..159d27c 100644
--- a/src/algorithm/ShortestPath/Vehicle/VehicleShortestPathCalculation.cpp
+++ b/src/algorithm/ShortestPath/Vehicle/VehicleShortestPathCalculation.cpp
@@ -10,7 +10,7 @@
 std::vector<uint>
 VehicleShortestPathCalculation::computeShortestPathsFromNode(Graph &graph, size_t startingNodeIdx, bool useEdges) {
     std::vector<uint> results;
-    results.resize(graph.getNbNodes(), UINT32_MAX);
+    results.resize(graph.getNbNodes(), INT16_MAX);
 
     if(!useEdges) {
         results = graph.getShortestSaevPaths()[startingNodeIdx];
@@ -92,7 +92,7 @@ VehicleShortestPathCalculation::getClosestPTNodesFromX(const Graph &graph, size_
 void VehicleShortestPathCalculation::expandStatesViaMatrix(const VehiclePathState& currentState, std::vector<uint> &results,
                                                            std::priority_queue<VehiclePathState, std::vector<VehiclePathState>, std::greater<>> &stateQueue,
                                                            const Graph& graph) {
-    uint newDistance = INT32_MAX;
+    uint newDistance = INT16_MAX;
     for(size_t i = 0; i < results.capacity(); ++i) {
         newDistance = currentState.getInstant() + graph.getShortestSAEVPath(currentState.getNodeIndex(), i);
         if(newDistance < results[i]) {
@@ -105,7 +105,7 @@ void VehicleShortestPathCalculation::expandStatesViaMatrix(const VehiclePathStat
 void VehicleShortestPathCalculation::expandStatesViaEdges(const VehiclePathState &currentState, std::vector<uint> &results,
                                                           std::priority_queue<VehiclePathState, std::vector<VehiclePathState>, std::greater<>> &stateQueue,
                                                           const Graph& graph) {
-    uint newDistance = INT32_MAX;
+    uint newDistance = INT16_MAX;
     for(const auto& edgeIndex : graph.getNode(currentState.getNodeIndex()).getOutgoingEdges()) {
         const Edge& edge = graph.getEdge(edgeIndex);
         newDistance = currentState.getInstant() + edge.getLength();
-- 
GitLab


From e8f5fb2c649104934085af001e7c0a7212f02d6d Mon Sep 17 00:00:00 2001
From: Romain BERNARD <romain.bernard@uca.fr>
Date: Thu, 19 Sep 2024 17:15:44 +0200
Subject: [PATCH 313/327] transform to lowercase before doing string comparison

---
 src/instance/graph/Graph.cpp | 22 +++++++++++++++-------
 1 file changed, 15 insertions(+), 7 deletions(-)

diff --git a/src/instance/graph/Graph.cpp b/src/instance/graph/Graph.cpp
index 9d6b9ec..77ac5fe 100644
--- a/src/instance/graph/Graph.cpp
+++ b/src/instance/graph/Graph.cpp
@@ -87,28 +87,34 @@ Graph::Graph(const std::string& datFilePath) {
     //-- End of nodes
 
     //Node links (edges or matrix)
-    if(currentRow[0].starts_with("#Edges")) {
+    std::string lowercaseRow = currentRow.toString();
+    std::ranges::transform(lowercaseRow, lowercaseRow.begin(), ::tolower);
+    if(lowercaseRow.starts_with("#edges")) {
         //-- Read Edges
         std::cout << currentRow.toString() << std::endl;
         while (infile >> currentRow && !currentRow[0].starts_with('#')) {
             this->parseEdgeRow(currentRow);
         }
         //-- End of edges
-    } else if (currentRow[0].starts_with("#Matrix")) {
+    } else if (lowercaseRow.starts_with("#matrix")) {
         //-- Read Distance matrix
         std::cout << currentRow.toString() << std::endl;
         this->parseDistanceMatrix(infile, currentRow);
         //-- End of edges
     }
 
-    if(currentRow[0].starts_with("#Depot")) {
+    lowercaseRow = currentRow.toString();
+    std::ranges::transform(lowercaseRow, lowercaseRow.begin(), ::tolower);
+    if(lowercaseRow.starts_with("#depot")) {
         infile >> currentRow;
         std::from_chars(currentRow[0].data(), currentRow[0].data() + currentRow[0].length(), _depotNodeIdx);
     }
 
     //-- Read Public transit line
     std::cout << currentRow.toString() << std::endl;
-    if(currentRow[0].starts_with("#PT Line fixed")) {
+    lowercaseRow = currentRow.toString();
+    std::ranges::transform(lowercaseRow, lowercaseRow.begin(), ::tolower);
+    if(lowercaseRow.starts_with("#pt line fixed")) {
         while(infile >> currentRow && !currentRow[0].starts_with('#')) {
             this->parseLineFixedSchedule(infile, currentRow);
         }
@@ -258,7 +264,7 @@ void Graph::parseLineRandomizedSchedule(const DATRow& row, std::mt19937 rng)
 {
     int startTime, endTime, frequency, minTravelTime, maxTravelTime, currentNodeIdx;
     //add nodes for the line
-    Line newLine = Line();
+    Line newLine{};
     //Give it an ID
     //TODO : use proper IDs in parsing for line names
     newLine.setLineId(std::to_string(this->transitLines.size()));
@@ -318,12 +324,14 @@ void Graph::parseLineFixedSchedule(std::ifstream& infile, DATRow& row) {
     }
 
     // Read schedule until hitting an empty line, used to separate individual lines to parse
-    std::vector<std::vector<int>> newSchedules;
+    int scheduledTime;
+    std::vector<std::vector<int>> newSchedules{newLine.size()};
     while(infile >> row && !row[0].empty()) {
         assertm(row.size() == newLine.size(), "Schedule size doesn't correspond to the number of nodes");
         // Add the time to the appropriate station's schedule vector
         for(uint stationIdx = 0; stationIdx < row.size(); ++stationIdx) {
-            newSchedules[stationIdx].emplace_back(std::stoi(row[stationIdx].data()));
+            std::from_chars(row[stationIdx].data(), row[stationIdx].data() + row[stationIdx].size(), scheduledTime);
+            newSchedules[stationIdx].emplace_back(scheduledTime);
         }
     }
 
-- 
GitLab


From e2dbe02c1e228d9ecdcbd6404c0acda0a3e103be Mon Sep 17 00:00:00 2001
From: Romain BERNARD <romain.bernard@uca.fr>
Date: Thu, 19 Sep 2024 17:16:08 +0200
Subject: [PATCH 314/327] doc formatting

---
 src/routes/vehicle/SAEVRoute.h | 7 ++++---
 1 file changed, 4 insertions(+), 3 deletions(-)

diff --git a/src/routes/vehicle/SAEVRoute.h b/src/routes/vehicle/SAEVRoute.h
index 3f08d5b..39ae4f2 100644
--- a/src/routes/vehicle/SAEVRoute.h
+++ b/src/routes/vehicle/SAEVRoute.h
@@ -121,9 +121,10 @@ public:
     SAEVRouteChangelist tryAddRequest(SAEVKeyPoint &requestOriginKeyPoint, SAEVKeyPoint * originRequestPredecessorKP, SAEVKeyPoint * destinationRequestPredecessorKP);
 
     /**
-     * Verifies time window constraints on our request's origin/destination's projected neighbour, aka originPredecessor/destinationPredecessor and their successor.
-     * There is a special case taken into account if originPredecessor and destinationPredecessor are the same KeyPoint, since then, Origin's successor would be Destination
-     * ⚠️ Weight constraints are checked separately
+     * Verifies time window constraints on our request's origin/destination's projected neighbour, aka originPredecessor/destinationPredecessor and their successor. <br>
+     * There is a special case taken into account if originPredecessor and destinationPredecessor are the same KeyPoint, since then, Origin's successor would be Destination <br>
+     * <br>
+     * ⚠️ Weight constraints are checked separately <br>
      * ⚠️ Those checks don't modify the route => no rollback is needed at this point
      * @param originKP Reference to the origin key point of our request, necessary to retrieve the appropriate key points
      * @param originNodeIndex The request's origin node index, necessary to compute travel times
-- 
GitLab


From bfc0dbbd598b22148a0396490e4f438cbf878134 Mon Sep 17 00:00:00 2001
From: Romain BERNARD <romain.bernard@uca.fr>
Date: Thu, 19 Sep 2024 17:16:56 +0200
Subject: [PATCH 315/327] account for the case where both departure and arrival
 TWs are given

---
 src/instance/requests/Request.cpp | 15 ++++++++++-----
 1 file changed, 10 insertions(+), 5 deletions(-)

diff --git a/src/instance/requests/Request.cpp b/src/instance/requests/Request.cpp
index 20effe1..57ca2cc 100644
--- a/src/instance/requests/Request.cpp
+++ b/src/instance/requests/Request.cpp
@@ -60,15 +60,20 @@ Request::Request(const DATRow& currentRow, const Graph& graph) {
         std::from_chars(currentRow[5].data(), currentRow[5].data() + currentRow[5].size(), _weight);
     }
 
-
-    if(!setDepartureTW) {
+    //If set arrival but not departure, deduce it from delta
+    if(!setDepartureTW && setArrivalTW) {
         _departureTW.min = _arrivalTW.min - _deltaTime;
         _departureTW.max = _arrivalTW.max - graph.getShortestSAEVPath(_originNodeIndex, _destinationNodeIndex);
-    }
-    if(!setArrivalTW) {
+    //If set departure but not arrival, deduce it from delta
+    } else if(setDepartureTW && !setArrivalTW) {
         _arrivalTW.min = _departureTW.min + graph.getShortestSAEVPath(_originNodeIndex, _destinationNodeIndex);
         _arrivalTW.max = _departureTW.max + _deltaTime;
+    //If both TWs are set, override delta which might not be set
+    } else if(setDepartureTW && setArrivalTW) {
+        _deltaTime = _arrivalTW.max - _departureTW.max;
     }
+
+    //Check TWs at the end
     if(_departureTW.min > _departureTW.max || _arrivalTW.min > _arrivalTW.max)
         throw TimeWindow::invalid_time_window_exception();
 }
@@ -82,7 +87,7 @@ std::vector<Request> Request::getRequestsFromFile(const std::string& datFilePath
 
     std::ifstream infile(datFilePath);
     assertm(!infile.fail(), "Failed to open the given file");
-    DATRow currentRow = DATRow(',');
+    DATRow currentRow(',');
 
     //-- Read params
     infile >> currentRow;
-- 
GitLab


From f8e645164f5827b3a18bcf07ba3f9c4c4e7c4ac4 Mon Sep 17 00:00:00 2001
From: Romain BERNARD <romain.bernard@uca.fr>
Date: Thu, 19 Sep 2024 18:03:32 +0200
Subject: [PATCH 316/327] fix max condition application for entries and exits

---
 .../Multimodal/Heuristics/MultimodalModularHeuristic.cpp      | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/src/algorithm/Multimodal/Heuristics/MultimodalModularHeuristic.cpp b/src/algorithm/Multimodal/Heuristics/MultimodalModularHeuristic.cpp
index df97c77..588ca10 100644
--- a/src/algorithm/Multimodal/Heuristics/MultimodalModularHeuristic.cpp
+++ b/src/algorithm/Multimodal/Heuristics/MultimodalModularHeuristic.cpp
@@ -20,7 +20,7 @@ std::vector<TransitAccess> MultimodalModularHeuristic::getBestTransitEntriesList
             const auto& lineStop : bestStationNode.getPTLinesSet()) {
             //Find the next passage lower or equal to our max entry time constraint
             auto iterator = lineStop.findNextScheduledPassage(getMaxEntryConstraint(baseRequest, bestStationNodeIdx));
-            if(iterator != lineStop.getSchedule().cbegin() && iterator != lineStop.getSchedule().cend()) { //Iterator is invalid if it points to schedule end (no result) or begin (no result lower than our constraint)
+            if(iterator != lineStop.getSchedule().cbegin()) { //Iterator is invalid if it points to schedule beginning (no result lower than our constraint)
                 --iterator; //Move iterator to the value that's under our max entry constraint
                 if(*iterator > maxDepartureTime //If we've found a valid time that's superior to our current max time
                 && *iterator > getMinEntryConstraint(baseRequest, bestStationNodeIdx)) { //and respects min entry time, replace old value
@@ -221,7 +221,7 @@ MultimodalModularHeuristic::getBestTransitExitsList(size_t baseRequestId, const
     for(const auto& shortestTransitPath : shortestTransitPaths) {
         //Check valid transit path + arrival node != starting point
         if(shortestTransitPath.getArrivalTime() >= 0 && shortestTransitPath.getArrivalNode() != entryNodeIdx
-        && shortestTransitPath.getArrivalTime() < getMaxExitConstraint(baseRequestId, entrySubRequestOriginKP, shortestTransitPath.getArrivalNode())) {
+        && shortestTransitPath.getArrivalTime() <= getMaxExitConstraint(baseRequestId, entrySubRequestOriginKP, shortestTransitPath.getArrivalNode())) {
             TransitAccess exit{shortestTransitPath.getArrivalNode(),  (uint) shortestTransitPath.getArrivalTime()};
             scoredTransitExits.emplace_back(exit, getTransitExitScore(baseRequest, exit));
         }
-- 
GitLab


From 29cf656331d84641e7cac59b062f5ae1457da3b4 Mon Sep 17 00:00:00 2001
From: Romain BERNARD <romain.bernard@uca.fr>
Date: Thu, 19 Sep 2024 18:06:57 +0200
Subject: [PATCH 317/327] move preprocess to time it with other shortest path

---
 test/src/MultimodalInsertionHeuristicDebug.cpp | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/test/src/MultimodalInsertionHeuristicDebug.cpp b/test/src/MultimodalInsertionHeuristicDebug.cpp
index b21989d..ef34db5 100644
--- a/test/src/MultimodalInsertionHeuristicDebug.cpp
+++ b/test/src/MultimodalInsertionHeuristicDebug.cpp
@@ -32,11 +32,11 @@ TEST(MultimodalInsertionHeuristicDebug, DebugBasicInstance) {
     std::cout << "------------------Start preprocessings-------------------" << std::endl << std::endl;
     START_TIMER
     graphFromSingleFile.computeAndUpdateShortestTransitPaths();
+    graphFromSingleFile.computeAndUpdateShortestPathsMatrix(true);
     STOP_TIMER("Preprocess")
     std::cout << "------------------End preprocessings-------------------" << std::endl << std::endl;
     std::cout << "------------------Start multimodal insertion-------------------" << std::endl << std::endl;
     START_TIMER
-    graphFromSingleFile.computeAndUpdateShortestPathsMatrix(true);
     multimodalHeuristic.doMultimodalRequestsInsertion();
     STOP_TIMER("Multimodal insertion")
     std::cout << "------------------End multimodal insertion-------------------" << std::endl << std::endl;
-- 
GitLab


From f288e90fc9eae24cb9ece768ec5a51b1b9db49a8 Mon Sep 17 00:00:00 2001
From: Romain BERNARD <romain.bernard@uca.fr>
Date: Thu, 19 Sep 2024 19:22:59 +0200
Subject: [PATCH 318/327] Add necessary data to instance for the algorithm to
 have the required shortest paths be compatible

---
 .../basic debug multimodal/graph.dat                | 13 ++++++++-----
 .../basic debug multimodal/requests.dat             |  2 +-
 2 files changed, 9 insertions(+), 6 deletions(-)

diff --git a/resources/test/instances/MultimodalHeuristic/basic debug multimodal/graph.dat b/resources/test/instances/MultimodalHeuristic/basic debug multimodal/graph.dat
index f7acda2..5d36ab9 100644
--- a/resources/test/instances/MultimodalHeuristic/basic debug multimodal/graph.dat	
+++ b/resources/test/instances/MultimodalHeuristic/basic debug multimodal/graph.dat	
@@ -6,12 +6,15 @@
 ,1,1
 ,3,3
 #Edges start,end,length
-0,3,30
+0,1,5
+0,2,10
+0,3,20
+1,0,5
+1,3,15
+2,3,5
+3,0,20
 #PT line fixed
 1,2
 10,15
 20,25
-30,35
-40,45
-50,55
-60,65
\ No newline at end of file
+30,35
\ No newline at end of file
diff --git a/resources/test/instances/MultimodalHeuristic/basic debug multimodal/requests.dat b/resources/test/instances/MultimodalHeuristic/basic debug multimodal/requests.dat
index 35ee223..308a1af 100644
--- a/resources/test/instances/MultimodalHeuristic/basic debug multimodal/requests.dat	
+++ b/resources/test/instances/MultimodalHeuristic/basic debug multimodal/requests.dat	
@@ -1,4 +1,4 @@
 #Global Params (delta ratio)
-2
+1
 #Requests (origin_idx,destination_idx,min_tw_start,max_tw_start,min_tw_end,max_tw_end,delta_time,capacity)
 0,3,10,30,40,60,,1
\ No newline at end of file
-- 
GitLab


From 946d2a6928192835840a795d7f6389f4578f9fab Mon Sep 17 00:00:00 2001
From: Romain BERNARD <romain.bernard@uca.fr>
Date: Thu, 19 Sep 2024 19:24:34 +0200
Subject: [PATCH 319/327] fix cases where isEntry wasn't used to differentiate
 transit entry/exit

---
 .../Heuristics/MultimodalModularHeuristic.cpp         | 11 ++++++++---
 src/routes/vehicle/SAEVRoute.cpp                      |  7 +++++++
 src/routes/vehicle/SAEVRoute.h                        |  2 ++
 3 files changed, 17 insertions(+), 3 deletions(-)

diff --git a/src/algorithm/Multimodal/Heuristics/MultimodalModularHeuristic.cpp b/src/algorithm/Multimodal/Heuristics/MultimodalModularHeuristic.cpp
index 588ca10..07fbcc0 100644
--- a/src/algorithm/Multimodal/Heuristics/MultimodalModularHeuristic.cpp
+++ b/src/algorithm/Multimodal/Heuristics/MultimodalModularHeuristic.cpp
@@ -109,7 +109,7 @@ MultimodalModularHeuristic::insertBestTransitAccessInRoute(const std::vector<Req
     for(const auto& subreq : accessSubRequestsList) {
         updateSubRequest(baseRequestId, subreq, isEntry);
         SAEVRouteChangelist changeList = BestInsertionHeuristic::tryBestRequestInsertionInActiveVehicle(
-                _route->getEntrySubRequestOrigin(baseRequestId), *_route);
+                _route->getSubRequestOrigin(baseRequestId, isEntry), *_route);
         //If we've found an insertion that doesn't create a vehicle, stop there
         if(changeList.success()) {
             DEBUG_MMH_MSG("ENTRY CANDIDATE SUCCESS : " + subreq.to_string());
@@ -162,8 +162,13 @@ void MultimodalModularHeuristic::updateSubRequest(size_t requestId, const Reques
     else
         _exitSubRequests[requestId] = request;
 
-    _route->getEntrySubRequestOrigin(requestId).setRequest(&getSubrequest(requestId, isEntry));
-    _route->getEntrySubRequestDestination(requestId).setRequest(&getSubrequest(requestId, isEntry));
+    if(isEntry) {
+        _route->getEntrySubRequestOrigin(requestId).setRequest(&getSubrequest(requestId, isEntry));
+        _route->getEntrySubRequestDestination(requestId).setRequest(&getSubrequest(requestId, isEntry));
+    } else {
+        _route->getExitSubRequestOrigin(requestId).setRequest(&getSubrequest(requestId, isEntry));
+        _route->getExitSubRequestDestination(requestId).setRequest(&getSubrequest(requestId, isEntry));
+    }
 }
 
 const Request& MultimodalModularHeuristic::getSubrequest(size_t requestId, bool isEntry) {
diff --git a/src/routes/vehicle/SAEVRoute.cpp b/src/routes/vehicle/SAEVRoute.cpp
index 818a394..8b11c80 100644
--- a/src/routes/vehicle/SAEVRoute.cpp
+++ b/src/routes/vehicle/SAEVRoute.cpp
@@ -565,3 +565,10 @@ SAEVRouteChangelist SAEVRoute::removeRequestWithPropagation(size_t requestId) {
     return removeRequestWithPropagation(getRequestOrigin(requestId));
 }
 
+SAEVKeyPoint &SAEVRoute::getSubRequestOrigin(size_t baseRequestId, bool isEntry) {
+    if(isEntry)
+        return getEntrySubRequestOrigin(baseRequestId);
+    else
+        return getExitSubRequestOrigin(baseRequestId);
+}
+
diff --git a/src/routes/vehicle/SAEVRoute.h b/src/routes/vehicle/SAEVRoute.h
index 39ae4f2..78ddd58 100644
--- a/src/routes/vehicle/SAEVRoute.h
+++ b/src/routes/vehicle/SAEVRoute.h
@@ -231,6 +231,8 @@ public:
      */
     std::string to_string(size_t vehicleId);
     void exportToFile();
+
+    SAEVKeyPoint &getSubRequestOrigin(size_t baseRequestId, bool isEntry);
 };
 
 #include "propagation/SAEVRouteChangelist.h"
-- 
GitLab


From a4f0fa9a54c749b8095a1db095ac99ceab144bc4 Mon Sep 17 00:00:00 2001
From: Romain BERNARD <romain.bernard@uca.fr>
Date: Thu, 19 Sep 2024 19:25:41 +0200
Subject: [PATCH 320/327] improve debug messages for heuristic

---
 .../Heuristics/MultimodalModularHeuristic.cpp |  5 +--
 .../propagation/SAEVRouteChangelist.cpp       | 35 +++++++++++++++++++
 .../vehicle/propagation/SAEVRouteChangelist.h |  6 ++++
 test/CMakeLists.txt                           |  1 +
 4 files changed, 45 insertions(+), 2 deletions(-)

diff --git a/src/algorithm/Multimodal/Heuristics/MultimodalModularHeuristic.cpp b/src/algorithm/Multimodal/Heuristics/MultimodalModularHeuristic.cpp
index 07fbcc0..941bd71 100644
--- a/src/algorithm/Multimodal/Heuristics/MultimodalModularHeuristic.cpp
+++ b/src/algorithm/Multimodal/Heuristics/MultimodalModularHeuristic.cpp
@@ -112,10 +112,11 @@ MultimodalModularHeuristic::insertBestTransitAccessInRoute(const std::vector<Req
                 _route->getSubRequestOrigin(baseRequestId, isEntry), *_route);
         //If we've found an insertion that doesn't create a vehicle, stop there
         if(changeList.success()) {
-            DEBUG_MMH_MSG("ENTRY CANDIDATE SUCCESS : " + subreq.to_string());
+            DEBUG_MMH_MSG(std::string(isEntry ? "ENTRY" : "EXIT") + " CANDIDATE SUCCESS : " + subreq.to_string());
             return getSubrequest(baseRequestId, isEntry);
         } else {
-            DEBUG_MMH_MSG("ENTRY CANDIDATE FAILURE : " + subreq.to_string());
+            DEBUG_MMH_MSG(std::string(isEntry ? "ENTRY" : "EXIT") + " CANDIDATE FAILURE : " + subreq.to_string() + "\n"
+                        + "CAUSE : " + changeList.getStatusString());
         }
     }
 
diff --git a/src/routes/vehicle/propagation/SAEVRouteChangelist.cpp b/src/routes/vehicle/propagation/SAEVRouteChangelist.cpp
index 3bd9e14..a289b26 100644
--- a/src/routes/vehicle/propagation/SAEVRouteChangelist.cpp
+++ b/src/routes/vehicle/propagation/SAEVRouteChangelist.cpp
@@ -78,6 +78,41 @@ SAEVRouteChangelist::InsertionStatus SAEVRouteChangelist::getStatus() const {
     return _status;
 }
 
+std::string SAEVRouteChangelist::getStatusString() const {
+    std::string res;
+
+    switch (_status) {
+        case InsertionStatus::SUCCESS:
+            res = "SUCCESS";
+            break;
+        case InsertionStatus::FAILURE_MIN:
+            res = "FAILURE_MIN";
+            break;
+        case InsertionStatus::FAILURE_MAX:
+            res = "FAILURE_MAX";
+            break;
+        case InsertionStatus::FAILURE_DELTA_MIN:
+            res = "FAILURE_DELTA_MIN";
+            break;
+        case InsertionStatus::FAILURE_DELTA_MAX:
+            res = "FAILURE_DELTA_MAX";
+            break;
+        case InsertionStatus::FAILURE_PRECONDITION_TW:
+            res = "FAILURE_PRECONDITION_TW";
+            break;
+        case InsertionStatus::FAILURE_PRECONDITION_WEIGHT:
+            res = "FAILURE_PRECONDITION_WEIGHT";
+            break;
+        case InsertionStatus::CHANGELIST_REVERTED:
+            res = "CHANGELIST_REVERTED";
+            break;
+        default:
+            res = "UNKNOWN STATUS";
+    }
+
+    return res;
+}
+
 SAEVRouteChangelist::InsertionStatus SAEVRouteChangelist::getCurrentStatus() const {
     return _currentStatus;
 }
diff --git a/src/routes/vehicle/propagation/SAEVRouteChangelist.h b/src/routes/vehicle/propagation/SAEVRouteChangelist.h
index fc7844b..13a043c 100644
--- a/src/routes/vehicle/propagation/SAEVRouteChangelist.h
+++ b/src/routes/vehicle/propagation/SAEVRouteChangelist.h
@@ -121,6 +121,12 @@ public:
      * @return True iff this changelist's score is strictly lower than rhs' score
      */
     bool operator<(const SAEVRouteChangelist& rhs) const;
+
+    /**
+     * Formats the current changelist status as a string for logging purposes
+     * @return A string corresponding to the current status
+     */
+    [[nodiscard]] std::string getStatusString() const;
 };
 
 
diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt
index 3554c1e..d30630e 100644
--- a/test/CMakeLists.txt
+++ b/test/CMakeLists.txt
@@ -8,6 +8,7 @@ include_directories(${gtest_SOURCE_DIR}/include ${gtest_SOURCE_DIR})
 #add_definitions(-DDEBUG_TRANSIT_PRECOMPUTE)
 #add_definitions(-DDEBUG_CONSTRAINT_PROPAGATION)
 #add_definitions(-DDEBUG_BEST_INSERTION_HEURISTIC)
+#add_definitions(-DDEBUG_MULTIMODAL_HEURISTIC)
 
 # 'Google_Tests_run' is the target name
 # 'test1.cpp test2.cpp' are source files with tests
-- 
GitLab


From e4041f77398fe97bc5a1baf06f1271c21c823210 Mon Sep 17 00:00:00 2001
From: Romain BERNARD <romain.bernard@uca.fr>
Date: Fri, 20 Sep 2024 13:14:50 +0200
Subject: [PATCH 321/327] refactor to fix typo

---
 .../Multimodal/Heuristics/MultimodalModularHeuristic.h    | 2 +-
 test/src/MultimodalInsertionHeuristicDebug.cpp            | 8 ++++----
 2 files changed, 5 insertions(+), 5 deletions(-)

diff --git a/src/algorithm/Multimodal/Heuristics/MultimodalModularHeuristic.h b/src/algorithm/Multimodal/Heuristics/MultimodalModularHeuristic.h
index 94d3f61..97e5805 100644
--- a/src/algorithm/Multimodal/Heuristics/MultimodalModularHeuristic.h
+++ b/src/algorithm/Multimodal/Heuristics/MultimodalModularHeuristic.h
@@ -89,7 +89,7 @@ public:
      */
     void doMultimodalRequestsInsertion();
 
-    [[nodiscard]] size_t getNbBaseRquests() const {
+    [[nodiscard]] size_t getNbBaseRequests() const {
         return _requestsVect->size();
     }
 
diff --git a/test/src/MultimodalInsertionHeuristicDebug.cpp b/test/src/MultimodalInsertionHeuristicDebug.cpp
index ef34db5..db49400 100644
--- a/test/src/MultimodalInsertionHeuristicDebug.cpp
+++ b/test/src/MultimodalInsertionHeuristicDebug.cpp
@@ -69,14 +69,14 @@ TEST(MultimodalInsertionHeuristicDebug, DebugBaseInstance) {
     std::cout << "------------------End preprocessings-------------------" << std::endl << std::endl;
     std::cout << "------------------Start multimodal insertion (entry)-------------------" << std::endl << std::endl;
     START_TIMER
-    for(size_t i = 0; i < multimodalHeuristic.getNbBaseRquests(); ++i) {
+    for(size_t i = 0; i < multimodalHeuristic.getNbBaseRequests(); ++i) {
         multimodalHeuristic.insertBestTransitEntryInRoute(requests[i], i);
     }
     STOP_TIMER("Multimodal insertion (entry)")
     std::cout << "------------------End multimodal insertion (entry)-------------------" << std::endl << std::endl;
     std::cout << "------------------Start multimodal insertion (exit)-------------------" << std::endl << std::endl;
     START_TIMER
-    for(size_t i = 0; i < multimodalHeuristic.getNbBaseRquests(); ++i) {
+    for(size_t i = 0; i < multimodalHeuristic.getNbBaseRequests(); ++i) {
         multimodalHeuristic.insertBestTransitExitsInRoute(requests[i], i);
     }
     STOP_TIMER("Multimodal insertion (exit)")
@@ -110,14 +110,14 @@ TEST(MultimodalInsertionHeuristicDebug, DebugInstanceAlain) {
     std::cout << "------------------End preprocessings-------------------" << std::endl << std::endl;
     std::cout << "------------------Start multimodal insertion (entry)-------------------" << std::endl << std::endl;
     START_TIMER
-    for(size_t i = 0; i < multimodalHeuristic.getNbBaseRquests(); ++i) {
+    for(size_t i = 0; i < multimodalHeuristic.getNbBaseRequests(); ++i) {
         multimodalHeuristic.insertBestTransitEntryInRoute(requests[i], i);
     }
     STOP_TIMER("Multimodal insertion (entry)")
     std::cout << "------------------End multimodal insertion (entry)-------------------" << std::endl << std::endl;
     std::cout << "------------------Start multimodal insertion (exit)-------------------" << std::endl << std::endl;
     START_TIMER
-    for(size_t i = 0; i < multimodalHeuristic.getNbBaseRquests(); ++i) {
+    for(size_t i = 0; i < multimodalHeuristic.getNbBaseRequests(); ++i) {
         multimodalHeuristic.insertBestTransitExitsInRoute(requests[i], i);
     }
     STOP_TIMER("Multimodal insertion (exit)")
-- 
GitLab


From b53a8c7c8bccecb1b2e9775bdd5ceb6ba19fe7d6 Mon Sep 17 00:00:00 2001
From: Romain BERNARD <romain.bernard@uca.fr>
Date: Mon, 23 Sep 2024 10:22:52 +0200
Subject: [PATCH 322/327] fix bounds reset : add depot case

---
 src/routes/vehicle/SAEVKeyPoint.cpp | 5 ++++-
 1 file changed, 4 insertions(+), 1 deletion(-)

diff --git a/src/routes/vehicle/SAEVKeyPoint.cpp b/src/routes/vehicle/SAEVKeyPoint.cpp
index 9094b70..726bb6c 100644
--- a/src/routes/vehicle/SAEVKeyPoint.cpp
+++ b/src/routes/vehicle/SAEVKeyPoint.cpp
@@ -128,7 +128,10 @@ std::string SAEVKeyPoint::to_string() const {
 }
 
 void SAEVKeyPoint::resetBounds() {
-    if(isOrigin()) {
+    if(isDepot()) {
+        _minTW = 0;
+        _maxTW = INT16_MAX;
+    } else if(isOrigin()) {
         _minTW = _requestPointer->getMinDepartureTw();
         _maxTW = _requestPointer->getMaxDepartureTw();
     } else {
-- 
GitLab


From b76a29b8f5e05e11a00ec1627e4aac69649e6bf8 Mon Sep 17 00:00:00 2001
From: Romain BERNARD <romain.bernard@uca.fr>
Date: Mon, 23 Sep 2024 10:23:44 +0200
Subject: [PATCH 323/327] fix bounds reset : properly reset originPredKP if
 necessary

---
 src/routes/vehicle/SAEVRoute.cpp | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/src/routes/vehicle/SAEVRoute.cpp b/src/routes/vehicle/SAEVRoute.cpp
index 8b11c80..9b309b3 100644
--- a/src/routes/vehicle/SAEVRoute.cpp
+++ b/src/routes/vehicle/SAEVRoute.cpp
@@ -528,14 +528,14 @@ std::string SAEVRoute::to_string() {
 SAEVRouteChangelist SAEVRoute::removeRequestWithPropagation(SAEVKeyPoint &originKP) {
     //save ref to part of the route we have to update before removing
     //FIXME : best would be to link to depot/vehicle to directly start from the origin depot instead of having two whiles
-    SAEVKeyPoint const* originPredKp = originKP.getPredecessor();
+    SAEVKeyPoint* originPredKp = originKP.getPredecessor();
     assertm(originPredKp != nullptr, "Trying to remove a key point that's not in any route");
     //Actually remove request
     removeRequest(originKP);
 
     std::queue<std::pair<int, SAEVKeyPoint*>> propagationQueue;
     //Now iterate over predecessor KPs to reset their bounds and add to propagation queue
-    SAEVKeyPoint* currentKP = originPredKp->getPredecessor();
+    SAEVKeyPoint* currentKP = originPredKp;
     while (currentKP != nullptr) {
         currentKP->resetBounds();
         propagationQueue.emplace(Min, currentKP);
-- 
GitLab


From d85a65ab5fd553547687b925a992e4e1d2873654 Mon Sep 17 00:00:00 2001
From: Romain BERNARD <romain.bernard@uca.fr>
Date: Mon, 23 Sep 2024 10:24:45 +0200
Subject: [PATCH 324/327] remove assert now that we account for empty lists
 later in the heuristic

---
 .../Heuristics/MultimodalModularHeuristic.cpp |  1 -
 test/lib/googletest                           |  2 +-
 .../src/MultimodalInsertionHeuristicDebug.cpp | 66 ++++++++++++++++++-
 3 files changed, 66 insertions(+), 3 deletions(-)

diff --git a/src/algorithm/Multimodal/Heuristics/MultimodalModularHeuristic.cpp b/src/algorithm/Multimodal/Heuristics/MultimodalModularHeuristic.cpp
index 941bd71..df5882d 100644
--- a/src/algorithm/Multimodal/Heuristics/MultimodalModularHeuristic.cpp
+++ b/src/algorithm/Multimodal/Heuristics/MultimodalModularHeuristic.cpp
@@ -232,7 +232,6 @@ MultimodalModularHeuristic::getBestTransitExitsList(size_t baseRequestId, const
             scoredTransitExits.emplace_back(exit, getTransitExitScore(baseRequest, exit));
         }
     }
-    assertm(!scoredTransitExits.empty(), ("No valid exit from the given entrance has been found for base request #" + std::to_string(baseRequestId)));
 
     //Sort and truncate transit exits list while removing score data that's unnecessary in later steps
     std::ranges::sort(scoredTransitExits, getScoredTransitExitOrderer());
diff --git a/test/lib/googletest b/test/lib/googletest
index ff233bd..0953a17 160000
--- a/test/lib/googletest
+++ b/test/lib/googletest
@@ -1 +1 @@
-Subproject commit ff233bdd4cac0a0bf6e5cd45bda3406814cb2796
+Subproject commit 0953a17a4281fc26831da647ad3fcd5e21e6473b
diff --git a/test/src/MultimodalInsertionHeuristicDebug.cpp b/test/src/MultimodalInsertionHeuristicDebug.cpp
index db49400..3d98bbd 100644
--- a/test/src/MultimodalInsertionHeuristicDebug.cpp
+++ b/test/src/MultimodalInsertionHeuristicDebug.cpp
@@ -42,7 +42,71 @@ TEST(MultimodalInsertionHeuristicDebug, DebugBasicInstance) {
     std::cout << "------------------End multimodal insertion-------------------" << std::endl << std::endl;
 }
 
-TEST(MultimodalInsertionHeuristicDebug, DebugBaseInstance) {
+TEST(MultimodalInsertionHeuristicDebug, DebugUnfulfilledEntry) {
+    std::string instancesPath = "../../resources/test/instances/MultimodalHeuristic/";
+    std::string instanceName = "debug unfulfilled entry/";
+    std::string graphFile = "graph.dat";
+    std::string requestsFile = "requests.dat";
+
+
+    //Parse graph
+    INIT_TIMER
+    Graph graphFromSingleFile(instancesPath + instanceName + graphFile);
+    std::vector<Request> requests = Request::getRequestsFromFile(instancesPath + instanceName + requestsFile, graphFromSingleFile);
+
+    //Init instance
+    Instance instance(requests,graphFromSingleFile,4);
+    SAEVRoute routesContainer(graphFromSingleFile, requests, true);
+    MultimodalModularHeuristic multimodalHeuristic(&graphFromSingleFile, &routesContainer, &requests);
+    STOP_TIMER("Instance parsing and init")
+    std::cout << "------------------Fin parsing instance et route-------------------" << std::endl << std::endl;
+
+    std::cout << "------------------Start preprocessings-------------------" << std::endl << std::endl;
+    START_TIMER
+    graphFromSingleFile.computeAndUpdateShortestTransitPaths();
+    graphFromSingleFile.computeAndUpdateShortestPathsMatrix(true);
+    STOP_TIMER("Preprocess")
+    std::cout << "------------------End preprocessings-------------------" << std::endl << std::endl;
+    std::cout << "------------------Start multimodal insertion-------------------" << std::endl << std::endl;
+    START_TIMER
+    multimodalHeuristic.doMultimodalRequestsInsertion();
+    STOP_TIMER("Multimodal insertion")
+    std::cout << "------------------End multimodal insertion-------------------" << std::endl << std::endl;
+}
+
+TEST(MultimodalInsertionHeuristicDebug, DebugUnfulfilledExit) {
+    std::string instancesPath = "../../resources/test/instances/MultimodalHeuristic/";
+    std::string instanceName = "debug unfulfilled exit/";
+    std::string graphFile = "graph.dat";
+    std::string requestsFile = "requests.dat";
+
+
+    //Parse graph
+    INIT_TIMER
+    Graph graphFromSingleFile(instancesPath + instanceName + graphFile);
+    std::vector<Request> requests = Request::getRequestsFromFile(instancesPath + instanceName + requestsFile, graphFromSingleFile);
+
+    //Init instance
+    Instance instance(requests,graphFromSingleFile,4);
+    SAEVRoute routesContainer(graphFromSingleFile, requests, true);
+    MultimodalModularHeuristic multimodalHeuristic(&graphFromSingleFile, &routesContainer, &requests);
+    STOP_TIMER("Instance parsing and init")
+    std::cout << "------------------Fin parsing instance et route-------------------" << std::endl << std::endl;
+
+    std::cout << "------------------Start preprocessings-------------------" << std::endl << std::endl;
+    START_TIMER
+    graphFromSingleFile.computeAndUpdateShortestTransitPaths();
+    graphFromSingleFile.computeAndUpdateShortestPathsMatrix(true);
+    STOP_TIMER("Preprocess")
+    std::cout << "------------------End preprocessings-------------------" << std::endl << std::endl;
+    std::cout << "------------------Start multimodal insertion-------------------" << std::endl << std::endl;
+    START_TIMER
+    multimodalHeuristic.doMultimodalRequestsInsertion();
+    STOP_TIMER("Multimodal insertion")
+    std::cout << "------------------End multimodal insertion-------------------" << std::endl << std::endl;
+}
+
+TEST(MultimodalInsertionHeuristicDebug, DebugPTInstance) {
     std::string instancesPath = "../../resources/test/instances/PT Shortest Path/";
     std::string instanceFolder = "contiguous_lines_debug_instance/";
     std::string datFile = "graph.dat";
-- 
GitLab


From 2a9d0ab45ad487410a02cf0d927fd916ca76d993 Mon Sep 17 00:00:00 2001
From: Romain BERNARD <romain.bernard@uca.fr>
Date: Mon, 23 Sep 2024 12:31:53 +0200
Subject: [PATCH 325/327] replace debug message macros to prevent their
 definitions from bleeding over to other classes

---
 .../Heuristics/BestInsertionHeuristic.cpp     | 10 ++++----
 .../Transit/TransitShortestPathPrecompute.cpp | 14 +++++------
 .../Transit/TransitStateContainer.h           |  6 ++---
 src/instance/graph/Graph.cpp                  | 14 +++++------
 src/routes/vehicle/SAEVRoute.cpp              | 24 +++++++++----------
 5 files changed, 34 insertions(+), 34 deletions(-)

diff --git a/src/algorithm/DARP/Heuristics/BestInsertionHeuristic.cpp b/src/algorithm/DARP/Heuristics/BestInsertionHeuristic.cpp
index c067ef8..db0e833 100644
--- a/src/algorithm/DARP/Heuristics/BestInsertionHeuristic.cpp
+++ b/src/algorithm/DARP/Heuristics/BestInsertionHeuristic.cpp
@@ -6,9 +6,9 @@
 
 #ifdef DEBUG_BEST_INSERTION_HEURISTIC
 #include <iostream>
-#define DEBUG_MSG(str) do { std::cout << "[BEST INSERTION] " << str << std::endl; } while( false )
+#define DEBUG_BIH_MSG(str) do { std::cout << "[BEST INSERTION] " << str << std::endl; } while( false )
 #else
-#define DEBUG_MSG(str) do { } while ( false )
+#define DEBUG_BIH_MSG(str) do { } while ( false )
 #endif
 
 SAEVRouteChangelist BestInsertionHeuristic::tryVehicleBestInsertion(SAEVKeyPoint &requestKp, size_t vehicleId, SAEVRoute& route) {
@@ -24,14 +24,14 @@ SAEVRouteChangelist BestInsertionHeuristic::tryVehicleBestInsertion(BestInsertio
 
     while(!bestInsertionsQueue.empty() && !bestInsertionFound) {
         currentBestInsertion = bestInsertionsQueue.topAndPop();
-        DEBUG_MSG("Trying insertion " + currentBestInsertion.to_string() + ", remaining : " + std::to_string(bestInsertionsQueue.size()));
+        DEBUG_BIH_MSG("Trying insertion " + currentBestInsertion.to_string() + ", remaining : " + std::to_string(bestInsertionsQueue.size()));
         lastInsertionChangelist = route.tryAddRequest(requestKp,currentBestInsertion.getOriginInsertionKp(),currentBestInsertion.getDestinationInsertionKp());
         //If insertion worked, signal it, otherwise revert changes
         if(lastInsertionChangelist.getStatus() == SAEVRouteChangelist::InsertionStatus::SUCCESS) {
-            DEBUG_MSG("\tBest valid insertion found !\n\t\t" + currentBestInsertion.to_string());
+            DEBUG_BIH_MSG("\tBest valid insertion found !\n\t\t" + currentBestInsertion.to_string());
             bestInsertionFound = true;
         } else {
-            DEBUG_MSG("Failed to insert best insertion " + currentBestInsertion.to_string());
+            DEBUG_BIH_MSG("Failed to insert best insertion " + currentBestInsertion.to_string());
             lastInsertionChangelist.revertChanges();
         }
     }
diff --git a/src/algorithm/ShortestPath/Transit/TransitShortestPathPrecompute.cpp b/src/algorithm/ShortestPath/Transit/TransitShortestPathPrecompute.cpp
index b7087e2..2c44f0f 100644
--- a/src/algorithm/ShortestPath/Transit/TransitShortestPathPrecompute.cpp
+++ b/src/algorithm/ShortestPath/Transit/TransitShortestPathPrecompute.cpp
@@ -8,9 +8,9 @@
 
 #ifdef DEBUG_TRANSIT_PRECOMPUTE
 #include <iostream>
-#define DEBUG_MSG(str) do { std::cout << "[TRANSIT] " << str << std::endl; } while( false )
+#define DEBUG_TRANSIT_MSG(str) do { std::cout << "[TRANSIT] " << str << std::endl; } while( false )
 #else
-#define DEBUG_MSG(str) do { } while ( false )
+#define DEBUG_TRANSIT_MSG(str) do { } while ( false )
 #endif
 
 //TODO:
@@ -29,13 +29,13 @@ TransitStateContainer TransitShortestPathPrecompute::executeAlgorithm(const Grap
         TransitAlgorithmState currentState = statePriorityQueue.top();
         statePriorityQueue.pop();
         if(!solutionsContainer.strictlyDominates(currentState)) {
-            DEBUG_MSG("\n\nComparing state " + currentState.toString() + " and " + solutionsContainer.getBestSolution(currentState.getNodeIndex(), currentState.getNbConnections()).toString());
+            DEBUG_TRANSIT_MSG("\n\nComparing state " + currentState.toString() + " and " + solutionsContainer.getBestSolution(currentState.getNodeIndex(), currentState.getNbConnections()).toString());
             for (const auto& lineStop : graph.getPTLinesSet(currentState.getNodeIndex()))
             {
                 int nextNode = lineStop.getNextNodeIndex();
                 //If there is a proper next node and if it's not the same as our last used line stop predecessor
                 if(nextNode != -1 && (currentState.isEmpty() || nextNode != currentState.getPrecedingNodeIndex())) {
-                    DEBUG_MSG("Extension from line " + lineStop.getLineRef().getLineId() + " towards node " + std::to_string(nextNode));
+                    DEBUG_TRANSIT_MSG("Extension from line " + lineStop.getLineRef().getLineId() + " towards node " + std::to_string(nextNode));
                     TransitAlgorithmState newState; //define variable before conditionals
                     int nextPassageIndex = currentState.getPassageIndex(); //default value if we stay on the same line and no turn back happens
                     if(currentState.isEmpty() || currentState.getLastConnectionLine() != lineStop.getLineRef()) // if new line is different than current line
@@ -66,17 +66,17 @@ TransitStateContainer TransitShortestPathPrecompute::executeAlgorithm(const Grap
                         }
                     }
 
-                    DEBUG_MSG("Created new state " + newState.toString());
+                    DEBUG_TRANSIT_MSG("Created new state " + newState.toString());
 
                     //Add new state to the solution container and the priority queue if it's not strictly dominated by an existing solution
                     if(newState.getNodeIndex() != -1 && !solutionsContainer.strictlyDominates(newState)) {
-                        DEBUG_MSG("Candidate state " + newState.toString() + " added to priority queue\n");
+                        DEBUG_TRANSIT_MSG("Candidate state " + newState.toString() + " added to priority queue\n");
                         solutionsContainer.replaceBestSolutionIfNecessary(nextNode, newState);
                         statePriorityQueue.emplace(newState);
                     }
                 }
             }
-            DEBUG_MSG("Done extending state " + currentState.toString());
+            DEBUG_TRANSIT_MSG("Done extending state " + currentState.toString());
         }
     }
 
diff --git a/src/algorithm/ShortestPath/Transit/TransitStateContainer.h b/src/algorithm/ShortestPath/Transit/TransitStateContainer.h
index c503063..46023fa 100644
--- a/src/algorithm/ShortestPath/Transit/TransitStateContainer.h
+++ b/src/algorithm/ShortestPath/Transit/TransitStateContainer.h
@@ -10,9 +10,9 @@
 
 #ifdef DEBUG_TRANSIT_PRECOMPUTE
 #include <iostream>
-#define DEBUG_MSG(str) do { std::cout << "[TRANSIT] " << str << std::endl; } while( false )
+#define DEBUG_TRANSIT_MSG(str) do { std::cout << "[TRANSIT] " << str << std::endl; } while( false )
 #else
-#define DEBUG_MSG(str) do { } while ( false )
+#define DEBUG_TRANSIT_MSG(str) do { } while ( false )
 #endif
 
 class TransitStateContainer {
@@ -66,7 +66,7 @@ public:
         if(newState.getNbConnections() > 0) {
             TransitAlgorithmState const& currentBest = solutionVector[nodeIndex][newState.getNbConnections() - 1];
             if(currentBest.getInstant() > newState.getInstant()) {
-                DEBUG_MSG("Candidate state " + newState.toString() + " is the new fastest solution");
+                DEBUG_TRANSIT_MSG("Candidate state " + newState.toString() + " is the new fastest solution");
                 solutionVector[nodeIndex][newState.getNbConnections() - 1] = newState;
             }
         }
diff --git a/src/instance/graph/Graph.cpp b/src/instance/graph/Graph.cpp
index 77ac5fe..2454d28 100644
--- a/src/instance/graph/Graph.cpp
+++ b/src/instance/graph/Graph.cpp
@@ -2,10 +2,10 @@
 // Created by rbernard on 22/01/24.
 //
 
-#ifdef DEBUG
-#define DEBUG_MSG(str) do { std::cout << str << std::endl; } while( false )
+#ifdef DEBUG_GRAPH
+#define DEBUG_GRAPH_MSG(str) do { std::cout << "[GRAPH] " + str << std::endl; } while( false )
 #else
-#define DEBUG_MSG(str) do { } while ( false )
+#define DEBUG_GRAPH_MSG(str) do { } while ( false )
 #endif
 
 #include <sstream>
@@ -240,7 +240,7 @@ void Graph::parseNodeRow(const DATRow& row)
         std::from_chars(row[2].data(), row[2].data() + row[2].length(), y);
 
         this->nodesVector.emplace_back(status, x, y);
-        DEBUG_MSG("Created new node " << x << " " << y << " with status = " << status);
+        DEBUG_GRAPH_MSG("Created new node " << x << " " << y << " with status = " << status);
     }
 }
 
@@ -256,7 +256,7 @@ void Graph::parseEdgeRow(const DATRow& row)
         std::from_chars(row[1].data(), row[1].data() + row[1].size(), edge_end);
         std::from_chars(row[2].data(), row[2].data() + row[2].size(), length);
         this->createAndAddEdge(edge_start, edge_end, length);
-        DEBUG_MSG("Created new edge between " << edge_start << " and " << edge_end << " of length " << length);
+        DEBUG_GRAPH_MSG("Created new edge between " << edge_start << " and " << edge_end << " of length " << length);
     }
 }
 
@@ -308,7 +308,7 @@ void Graph::parseLineRandomizedSchedule(const DATRow& row, std::mt19937 rng)
     //Check for errors
     if(newLine.check()) {
         this->addLine(newLine);
-        DEBUG_MSG("Created new line with randomized schedule");
+        DEBUG_GRAPH_MSG("Created new line with randomized schedule");
     }
 }
 
@@ -343,7 +343,7 @@ void Graph::parseLineFixedSchedule(std::ifstream& infile, DATRow& row) {
     //Check for errors
     if(newLine.check()) {
         this->addLine(newLine);
-        DEBUG_MSG("Created new line with fixed schedule");
+        DEBUG_GRAPH_MSG("Created new line with fixed schedule");
     }
 }
 
diff --git a/src/routes/vehicle/SAEVRoute.cpp b/src/routes/vehicle/SAEVRoute.cpp
index 9b309b3..b1452be 100644
--- a/src/routes/vehicle/SAEVRoute.cpp
+++ b/src/routes/vehicle/SAEVRoute.cpp
@@ -9,9 +9,9 @@
 
 #ifdef DEBUG_CONSTRAINT_PROPAGATION
 #include <iostream>
-#define DEBUG_MSG(str) do { std::cout << "[PROPAG] " << str << std::endl; } while( false )
+#define DEBUG_PROPAG_MSG(str) do { std::cout << "[PROPAG] " << str << std::endl; } while( false )
 #else
-#define DEBUG_MSG(str) do { } while ( false )
+#define DEBUG_PROPAG_MSG(str) do { } while ( false )
 #endif
 
 SAEVRoute::SAEVRoute(const Graph &graph, const std::vector<Request> &requestList)
@@ -151,7 +151,7 @@ SAEVRoute::tryAddRequest(SAEVKeyPoint &requestOriginKeyPoint, SAEVKeyPoint * ori
     SAEVKeyPoint const* currentKP = originRequestPredecessorKP;
     do {
         if(currentKP->getCurrentOccupation() + request->getWeight() > SAEVehicle::getCapacity()) {
-            DEBUG_MSG("WEIGHT VIOLATION : request weight = " + std::to_string(request->getWeight()) + " incompatible KP = " + currentKP->to_string());
+            DEBUG_PROPAG_MSG("WEIGHT VIOLATION : request weight = " + std::to_string(request->getWeight()) + " incompatible KP = " + currentKP->to_string());
             return SAEVRouteChangelist(this, &requestOriginKeyPoint, originRequestPredecessorKP, destinationRequestPredecessorKP, SAEVRouteChangelist::InsertionStatus::FAILURE_PRECONDITION_WEIGHT);
         }
         currentKP = currentKP->getSuccessor();
@@ -163,7 +163,7 @@ SAEVRoute::tryAddRequest(SAEVKeyPoint &requestOriginKeyPoint, SAEVKeyPoint * ori
     if(isValid) {
         return insertRequestWithPropagation(requestOriginKeyPoint, originRequestPredecessorKP, destinationRequestPredecessorKP);
     } else {
-        DEBUG_MSG("TW VIOLATION on neighbour KPs");
+        DEBUG_PROPAG_MSG("TW VIOLATION on neighbour KPs");
         return SAEVRouteChangelist(this, &requestOriginKeyPoint, originRequestPredecessorKP, destinationRequestPredecessorKP, SAEVRouteChangelist::InsertionStatus::FAILURE_PRECONDITION_TW);
     }
 }
@@ -264,7 +264,7 @@ SAEVRouteChangelist SAEVRoute::doBoundPropagation(std::queue<std::pair<int, SAEV
                 newValue = keyPoint->getMinTw() + _graph->getShortestSAEVPath(keyPoint->getNodeIndex(), successorKP->getNodeIndex());
                 if (oldValue < newValue) {
                     if (newValue > successorKP->getMaxTw()) {
-                        DEBUG_MSG("\tMIN TW VIOLATION");
+                        DEBUG_PROPAG_MSG("\tMIN TW VIOLATION");
                         changelist.setStatus(SAEVRouteChangelist::InsertionStatus::FAILURE_MIN);
                         return changelist;
                     }
@@ -278,7 +278,7 @@ SAEVRouteChangelist SAEVRoute::doBoundPropagation(std::queue<std::pair<int, SAEV
             newValue = keyPoint->getMinTw() - keyPoint->getDeltaTime();
             if(!keyPoint->isDepot() && keyPoint->isDestination() && oldValue < newValue) {
                 if (newValue > counterpartKP->getMaxTw()) {
-                    DEBUG_MSG("\tMIN DELTA Destination->Origine");
+                    DEBUG_PROPAG_MSG("\tMIN DELTA Destination->Origine");
                     changelist.setStatus(SAEVRouteChangelist::InsertionStatus::FAILURE_DELTA_MIN);
                     return changelist;
                 }
@@ -294,7 +294,7 @@ SAEVRouteChangelist SAEVRoute::doBoundPropagation(std::queue<std::pair<int, SAEV
                 newValue = keyPoint->getMaxTw() - _graph->getShortestSAEVPath(predecessorKP->getNodeIndex(), keyPoint->getNodeIndex());
                 if(oldValue > newValue) {
                     if (predecessorKP->getMinTw() > newValue) {
-                        DEBUG_MSG("\tMAX TW VIOLATION");
+                        DEBUG_PROPAG_MSG("\tMAX TW VIOLATION");
                         changelist.setStatus(SAEVRouteChangelist::InsertionStatus::FAILURE_MAX);
                         return changelist;
                     }
@@ -308,7 +308,7 @@ SAEVRouteChangelist SAEVRoute::doBoundPropagation(std::queue<std::pair<int, SAEV
             newValue = keyPoint->getMaxTw() + keyPoint->getDeltaTime();
             if(!keyPoint->isDepot() && keyPoint->isOrigin() && oldValue > newValue) {
                 if (counterpartKP->getMinTw() > newValue) {
-                    DEBUG_MSG("\tMAX DELTA Origine->Destination");
+                    DEBUG_PROPAG_MSG("\tMAX DELTA Origine->Destination");
                     changelist.setStatus(SAEVRouteChangelist::InsertionStatus::FAILURE_DELTA_MAX);
                     return changelist;
                 }
@@ -377,11 +377,11 @@ bool SAEVRoute::checkRouteTimeWindows(size_t vehicleId) {
         //MIN/MAX
         if(succKP != nullptr) {
             if(!currentKeyPoint->isDepot() && currentKeyPoint->getMinTw() + _graph->getShortestSAEVPath(currentKeyPoint->getNodeIndex(), succKP->getNodeIndex()) > succKP->getMaxTw() ) {
-                DEBUG_MSG("MIN TW VIOLATION : " + currentKeyPoint->to_string() + " > " + succKP->to_string());
+                DEBUG_PROPAG_MSG("MIN TW VIOLATION : " + currentKeyPoint->to_string() + " > " + succKP->to_string());
                 return false;
             }
             if(!succKP->isDepot() && currentKeyPoint->getMaxTw() + _graph->getShortestSAEVPath(currentKeyPoint->getNodeIndex(), succKP->getNodeIndex()) < succKP->getMaxTw() ) {
-                DEBUG_MSG("MAX TW VIOLATION : " + currentKeyPoint->to_string() + " < " + succKP->to_string());
+                DEBUG_PROPAG_MSG("MAX TW VIOLATION : " + currentKeyPoint->to_string() + " < " + succKP->to_string());
                 return false;
             }
         }
@@ -389,7 +389,7 @@ bool SAEVRoute::checkRouteTimeWindows(size_t vehicleId) {
         if((!currentKeyPoint->isDepot() && currentKeyPoint->isOrigin() && counterpartKP != nullptr)
         && (counterpartKP->getMinTw() - currentKeyPoint->getMinTw() > currentKeyPoint->getRequest()->getDeltaTime()
         ||  counterpartKP->getMaxTw() - currentKeyPoint->getMaxTw() > currentKeyPoint->getRequest()->getDeltaTime())) {
-            DEBUG_MSG("DELTA VIOLATION : " + currentKeyPoint->to_string() + " " + counterpartKP->to_string());
+            DEBUG_PROPAG_MSG("DELTA VIOLATION : " + currentKeyPoint->to_string() + " " + counterpartKP->to_string());
             return false;
         }
         currentKeyPoint = currentKeyPoint->getSuccessor();
@@ -512,7 +512,7 @@ void SAEVRoute::removeRequestWeightFromRoute(SAEVKeyPoint& requestOriginKeyPoint
 
 void SAEVRoute::insertRequestInNewVehicle(SAEVKeyPoint &originKp) {
     size_t vehicleId = addNewActiveVehicle();
-    DEBUG_MSG("NEW VEHICLE CREATED, ID :" + std::to_string(vehicleId));
+    DEBUG_PROPAG_MSG("NEW VEHICLE CREATED, ID :" + std::to_string(vehicleId));
 
     tryAddRequest(originKp, &getOriginDepot(vehicleId), &getOriginDepot(vehicleId));
 }
-- 
GitLab


From e20c74020f66bb1626199021e7ac4f67364c0850 Mon Sep 17 00:00:00 2001
From: Romain BERNARD <romain.bernard@uca.fr>
Date: Mon, 23 Sep 2024 13:30:31 +0200
Subject: [PATCH 326/327] Add basic debug instances for invalid entry/exit
 (TODO: add requests variants with some successes and some fails)

---
 .../debug unfulfilled entry/graph.dat         | 20 +++++++++++++++++++
 .../debug unfulfilled entry/requests.dat      |  4 ++++
 .../debug unfulfilled exit/graph.dat          | 19 ++++++++++++++++++
 .../debug unfulfilled exit/requests.dat       |  4 ++++
 .../Heuristics/MultimodalModularHeuristic.h   |  2 +-
 .../Multimodal/Heuristics/TransitAccess.h     |  2 +-
 src/utils/Globals.h                           |  2 +-
 7 files changed, 50 insertions(+), 3 deletions(-)
 create mode 100644 resources/test/instances/MultimodalHeuristic/debug unfulfilled entry/graph.dat
 create mode 100644 resources/test/instances/MultimodalHeuristic/debug unfulfilled entry/requests.dat
 create mode 100644 resources/test/instances/MultimodalHeuristic/debug unfulfilled exit/graph.dat
 create mode 100644 resources/test/instances/MultimodalHeuristic/debug unfulfilled exit/requests.dat

diff --git a/resources/test/instances/MultimodalHeuristic/debug unfulfilled entry/graph.dat b/resources/test/instances/MultimodalHeuristic/debug unfulfilled entry/graph.dat
new file mode 100644
index 0000000..f2ab163
--- /dev/null
+++ b/resources/test/instances/MultimodalHeuristic/debug unfulfilled entry/graph.dat	
@@ -0,0 +1,20 @@
+#Params (seed)
+123456789
+#Nodes format : status (work, leisure, residential),x,y
+,0,0
+,8,4
+,1,1
+,3,3
+#Edges start,end,length
+0,1,60
+0,2,60
+0,3,20
+1,0,5
+1,3,15
+2,3,5
+3,0,20
+#PT line fixed
+1,2
+10,15
+20,25
+30,35
\ No newline at end of file
diff --git a/resources/test/instances/MultimodalHeuristic/debug unfulfilled entry/requests.dat b/resources/test/instances/MultimodalHeuristic/debug unfulfilled entry/requests.dat
new file mode 100644
index 0000000..308a1af
--- /dev/null
+++ b/resources/test/instances/MultimodalHeuristic/debug unfulfilled entry/requests.dat	
@@ -0,0 +1,4 @@
+#Global Params (delta ratio)
+1
+#Requests (origin_idx,destination_idx,min_tw_start,max_tw_start,min_tw_end,max_tw_end,delta_time,capacity)
+0,3,10,30,40,60,,1
\ No newline at end of file
diff --git a/resources/test/instances/MultimodalHeuristic/debug unfulfilled exit/graph.dat b/resources/test/instances/MultimodalHeuristic/debug unfulfilled exit/graph.dat
new file mode 100644
index 0000000..ea282ec
--- /dev/null
+++ b/resources/test/instances/MultimodalHeuristic/debug unfulfilled exit/graph.dat	
@@ -0,0 +1,19 @@
+#Params (seed)
+123456789
+#Nodes format : status (work, leisure, residential),x,y
+,0,0
+,8,4
+,1,1
+,3,3
+#Edges start,end,length
+0,2,10
+0,3,20
+1,0,5
+1,3,15
+2,3,5
+3,0,20
+#PT line fixed
+1,2
+10,15
+20,25
+30,35
\ No newline at end of file
diff --git a/resources/test/instances/MultimodalHeuristic/debug unfulfilled exit/requests.dat b/resources/test/instances/MultimodalHeuristic/debug unfulfilled exit/requests.dat
new file mode 100644
index 0000000..308a1af
--- /dev/null
+++ b/resources/test/instances/MultimodalHeuristic/debug unfulfilled exit/requests.dat	
@@ -0,0 +1,4 @@
+#Global Params (delta ratio)
+1
+#Requests (origin_idx,destination_idx,min_tw_start,max_tw_start,min_tw_end,max_tw_end,delta_time,capacity)
+0,3,10,30,40,60,,1
\ No newline at end of file
diff --git a/src/algorithm/Multimodal/Heuristics/MultimodalModularHeuristic.h b/src/algorithm/Multimodal/Heuristics/MultimodalModularHeuristic.h
index 97e5805..46242b3 100644
--- a/src/algorithm/Multimodal/Heuristics/MultimodalModularHeuristic.h
+++ b/src/algorithm/Multimodal/Heuristics/MultimodalModularHeuristic.h
@@ -66,7 +66,7 @@ private:
     std::vector<size_t> _darpRequestList;
 
     //Add friend test classes to test inner workings without making the whole API public
-    FRIEND_TEST(MultimodalInsertionHeuristicDebug, DebugBaseInstance);
+    FRIEND_TEST(MultimodalInsertionHeuristicDebug, DebugPTInstance);
     FRIEND_TEST(MultimodalInsertionHeuristicDebug, DebugInstanceAlain);
 
 //Public interface to interact with the modular heuristic
diff --git a/src/algorithm/Multimodal/Heuristics/TransitAccess.h b/src/algorithm/Multimodal/Heuristics/TransitAccess.h
index a1ec4f6..c59a121 100644
--- a/src/algorithm/Multimodal/Heuristics/TransitAccess.h
+++ b/src/algorithm/Multimodal/Heuristics/TransitAccess.h
@@ -1,5 +1,5 @@
 //
-// Created by Bebs on 24/07/2024.
+// Created by Romain on 24/07/2024.
 //
 
 #ifndef GREEDYALGORITHM_TRANSITACCESS_H
diff --git a/src/utils/Globals.h b/src/utils/Globals.h
index 88a94e0..3beb725 100644
--- a/src/utils/Globals.h
+++ b/src/utils/Globals.h
@@ -1,5 +1,5 @@
 //
-// Created by Bebs on 19/07/2024.
+// Created by Romain on 19/07/2024.
 //
 
 #ifndef GREEDYALGORITHM_GLOBALS_H
-- 
GitLab


From eb81f49d0a9bc39c507137f4565a7d187dbfedaa Mon Sep 17 00:00:00 2001
From: Romain BERNARD <romain.bernard@uca.fr>
Date: Fri, 27 Sep 2024 11:13:39 +0200
Subject: [PATCH 327/327] A bit of cleanup

---
 src/instance/graph/Graph.h              |  2 -
 src/instance/graph/Node.h               |  2 +-
 src/services/visualisation/graph_vis.py | 78 -------------------------
 3 files changed, 1 insertion(+), 81 deletions(-)
 delete mode 100644 src/services/visualisation/graph_vis.py

diff --git a/src/instance/graph/Graph.h b/src/instance/graph/Graph.h
index f1baeea..2d7bd8a 100644
--- a/src/instance/graph/Graph.h
+++ b/src/instance/graph/Graph.h
@@ -116,8 +116,6 @@ public:
         return nodesVector[nodeIndex].getOutgoingEdges().size();
     }
 
-    //TODO: try and define an Edge iterator over a given node's incoming/outgoing
-
     [[nodiscard]] size_t getNbEdges(size_t nodeIndex) const {
         return nodesVector[nodeIndex].getIncomingEdges().size() + nodesVector[nodeIndex].getOutgoingEdges().size();
     }
diff --git a/src/instance/graph/Node.h b/src/instance/graph/Node.h
index 2700a28..dbc5b7d 100644
--- a/src/instance/graph/Node.h
+++ b/src/instance/graph/Node.h
@@ -37,7 +37,7 @@ private:
     std::vector<int> _incomingEdgesIndex; //List of edge index in the graph structure for all edges leading to this node
     std::vector<int> _outgoingEdgesIndex; //List of edge index in the graph structure for all edges leading to this node
     std::vector<size_t> _bestStationsNodeIdxVector;
-    //TODO : Should these vectors be considered complete over the whole set of nodes ? Probably ? Considering we will probably pre-process shortest paths between all SAEV stations
+
 
 public:
     Node();
diff --git a/src/services/visualisation/graph_vis.py b/src/services/visualisation/graph_vis.py
deleted file mode 100644
index 5c0ca48..0000000
--- a/src/services/visualisation/graph_vis.py
+++ /dev/null
@@ -1,78 +0,0 @@
-import matplotlib.pyplot as plt
-
-#visualisation params
-eps = 0.2 #decalage du label par rapport au point
-
-
-class Edge:
-    def __init__(self):
-        self.start = None
-        self.end = None
-        self.length = None
-
-    def __init__(self, start: int, end: int, length: float):
-        self.start = start
-        self.end = end
-        self.length = length
-
-
-class Node:
-    def __init__(self):
-        self.status = None
-        self.x = None
-        self.y = None
-
-    def __init__(self, x: float, y: float, status: str = "work"):
-        self.status = status
-        self.x = x
-        self.y = y
-
-
-#TODO : get those from cpp
-nodes = []
-edges = []
-i = 0
-N = len(nodes)
-instanceFolderPath = "resources/test/outputs/basic_debug_instance/"
-
-#Read nodes
-fp = open(instanceFolderPath + 'nodes.txt')
-lines = fp.read().split("\n")
-fp.close()
-for nodeLine in lines:
-    splitLine = nodeLine.split(" ")
-    if len(splitLine) == 2:
-        nodes.append(Node(float(splitLine[0]), float(splitLine[1])))
-
-#Read edges
-fp = open(instanceFolderPath + 'edges.txt')
-lines = fp.read().split("\n")
-fp.close()
-for edgeLine in lines:
-    splitLine = edgeLine.split(" ")
-    if len(splitLine) == 3:
-        edges.append(Edge(int(splitLine[0]), int(splitLine[1]), float(splitLine[2])))
-
-
-#print points from nodes vectors
-plt.scatter([node.x for node in nodes], [node.y for node in nodes], color="red", s=50)
-
-#print labels
-while i < N:
-    suiv = (i+1)%N
-    for i in range(len(nodes)):
-        plt.text(nodes[i].x+eps, nodes[i].y-eps, i)
-    i=i+1
-
-
-#Print edges
-for edge in edges:
-    plt.annotate(text='', xy=(nodes[edge.start].x, nodes[edge.start].y),
-                 xytext=(nodes[edge.end].x, nodes[edge.end].y),
-                 arrowprops=dict(arrowstyle='<-'))
-
-
-#on agrandit un peu les limites sur X pour que les
-# labels ne dépassent pas le cadre
-plt.xlim(min([node.x for node in nodes])-eps, max([node.x for node in nodes])+2*eps)
-plt.show()
\ No newline at end of file
-- 
GitLab