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] 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