LCOV - code coverage report
Current view: top level - src/utils/router - AFBuilder.h (source / functions) Coverage Total Hit
Test: lcov.info Lines: 0.0 % 38 0
Test Date: 2025-11-13 15:38:19 Functions: 0.0 % 3 0

            Line data    Source code
       1              : /****************************************************************************/
       2              : // Eclipse SUMO, Simulation of Urban MObility; see https://eclipse.dev/sumo
       3              : // Copyright (C) 2001-2025 German Aerospace Center (DLR) and others.
       4              : // This program and the accompanying materials are made available under the
       5              : // terms of the Eclipse Public License 2.0 which is available at
       6              : // https://www.eclipse.org/legal/epl-2.0/
       7              : // This Source Code may also be made available under the following Secondary
       8              : // Licenses when the conditions for such availability set forth in the Eclipse
       9              : // Public License 2.0 are satisfied: GNU General Public License, version 2
      10              : // or later which is available at
      11              : // https://www.gnu.org/licenses/old-licenses/gpl-2.0-standalone.html
      12              : // SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later
      13              : /****************************************************************************/
      14              : /// @file    AFBuilder.h
      15              : /// @author  Ruediger Ebendt
      16              : /// @date    01.11.2023
      17              : ///
      18              : // Arc flags builder for the arc flag router
      19              : /****************************************************************************/
      20              : #pragma once
      21              : #include <config.h>
      22              : #include <vector>
      23              : // uncomment to disable assert()
      24              : // #define NDEBUG
      25              : #include <cassert>
      26              : 
      27              : #include "AFBuild.h"
      28              : #include "FlippedEdge.h"
      29              : 
      30              : //#define AFBL_DEBUG_LEVEL_0
      31              : //#define AFBL_DEBUG_LEVEL_1
      32              : //#define AFBL_DEBUG_LEVEL_2
      33              : 
      34              : #ifdef AFBL_DEBUG_LEVEL_2
      35              : #define AFBL_DEBUG_LEVEL_1
      36              : #endif
      37              : 
      38              : #ifdef AFBL_DEBUG_LEVEL_1
      39              : #define AFBL_DEBUG_LEVEL_0
      40              : #endif
      41              : 
      42              : // ===========================================================================
      43              : // class definitions
      44              : // ===========================================================================
      45              : /**
      46              :  * @class AFBuilder
      47              :  * @brief Builds arc flags for shortest path search with the arc flag router
      48              :  */
      49              : 
      50              : template<class E, class N, class V, class M>
      51              : class AFBuilder {
      52              : public:
      53              :     typedef typename AFInfo<E>::FlagInfo FlagInfo;
      54              :     typedef AbstractLookupTable<FlippedEdge<E, N, V>, V> FlippedLookupTable;
      55              : 
      56              :     /** @brief Constructor
      57              :      * @param[in] numberOfLevels The number of levels
      58              :      * @param[in] edges The container with all edges of the network
      59              :      * @param[in] unbuildIsWarning The flag indicating whether network unbuilds should issue warnings or errors
      60              :      * @param[in] flippedOperation The operation for a backward graph with flipped edges
      61              :      * @param[in] flippedLookup The lookup table for a backward graph with flipped edges
      62              :      * @param[in] havePermissions The flag indicating whether edges have permissions which must be respected
      63              :      * @param[in] haveRestrictions The flag indicating whether edges have restrictions which must be respected
      64              :      * @param[in] toProhibit The list of explicitly prohibited edges
      65              :      */
      66            0 :     AFBuilder(int numberOfLevels, const std::vector<E*>& edges, bool unbuildIsWarning,
      67              :               typename SUMOAbstractRouter<FlippedEdge<E, N, V>, V>::Operation flippedOperation,
      68              :               const std::shared_ptr<const FlippedLookupTable> flippedLookup = nullptr,
      69              :               const bool havePermissions = false, const bool haveRestrictions = false,
      70              :               const std::map<const FlippedEdge<E, N, V>*, double>* toProhibit = nullptr) :
      71            0 :         myEdges(edges),
      72            0 :         myNumberOfLevels(numberOfLevels),
      73            0 :         myNumberOfArcFlags(2 * (myNumberOfLevels - 1)),
      74              : #ifdef AFBL_DEBUG_LEVEL_0
      75              :         myArcFlagsFileName("arcflags.csv"),
      76              : #endif
      77            0 :         myAmClean(true) {
      78            0 :         for (const E* const edge : edges) {
      79            0 :             myFlagInfos.push_back(new FlagInfo(edge));
      80              :         }
      81              :         // build the backward graph with flipped edges / nodes in advance
      82              : #ifdef AFBL_DEBUG_LEVEL_0
      83              :         std::cout << "Building flipped edges (" << edges.size() << " edges) / nodes..." << std::endl;
      84              : #endif
      85            0 :         for (const E* const edge : edges) {
      86            0 :             myFlippedEdges.push_back(edge->getFlippedRoutingEdge());
      87              :         }
      88            0 :         for (FlippedEdge<E, N, V>* flippedEdge : myFlippedEdges) {
      89            0 :             flippedEdge->init();
      90              :         }
      91              : #ifdef AFBL_DEBUG_LEVEL_0
      92              :         std::cout << "Flipped edges / nodes are ready." << std::endl;
      93              : #endif
      94            0 :         myFlippedPartition = new KDTreePartition<FlippedEdge<E, N, V>, FlippedNode<E, N, V>, V>(myNumberOfLevels,
      95            0 :                 myFlippedEdges, havePermissions, haveRestrictions);
      96              : #ifdef AFBL_DEBUG_LEVEL_0
      97              :         std::cout << "Instantiating arc flag build..." << std::endl;
      98              : #endif
      99            0 :         myArcFlagBuild = new AFBuild<E, N, V, M>(myFlippedEdges, myFlippedPartition, numberOfLevels, unbuildIsWarning,
     100              :                 flippedOperation, flippedLookup, havePermissions, haveRestrictions, toProhibit);
     101              : 
     102              : #ifdef AFBL_DEBUG_LEVEL_0
     103              :         std::cout << "Arc flag build is instantiated (but still uninitialized)." << std::endl;
     104              : #endif
     105            0 :     } // end of constructor
     106              : 
     107              :     /// @brief Destructor
     108              :     ~AFBuilder();
     109              : 
     110              :     /// @brief Returns the arc flag build
     111              :     AFBuild<E, N, V, M>* getArcFlagBuild() {
     112            0 :         return myArcFlagBuild;
     113              :     }
     114              :     /// @brief Returns the edges
     115              :     const std::vector<E*>& getEdges() {
     116            0 :         return myEdges;
     117              :     }
     118              :     /// @brief Resets the builder
     119              :     void reset();
     120              :     /** @brief Build the arc flag information for the arc flag router
     121              :      * @param[in] msTime The start time of the routes in milliseconds
     122              :      * @param[in] The vehicle
     123              :      * @return The vector with the arc flag information
     124              :      */
     125              :     std::vector<FlagInfo*>& build(SUMOTime msTime, const V* const vehicle);
     126              :     /** @brief Converts a SHARC level number to a partition level number
     127              :      * @param[in] sHARCLevel The SHARC level
     128              :      * @return The partition level number
     129              :      */
     130              :     int sHARCLevel2PartitionLevel(int sHARCLevel) {
     131              :         return AFRouter<E, N, V, M>::sHARCLevel2PartitionLevel(sHARCLevel, myNumberOfLevels);
     132              :     }
     133              : 
     134              : protected:
     135              : #ifdef AFBL_DEBUG_LEVEL_0
     136              :     /** @brief Loads already precomputed arc flags from a CSV file (for testing purposes)
     137              :      * @param[in] fileName The name of the CSV file
     138              :      */
     139              :     void loadFlagsFromCsv(const std::string fileName);
     140              :     /** @brief Saves computed arc flags to a CSV file (for testing purposes)
     141              :      * @param[in] fileName The name of the CSV file
     142              :      */
     143              :     void saveFlagsToCsv(const std::string fileName);
     144              :     /** @brief Returns true iff a file with the given name exists
     145              :      * @param[in] name The name of the file to test for existence
     146              :      * @return true iff a file with the given name exists
     147              :      */
     148              :     bool fileExists(const std::string& name) {
     149              :         std::ifstream f(name.c_str());
     150              :         return f.good();
     151              :     }
     152              : #endif
     153              :     /// @brief The edges
     154              :     const std::vector<E*>& myEdges;
     155              :     /// @brief The flipped (backward) edges
     156              :     std::vector<FlippedEdge<E, N, V>*> myFlippedEdges;
     157              :     /// @brief The k-d tree partition of the backward graph with flipped edges
     158              :     KDTreePartition<FlippedEdge<E, N, V>, FlippedNode<E, N, V>, V>* myFlippedPartition;
     159              :     /// @brief The flag informations
     160              :     std::vector<FlagInfo*> myFlagInfos;
     161              :     /// @brief The arc flag build
     162              :     AFBuild<E, N, V, M>* myArcFlagBuild;
     163              :     /// @brief The number of levels of the k-d tree partition of the network
     164              :     int myNumberOfLevels;
     165              :     /// @brief The number of arc flags per each edge
     166              :     int myNumberOfArcFlags;
     167              : #ifdef AFBL_DEBUG_LEVEL_0
     168              :     /// @brief The name of the arc flags file.
     169              :     // @note This is a CSV file for convenience/testing purposes
     170              :     const std::string myArcFlagsFileName;
     171              : #endif
     172              :     bool myAmClean;
     173              : };
     174              : 
     175              : // ===========================================================================
     176              : // method definitions
     177              : // ===========================================================================
     178              : 
     179              : template<class E, class N, class V, class M>
     180            0 : AFBuilder<E, N, V, M>::~AFBuilder() {
     181            0 :     delete myArcFlagBuild;
     182            0 :     delete myFlippedPartition;
     183            0 :     for (FlagInfo* flagInfo : myFlagInfos) {
     184            0 :         delete flagInfo;
     185              :     }
     186            0 : }
     187              : 
     188              : template<class E, class N, class V, class M>
     189              : void AFBuilder<E, N, V, M>::reset() {
     190            0 :     for (FlagInfo* flagInfo : myFlagInfos) {
     191            0 :         flagInfo->reset();
     192              :     }
     193            0 :     myAmClean = true;
     194            0 : }
     195              : 
     196              : template<class E, class N, class V, class M>
     197            0 : std::vector<typename AFInfo<E>::FlagInfo*>& AFBuilder<E, N, V, M>::build(SUMOTime msTime, const V* const vehicle) {
     198            0 :     if (!myAmClean) {
     199              :         reset();
     200              :     }
     201              :     assert(myFlippedPartition);
     202            0 :     if (myFlippedPartition->isClean()) {
     203            0 :         myFlippedPartition->init(vehicle);
     204            0 :         myArcFlagBuild->setFlippedPartition(myFlippedPartition);
     205              :     } else {
     206            0 :         myFlippedPartition->reset(vehicle);
     207              :     }
     208              :     assert(myArcFlagBuild);
     209              : #ifdef AFBL_DEBUG_LEVEL_0
     210              :     bool fileExists = this->fileExists(myArcFlagsFileName);
     211              :     if (fileExists && myAmClean) {
     212              :         std::cout << "Loading arc flags from file " << myArcFlagsFileName << std::endl;
     213              :         loadFlagsFromCsv(myArcFlagsFileName);
     214              :         std::cout << "Arc flags loaded." << std::endl;
     215              :     } else {
     216              : #endif
     217            0 :         myArcFlagBuild->init(msTime, vehicle, myFlagInfos);
     218              : #ifdef AFBL_DEBUG_LEVEL_0
     219              :     }
     220              : #endif
     221            0 :     delete myFlippedPartition;
     222            0 :     myFlippedPartition = nullptr;
     223              : 
     224              : #ifdef AFBL_DEBUG_LEVEL_0
     225              :     if (!fileExists) {
     226              :         std::cout << "Saving arc flags..." << std::endl;
     227              :         // save flag vectors in a CSV file (one column, flag vectors in the order of edges)
     228              :         saveFlagsToCsv(myArcFlagsFileName);
     229              :         std::cout << "Arc flags have been saved." << std::endl;
     230              :     }
     231              : #endif
     232            0 :     myAmClean = false;
     233            0 :     return myFlagInfos;
     234              : }
     235              : 
     236              : #ifdef AFBL_DEBUG_LEVEL_0
     237              : template<class E, class N, class V, class M>
     238              : void AFBuilder<E, N, V, M>::saveFlagsToCsv(const std::string fileName) {
     239              :     std::ofstream csvFile(fileName);
     240              :     for (FlagInfo* flagInfo : myFlagInfos) {
     241              :         if ((flagInfo->arcFlags).empty()) {
     242              :             // default flag is false / zero
     243              :             std::fill_n(std::back_inserter(flagInfo->arcFlags),
     244              :                         myNumberOfArcFlags, false);
     245              :         }
     246              :         for (bool flag : flagInfo->arcFlags) {
     247              :             csvFile << flag;
     248              :         }
     249              :         csvFile << std::endl;
     250              :     }
     251              :     csvFile.close();
     252              : }
     253              : 
     254              : template<class E, class N, class V, class M>
     255              : void AFBuilder<E, N, V, M>::loadFlagsFromCsv(const std::string fileName) {
     256              :     assert(myAmClean);
     257              :     std::string fileNameCopy = fileName;
     258              :     std::ifstream csvFile(fileNameCopy);
     259              :     std::string result;
     260              :     if (!csvFile.is_open()) {
     261              :         result = fileNameCopy.insert(0, "Could not open CSV file ");
     262              :         throw std::runtime_error(result);
     263              :     }
     264              :     for (FlagInfo* flagInfo : myFlagInfos) {
     265              :         (flagInfo->arcFlags).clear();
     266              :         std::fill_n(std::back_inserter(flagInfo->arcFlags),
     267              :                     myNumberOfArcFlags, false);
     268              :         std::string line;
     269              :         if (std::getline(csvFile, line)) {
     270              :             if (line.empty()) {
     271              :                 continue;
     272              :             }
     273              :             std::stringstream stringStream(line);
     274              :             std::string flagAsString(1, '\0');
     275              :             int pos = 0;
     276              :             while (stringStream.read(&flagAsString[0], 1)) {
     277              :                 (flagInfo->arcFlags)[pos++] = (!flagAsString.compare("0") ? 0 : 1);
     278              :             }
     279              :         } else {
     280              :             result = fileNameCopy.insert(0, "CSV file ");
     281              :             throw std::runtime_error(result.append(" has not enough lines - wrong or corrupted file?"));
     282              :         }
     283              :     }
     284              :     myAmClean = false;
     285              :     csvFile.close();
     286              : }
     287              : #endif
        

Generated by: LCOV version 2.0-1