├── .gitattributes ├── .gitignore ├── .gitmodules ├── Algorithms ├── Buckets │ ├── BCCHBucketBuilder.h │ ├── BCCHClosestPoiQuery.h │ ├── BCHBucketBuilder.h │ ├── BCHClosestPoiQuery.h │ ├── BucketBuilder.h │ ├── BucketClosestPoiQuery.h │ ├── BucketEntry.h │ ├── DynamicBucketContainer.h │ └── StaticBucketContainer.h ├── CCH │ ├── CCH.h │ ├── CCHClosestPoiQuery.h │ ├── CCHMetric.h │ ├── EliminationTreeQuery.h │ └── UpwardEliminationTreeSearch.h ├── CH │ ├── CH.h │ ├── CHPathUnpacker.h │ └── CHQuery.h ├── DemandCalculation │ ├── CCHOpportunityChooser.h │ ├── ChooserDemandCalculator.h │ ├── DijkstraOpportunityChooser.h │ ├── FormulaDemandCalculator.h │ ├── KDTreeOpportunityChooser.h │ └── PopulationAssignment.h ├── Dijkstra │ ├── BiDijkstra.h │ ├── DagShortestPaths.h │ ├── Dijkstra.h │ └── DijkstraClosestPoiQuery.h ├── GraphTraversal │ ├── DepthFirstSearch.h │ ├── DfsNumbering.h │ └── StronglyConnectedComponents.h ├── Partitioning │ └── RecursiveBisection.h └── TrafficAssignment │ ├── Adapters │ ├── BiDijkstraAdapter.h │ ├── CCHAdapter.h │ ├── CHAdapter.h │ └── DijkstraAdapter.h │ ├── AllOrNothingAssignment.h │ ├── FrankWolfeAssignment.h │ ├── ObjectiveFunctions │ ├── SystemOptimum.h │ └── UserEquilibrium.h │ ├── TraversalCostFunctions │ ├── BprFunction.h │ ├── DavidsonFunction.h │ ├── InverseFunction.h │ └── ModifiedDavidsonFunction.h │ └── UnivariateMinimization.h ├── CMakeLists.txt ├── DataStructures ├── Containers │ ├── BitVector.h │ ├── ConcurrentLocalIdMap.h │ ├── LocalIdMap.h │ └── Subset.h ├── Geometry │ ├── Area.h │ ├── CoordinateTransformation.h │ ├── Helpers.h │ ├── KDTree.h │ ├── LatLng.h │ ├── Point.h │ ├── PointSet.h │ ├── Polygon.h │ ├── Rectangle.h │ └── SummedAreaTables │ │ └── OctagonalSummedAreaTable.h ├── Graph │ ├── Attributes │ │ ├── AbstractAttribute.h │ │ ├── AbstractBitAttribute.h │ │ ├── CapacityAttribute.h │ │ ├── CoordinateAttribute.h │ │ ├── EdgeIdAttribute.h │ │ ├── EdgeTailAttribute.h │ │ ├── FreeFlowSpeedAttribute.h │ │ ├── LatLngAttribute.h │ │ ├── LengthAttribute.h │ │ ├── NumLanesAttribute.h │ │ ├── NumOpportunitiesAttribute.h │ │ ├── OsmRoadCategoryAttribute.h │ │ ├── PopulationAttribute.h │ │ ├── RoadGeometryAttribute.h │ │ ├── SequentialVertexIdAttribute.h │ │ ├── SpeedLimitAttribute.h │ │ ├── TravelCostAttribute.h │ │ ├── TravelTimeAttribute.h │ │ ├── TraversalCostAttribute.h │ │ ├── UnpackingInfoAttribute.h │ │ ├── VertexIdAttribute.h │ │ └── XatfRoadCategoryAttribute.h │ ├── Export │ │ └── DefaultExporter.h │ ├── Graph.h │ └── Import │ │ ├── DimacsImporter.h │ │ ├── MatSimImporter.h │ │ ├── OsmImporter.h │ │ ├── VisumImporter.h │ │ └── XatfImporter.h ├── Labels │ ├── BasicLabelSet.h │ ├── Containers │ │ ├── ParentLabelContainer.h │ │ ├── SimpleDistanceLabelContainer.h │ │ └── StampedDistanceLabelContainer.h │ ├── ParentInfo.h │ └── SimdLabelSet.h ├── Partitioning │ ├── SeparatorDecomposition.h │ └── SeparatorTree.h ├── Queues │ ├── AddressableKHeap.h │ └── TournamentTree.h └── Utilities │ ├── DynamicRagged2DArrays.h │ ├── Matrix.h │ ├── OriginDestination.h │ ├── Permutation.h │ └── UnionFind.h ├── Experiments └── ODPairGenerator.h ├── External ├── randomc │ ├── ex-ran.cpp │ ├── license.txt │ ├── mersenne.cpp │ ├── mother.cpp │ ├── ran-instructions.pdf │ ├── rancombi.cpp │ ├── randomc.h │ ├── sfmt.cpp │ ├── sfmt.h │ ├── testirandomx.cpp │ └── userintf.cpp ├── rapidxml │ ├── license.txt │ ├── manual.html │ ├── rapidxml.hpp │ ├── rapidxml_iterators.hpp │ ├── rapidxml_print.hpp │ └── rapidxml_utils.hpp └── stocc │ ├── distrib.pdf │ ├── erfres.cpp │ ├── erfresmk.cpp │ ├── ex-cards.cpp │ ├── ex-evol1.cpp │ ├── ex-evol2.cpp │ ├── ex-lotto.cpp │ ├── ex-stoc.cpp │ ├── fnchyppr.cpp │ ├── license.txt │ ├── ran-instructions.pdf │ ├── randomc.h │ ├── sampmet.pdf │ ├── stoc1.cpp │ ├── stoc2.cpp │ ├── stoc3.cpp │ ├── stocc.h │ ├── testbino.cpp │ ├── testfnch.cpp │ ├── testhype.cpp │ ├── testmfnc.cpp │ ├── testmwnc.cpp │ ├── testpois.cpp │ ├── testwnch.cpp │ └── wnchyppr.cpp ├── LICENSE ├── Launchers ├── AssignTraffic.cc ├── CMakeLists.txt ├── CalculateDemand.cc ├── RunP2PAlgo.cc └── RunPoiAlgo.cc ├── Publications ├── DemandCalculation │ └── SIGSPATIAL19 │ │ └── RunExperiments ├── FastTA │ ├── ALENEX18 │ │ ├── ConductP2P │ │ ├── ConductTA │ │ ├── PrepareP2P │ │ └── PrepareTA │ ├── JEA │ │ ├── ConductP2P │ │ ├── ConductTA │ │ ├── DrawNetworks │ │ ├── ParameterTests │ │ ├── PrepareP2P │ │ └── PrepareTA │ └── SEA18 │ │ ├── ConductP2P │ │ ├── ConductTA │ │ ├── ParameterTests │ │ ├── PrepareP2P │ │ └── PrepareTA └── NearestNeighbors │ └── SEA21 │ └── RunExperiments ├── README.md ├── RawData ├── CMakeLists.txt ├── CalibrateOsm.cc ├── ComputeDijkstraRanks.cc ├── ComputeDistances.cc ├── ComputeUnionBoundary.cc ├── ConvertGraph.cc ├── DrawNetwork.cc ├── GenerateMatchingODPairs.cc ├── GenerateODPairs.cc ├── MeanDistancePerRank.cc ├── OsmComputeUnionOfBoundaries.py ├── ParseMobiToppFile.cc ├── ParseMtxFile.cc ├── RadiationModel.cc ├── SimplifyOsmPolyFile.py ├── Visum │ └── ZonePolygons.h ├── VisumExtractPoi.cc ├── VisumExtractTables.py └── XatfMergeCountries.py ├── Stats └── TrafficAssignment │ ├── AllOrNothingAssignmentStats.h │ └── FrankWolfeAssignmentStats.h ├── Tools ├── BinaryIO.h ├── Bitwise.h ├── CommandLine │ ├── CommandLineParser.h │ └── ProgressBar.h ├── CompilerSpecific.h ├── ConcurrentHelpers.h ├── Constants.h ├── ContainerHelpers.h ├── DateHelpers.h ├── EnumParser.h ├── LexicalCast.h ├── Logging │ ├── LogManager.h │ └── NullLogger.h ├── MachineSpecs.h ├── Math.h ├── OpenMP.h ├── Simd │ └── AlignedVector.h ├── StringHelpers.h ├── TemplateProgramming.h ├── Timer.h └── Workarounds.h └── Visualization ├── Color.h ├── GraphDrawer.h ├── Graphic.h ├── Graphics ├── PdfGraphic.h ├── PngGraphic.h └── SvgGraphic.h └── PrimitiveDrawer.h /.gitattributes: -------------------------------------------------------------------------------- 1 | # Enable automatic end-of-line normalization. 2 | * text 3 | *.pdf -text 4 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Build tree. 2 | /Build/ 3 | 4 | # Various config files. 5 | /.settings/ 6 | /.cproject 7 | /.project 8 | /.pydevproject 9 | -------------------------------------------------------------------------------- /.gitmodules: -------------------------------------------------------------------------------- 1 | [submodule "External/RoutingKit"] 2 | path = External/RoutingKit 3 | url = https://github.com/RoutingKit/RoutingKit.git 4 | [submodule "External/fast-cpp-csv-parser"] 5 | path = External/fast-cpp-csv-parser 6 | url = https://github.com/ben-strasser/fast-cpp-csv-parser.git 7 | [submodule "External/vectorclass"] 8 | path = External/vectorclass 9 | url = https://github.com/vectorclass/version2.git 10 | -------------------------------------------------------------------------------- /Algorithms/Buckets/BCCHBucketBuilder.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | #include 5 | #include 6 | 7 | #include "Algorithms/Buckets/BucketBuilder.h" 8 | #include "Algorithms/CCH/UpwardEliminationTreeSearch.h" 9 | #include "Algorithms/CH/CH.h" 10 | #include "Algorithms/CH/CHQuery.h" 11 | #include "Algorithms/Dijkstra/Dijkstra.h" 12 | #include "DataStructures/Labels/BasicLabelSet.h" 13 | #include "DataStructures/Labels/ParentInfo.h" 14 | 15 | // This class implements the construction of static customizable-CH buckets for a given set of 16 | // targets. It uses an elimination tree search that applies the stall-on-demand optimization. 17 | class BCCHBucketBuilder : public BucketBuilder, 19 | dij::CompoundCriterion< 20 | elimintree::PruningCriterion, 21 | CHQuery>::PruningCriterion, 22 | buckets::CollectSearchSpace>>> { 23 | public: 24 | // Creates a facility for building customizable-CH buckets. 25 | BCCHBucketBuilder( 26 | const CH::SearchGraph& upwardGraph, const CH::SearchGraph& downwardGraph, 27 | const std::vector& elimTree) 28 | : BucketBuilder( 29 | upwardGraph.numVertices(), 30 | CHSearch(downwardGraph, elimTree, {{}, {upwardGraph}, {targetId, searchSpaces}})) { 31 | assert(upwardGraph.numVertices() == downwardGraph.numVertices()); 32 | assert(upwardGraph.numVertices() == elimTree.size()); 33 | } 34 | }; 35 | -------------------------------------------------------------------------------- /Algorithms/Buckets/BCCHClosestPoiQuery.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "Algorithms/Buckets/BCCHBucketBuilder.h" 4 | #include "Algorithms/Buckets/BucketClosestPoiQuery.h" 5 | #include "Algorithms/CCH/CCH.h" 6 | #include "Algorithms/CCH/UpwardEliminationTreeSearch.h" 7 | #include "Algorithms/CH/CH.h" 8 | #include "Algorithms/Dijkstra/Dijkstra.h" 9 | #include "DataStructures/Labels/BasicLabelSet.h" 10 | #include "DataStructures/Labels/ParentInfo.h" 11 | 12 | // This class implements a BCCH-based closest-POI query in a road network. It uses an elimination 13 | // tree search (which does not apply stall-on-demand) for the forward search. 14 | class BCCHClosestPoiQuery : public BucketClosestPoiQuery< 15 | BCCHBucketBuilder, 16 | UpwardEliminationTreeSearch< 17 | BasicLabelSet<0, ParentInfo::NO_PARENT_INFO>, 18 | dij::CompoundCriterion< 19 | buckets::StopWhenFrontierFartherThanClosestPois, 20 | buckets::ScanBucket>>> { 21 | public: 22 | // Creates a BCCH-based closest-POI query in the specified CCH. 23 | explicit BCCHClosestPoiQuery(const CCH& cch, const CH& minCH) 24 | : BucketClosestPoiQuery( 25 | minCH.upwardGraph().numVertices(), 26 | new BucketBuilder(minCH.upwardGraph(), minCH.downwardGraph(), cch.getEliminationTree()), 27 | ForwardCHSearch( 28 | minCH.upwardGraph(), cch.getEliminationTree(), 29 | {{currentlyClosestPois}, 30 | {numPoisToBeReported, bucketContainer, currentlyClosestPois}})) {} 31 | }; 32 | -------------------------------------------------------------------------------- /Algorithms/Buckets/BCHBucketBuilder.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | 5 | #include "Algorithms/Buckets/BucketBuilder.h" 6 | #include "Algorithms/CH/CH.h" 7 | #include "Algorithms/CH/CHQuery.h" 8 | #include "Algorithms/Dijkstra/Dijkstra.h" 9 | #include "DataStructures/Graph/Attributes/TraversalCostAttribute.h" 10 | #include "DataStructures/Labels/BasicLabelSet.h" 11 | #include "DataStructures/Labels/ParentInfo.h" 12 | 13 | // This class implements the construction of static standard-CH buckets for a given set of targets. 14 | // It uses a Dijkstra-based CH search that applies the stall-on-demand optimization. 15 | class BCHBucketBuilder : public BucketBuilder, 17 | dij::NoCriterion, 18 | dij::CompoundCriterion< 19 | CHQuery>::PruningCriterion, 20 | buckets::CollectSearchSpace>>> { 21 | public: 22 | // Creates a facility for building standard-CH buckets. 23 | BCHBucketBuilder(const CH::SearchGraph& upwardGraph, const CH::SearchGraph& downwardGraph) 24 | : BucketBuilder( 25 | upwardGraph.numVertices(), 26 | CHSearch(downwardGraph, {}, {{upwardGraph}, {targetId, searchSpaces}})) { 27 | assert(upwardGraph.numVertices() == downwardGraph.numVertices()); 28 | } 29 | }; 30 | -------------------------------------------------------------------------------- /Algorithms/Buckets/BCHClosestPoiQuery.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "Algorithms/Buckets/BCHBucketBuilder.h" 4 | #include "Algorithms/Buckets/BucketClosestPoiQuery.h" 5 | #include "Algorithms/CH/CH.h" 6 | #include "Algorithms/CH/CHQuery.h" 7 | #include "Algorithms/Dijkstra/Dijkstra.h" 8 | #include "DataStructures/Graph/Attributes/TraversalCostAttribute.h" 9 | #include "DataStructures/Labels/BasicLabelSet.h" 10 | #include "DataStructures/Labels/ParentInfo.h" 11 | 12 | // This class implements a BCH-based closest-POI query in a road network. It uses a Dijkstra-based 13 | // CH search (which applies the stall-on-demand optimization) for the forward search. 14 | class BCHClosestPoiQuery : public BucketClosestPoiQuery< 15 | BCHBucketBuilder, 16 | Dijkstra< 17 | CH::SearchGraph, TraversalCostAttribute, BasicLabelSet<0, ParentInfo::NO_PARENT_INFO>, 18 | buckets::StopWhenFrontierFartherThanClosestPois, 19 | dij::CompoundCriterion< 20 | CHQuery>::PruningCriterion, 21 | buckets::ScanBucket>>> { 22 | public: 23 | // Creates a BCH-based closest-POI query in the specified CH. 24 | explicit BCHClosestPoiQuery(const CH& ch) 25 | : BucketClosestPoiQuery( 26 | ch.upwardGraph().numVertices(), 27 | new BucketBuilder(ch.upwardGraph(), ch.downwardGraph()), 28 | ForwardCHSearch( 29 | ch.upwardGraph(), {currentlyClosestPois}, 30 | {{ch.downwardGraph()}, 31 | {numPoisToBeReported, bucketContainer, currentlyClosestPois}})) {} 32 | }; 33 | -------------------------------------------------------------------------------- /Algorithms/Buckets/BucketEntry.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | #include 5 | 6 | // This class represents an entry in the bucket of a vertex v. It can be thought of as a shortcut 7 | // from v to targetId with length distToTarget. Note that the terminology was developed with 8 | // one-to-many queries in mind. In many-to-one queries, targetId stores a source ID and distToTarget 9 | // stores the distance from the corresponding source to v. 10 | struct BucketEntry { 11 | BucketEntry() noexcept = default; 12 | 13 | BucketEntry(const int targetId, const int distToTarget) noexcept 14 | : targetId(targetId), distToTarget(distToTarget) {} 15 | 16 | constexpr bool operator==(const BucketEntry& rhs) const noexcept { 17 | return targetId == rhs.targetId; 18 | } 19 | 20 | int32_t targetId = std::numeric_limits::max(); 21 | int32_t distToTarget; 22 | }; 23 | -------------------------------------------------------------------------------- /Algorithms/Buckets/DynamicBucketContainer.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | #include 5 | #include 6 | 7 | #include "DataStructures/Utilities/DynamicRagged2DArrays.h" 8 | 9 | // This class maintains a dynamic bucket for each vertex for bucket-based CH searches. We store all 10 | // bucket entries in a single dynamic value array. The entries in the same bucket are stored 11 | // consecutively in memory, in no particular order. In addition, an index array stores the starting 12 | // and ending point of each bucket's value block in the value array. 13 | // 14 | // When we remove an entry from a bucket, we fill the resulting hole in the value array with the 15 | // rightmost value in the bucket's value block, and decrement the block's ending point in the index 16 | // array. Consider an insertion of an entry into a bucket. If the element immediately after the 17 | // bucket's value block is a hole, the new entry fills this hole. Analogously, if the element before 18 | // the value block is a hole, the new entry fills that hole. Otherwise, we move the entire value 19 | // block to the end of the value array, and additionally insert a number of holes after the value 20 | // block (the number is a constant fraction of the block size). Then, there is a hole after the 21 | // block, and we proceed as described above. 22 | template 23 | class DynamicBucketContainer { 24 | public: 25 | using Bucket = ConstantValueBlock; 26 | 27 | // Constructs a container that can maintain buckets for the specified number of vertices. 28 | explicit DynamicBucketContainer(const int numVertices) : bucketPositions(numVertices) { 29 | assert(numVertices >= 0); 30 | } 31 | 32 | // Returns the bucket of the specified vertex. 33 | Bucket getBucketOf(const int vertex) const { 34 | assert(vertex >= 0); assert(vertex < bucketPositions.size()); 35 | const auto& pos = bucketPositions[vertex]; 36 | return Bucket(entries.begin() + pos.start, entries.begin() + pos.end); 37 | } 38 | 39 | // Inserts the given entry into the bucket of the specified vertex. 40 | bool insert(const int vertex, const BucketEntryT& entry) { 41 | insertion(vertex, entry, bucketPositions, entries); 42 | return true; 43 | } 44 | 45 | // Removes the entry for targetId from the bucket of the specified vertex. 46 | bool remove(const int vertex, const int targetId) { 47 | assert(vertex >= 0); assert(vertex < bucketPositions.size()); 48 | numEntriesVisited = 0; 49 | const auto& pos = bucketPositions[vertex]; 50 | for (auto i = pos.start; i < pos.end; ++i) { 51 | ++numEntriesVisited; 52 | if (entries[i].targetId == targetId) { 53 | removal(vertex, i - pos.start, bucketPositions, entries); 54 | return true; 55 | } 56 | } 57 | return false; 58 | } 59 | 60 | // Removes all entries from all buckets. 61 | void clear() { 62 | for (auto& bucketPos : bucketPositions) 63 | bucketPos.end = bucketPos.start; 64 | std::fill(entries.begin(), entries.end(), BucketEntryT()); 65 | } 66 | 67 | // Returns the number of bucket entries visited during the last remove operation. 68 | int getNumEntriesVisited() const noexcept { 69 | return numEntriesVisited; 70 | } 71 | 72 | private: 73 | using BucketPosition = ValueBlockPosition; 74 | 75 | std::vector bucketPositions; 76 | std::vector entries; 77 | int numEntriesVisited; 78 | }; 79 | -------------------------------------------------------------------------------- /Algorithms/Buckets/StaticBucketContainer.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | #include 5 | #include 6 | 7 | #include "Algorithms/Buckets/BucketEntry.h" 8 | #include "DataStructures/Utilities/DynamicRagged2DArrays.h" 9 | 10 | // This class maintains a static bucket for each vertex for bucket-based CH searches. We store all 11 | // bucket entries in a single value array. The entries in the same bucket are stored consecutively 12 | // in memory. In addition, an index array stores the starting position of each bucket's value block 13 | // in the value array. 14 | class StaticBucketContainer { 15 | template 16 | friend class BucketBuilder; 17 | 18 | public: 19 | using Bucket = ConstantValueBlock; 20 | 21 | // Returns the bucket of v. 22 | Bucket getBucketOf(const int v) const { 23 | assert(v >= 0); assert(v < bucketPositions.size() - 1); 24 | return {entries.begin() + bucketPositions[v], entries.begin() + bucketPositions[v + 1]}; 25 | } 26 | 27 | // Returns the space (in bytes) consumed by these buckets. 28 | int spaceConsumption() const noexcept { 29 | return bucketPositions.size() * sizeof(int32_t) + entries.size() * sizeof(BucketEntry); 30 | } 31 | 32 | private: 33 | // Default constructor. 34 | StaticBucketContainer() noexcept = default; 35 | 36 | std::vector bucketPositions; // The starting position of each bucket in the entry array. 37 | std::vector entries; // With entries in the same bucket stored consecutively. 38 | }; 39 | -------------------------------------------------------------------------------- /Algorithms/CH/CHPathUnpacker.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | #include 5 | #include 6 | #include 7 | 8 | #include "Algorithms/CH/CH.h" 9 | #include "Tools/Constants.h" 10 | 11 | // This class unpacks an up-down path in a contraction hierarchy (which generally contains 12 | // shortcuts) into the corresponding path in the original graph (which contains only original 13 | // edges). A path is represented as a dynamic array of edge identifiers. For efficiency, we do not 14 | // allocate a new array for each path we unpack. Instead, the caller passes an array that gets 15 | // filled with the unpacked path. Therefore, arrays can be reused in successive calls. 16 | class CHPathUnpacker { 17 | public: 18 | using Path = std::vector; 19 | 20 | explicit CHPathUnpacker(const CH& ch) : ch(ch) {} 21 | 22 | void unpackUpDownPath(const Path& upPath, const Path& downPath, Path& unpackedPath) { 23 | assert(packedPath.empty()); 24 | packedPath.insert(packedPath.end(), downPath.rbegin(), downPath.rend()); 25 | std::for_each(packedPath.begin(), packedPath.end(), [](int& edge) { edge = -(edge + 1); }); 26 | packedPath.insert(packedPath.end(), upPath.begin(), upPath.end()); 27 | 28 | while (!packedPath.empty()) { 29 | const auto edge = packedPath.back(); 30 | packedPath.pop_back(); 31 | const auto& unpackingInfo = edge >= 0 ? 32 | ch.upwardGraph().unpackingInfo(edge) : ch.downwardGraph().unpackingInfo(-edge - 1); 33 | if (unpackingInfo.second == INVALID_EDGE) { 34 | unpackedPath.push_back(unpackingInfo.first); 35 | } else { 36 | packedPath.push_back(unpackingInfo.second); 37 | packedPath.push_back(-(unpackingInfo.first + 1)); 38 | } 39 | } 40 | } 41 | 42 | private: 43 | const CH& ch; 44 | Path packedPath; 45 | }; 46 | -------------------------------------------------------------------------------- /Algorithms/DemandCalculation/ChooserDemandCalculator.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | 9 | #include "DataStructures/Graph/Graph.h" 10 | #include "Tools/CommandLine/ProgressBar.h" 11 | #include "Tools/OpenMP.h" 12 | #include "Tools/Timer.h" 13 | 14 | // A travel demand calculator based on repeatedly choosing random sources and corresponding targets. 15 | // Each source is chosen with probability proportional to its population. The target is chosen to be 16 | // the closest opportunity with sufficiently high fitness. 17 | template class OpportunityChooserT> 18 | class ChooserDemandCalculator { 19 | public: 20 | // Constructs a travel demand calculator for the specified network. 21 | explicit ChooserDemandCalculator(const GraphT& graph, const int seed, const bool verbose) noexcept 22 | : graph(graph), numOpportunities(0), seed(seed), verbose(verbose) { 23 | FORALL_VERTICES(graph, v) 24 | numOpportunities += graph.numOpportunities(v); 25 | assert(numOpportunities > 0); 26 | assert(seed >= 0); 27 | } 28 | 29 | // Generates OD pairs and writes them to the specified file. 30 | template 31 | void calculateDemand( 32 | int numODPairs, double lambda, double swapProb, const std::string& fileName, 33 | ChooserParameters&& ...params) const { 34 | Timer timer; 35 | if (verbose) std::cout << "Calculating demand: "; 36 | ProgressBar bar(numODPairs, verbose); 37 | 38 | const auto firstWeight = &graph.population(0); 39 | const auto lastWeight = &graph.population(graph.numVertices() - 1) + 1; 40 | 41 | #pragma omp parallel 42 | { 43 | OpportunityChooserT chooser(graph, seed, params...); 44 | std::minstd_rand rand(seed + omp_get_thread_num() + 1); 45 | std::discrete_distribution<> sourceDist(firstWeight, lastWeight); 46 | std::uniform_int_distribution<> rankDist(1, numOpportunities); 47 | std::bernoulli_distribution swapDist(swapProb); 48 | 49 | std::ofstream out(fileName + ".part" + std::to_string(omp_get_thread_num())); 50 | assert(out.good()); 51 | 52 | #pragma omp for schedule(static, 1) nowait 53 | for (auto i = 0; i < numODPairs; ++i) { 54 | Timer tripTimer; 55 | auto src = sourceDist(rand); 56 | auto dst = src; 57 | while (src == dst) { 58 | auto numFitOpportunities = 0; 59 | while (numFitOpportunities == 0) { 60 | const auto rank = rankDist(rand); 61 | numFitOpportunities = std::binomial_distribution<>(rank, 1 - lambda)(rand); 62 | } 63 | dst = chooser.findClosestOpportunityWithHighFitness(src, numFitOpportunities); 64 | } 65 | if (swapDist(rand)) 66 | std::swap(src, dst); 67 | const auto timeToCalculateTrip = tripTimer.elapsed(); 68 | out << src << ',' << dst << ',' << timeToCalculateTrip << '\n'; 69 | ++bar; 70 | } 71 | } 72 | 73 | bar.finish(); 74 | if (verbose) std::cout << "done (" << timer.elapsed() << "ms)." << std::endl; 75 | } 76 | 77 | private: 78 | const GraphT& graph; // The network we work on. 79 | int numOpportunities; // The total number of opportunities in the network. 80 | const int seed; // The seed with which the random number generators will be started. 81 | const bool verbose; // Should we display informative messages? 82 | }; 83 | -------------------------------------------------------------------------------- /Algorithms/DemandCalculation/DijkstraOpportunityChooser.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | #include 5 | 6 | #include "Algorithms/Dijkstra/Dijkstra.h" 7 | #include "DataStructures/Graph/Attributes/TravelTimeAttribute.h" 8 | #include "DataStructures/Graph/Graph.h" 9 | #include "DataStructures/Labels/BasicLabelSet.h" 10 | #include "DataStructures/Labels/ParentInfo.h" 11 | #include "Tools/Constants.h" 12 | #include "Tools/OpenMP.h" 13 | 14 | // A Dijkstra-based approach to choose the closest opportunity with high fitness. In the radiation 15 | // model, each opportunity has a fitness value drawn from some distribution, and each traveler has 16 | // a threshold drawn from the same distribution. Then the traveler chooses the closest opportunity 17 | // with a fitness value higher than their threshold. 18 | template 19 | class DijkstraOpportunityChooser { 20 | public: 21 | // Constructs an opportunity chooser based on Dijkstra's algorithm. 22 | explicit DijkstraOpportunityChooser(const GraphT& graph, const int seed) 23 | : graph(graph), numOpportunities(0), rand(seed + omp_get_thread_num() + 1), dijkstra(graph) { 24 | FORALL_VERTICES(graph, u) 25 | numOpportunities += graph.numOpportunities(u); 26 | assert(numOpportunities > 0); 27 | assert(seed >= 0); 28 | } 29 | 30 | // Returns the vertex with the closest opportunity with sufficiently high fitness. 31 | int findClosestOpportunityWithHighFitness(const int src, const int numFitOpportunities) { 32 | assert(numFitOpportunities > 0); 33 | std::geometric_distribution<> dist(1.0 * numFitOpportunities / numOpportunities); 34 | int u = INVALID_VERTEX, numInterveningOpportunities = numOpportunities; 35 | while (numInterveningOpportunities >= numOpportunities) 36 | numInterveningOpportunities = dist(rand); 37 | dijkstra.init({{src}}); 38 | while (numInterveningOpportunities >= 0) { 39 | assert(!dijkstra.queue.empty()); 40 | u = dijkstra.settleNextVertex(); 41 | numInterveningOpportunities -= graph.numOpportunities(u); 42 | } 43 | return u; 44 | } 45 | 46 | // Returns the cumulative number of opportunities between source and target. 47 | int computeInterveningOpportunities(const int src, const int dst) noexcept { 48 | int u = INVALID_VERTEX; 49 | int numInterveningOpportunities = -graph.numOpportunities(src) - graph.numOpportunities(dst); 50 | dijkstra.init({{src}}); 51 | while (u != dst) { 52 | assert(!dijkstra.queue.empty()); 53 | u = dijkstra.settleNextVertex(); 54 | numInterveningOpportunities += graph.numOpportunities(u); 55 | } 56 | assert(numInterveningOpportunities >= 0); 57 | return numInterveningOpportunities; 58 | } 59 | 60 | private: 61 | using Dij = Dijkstra>; 62 | 63 | const GraphT& graph; // The network we work on. 64 | int numOpportunities; // The total number of opportunities in the network. 65 | std::minstd_rand rand; // A Lehmer random number generator. 66 | Dij dijkstra; // Dijkstra's shortest-path algorithm. 67 | }; 68 | -------------------------------------------------------------------------------- /Algorithms/GraphTraversal/DepthFirstSearch.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | #include 5 | #include 6 | 7 | #include "DataStructures/Graph/Graph.h" 8 | 9 | // Non-recursive implementation of depth-first search. This class is an algorithm template. 10 | // Concrete DFS-based algorithms (like computing a DFS numbering or strongly connected components) 11 | // are derived from it by implementing various hook functions called during execution of the DFS. 12 | template 13 | class DepthFirstSearch { 14 | // Only concrete DFS-based algorithms are allowed to access the members of this class. 15 | friend ConcreteAlgoT; 16 | 17 | private: 18 | // An active vertex, i.e., a vertex that has been reached but not finished. 19 | struct ActiveVertex { 20 | // Constructs an active vertex. 21 | ActiveVertex(const int id, const int nextUnexploredEdge) 22 | : id(id), nextUnexploredEdge(nextUnexploredEdge) {} 23 | 24 | int id; // The ID of this active vertex. 25 | int nextUnexploredEdge; // The next unexplored incident edge. 26 | }; 27 | 28 | // Constructs a DFS instance. 29 | explicit DepthFirstSearch(ConcreteAlgoT& algo) : concreteAlgo(algo) { 30 | // Push a sentinel onto the stack. 31 | activeVertices.emplace(-1, -1); 32 | } 33 | 34 | // Runs a non-recursive DFS. 35 | template 36 | void run(const GraphT& graph) { 37 | concreteAlgo.unmarkVertices(graph.numVertices()); 38 | concreteAlgo.init(); 39 | FORALL_VERTICES(graph, s) 40 | if (!concreteAlgo.hasBeenReached(s)) 41 | growDfsTree(graph, s); 42 | } 43 | 44 | // Runs a non-recursive DFS starting at s. 45 | template 46 | void run(const GraphT& graph, const int s) { 47 | concreteAlgo.unmarkVertices(graph.numVertices()); 48 | concreteAlgo.init(); 49 | growDfsTree(graph, s); 50 | } 51 | 52 | // Grows a DFS tree rooted at s, calling hook functions for DFS-based algorithms during execution. 53 | template 54 | void growDfsTree(const GraphT& graph, const int s) { 55 | concreteAlgo.markAsReached(s); 56 | concreteAlgo.root(s); 57 | assert(activeVertices.size() == 1); 58 | activeVertices.top().id = s; // Set the sentinel. 59 | activeVertices.emplace(s, graph.firstEdge(s)); 60 | 61 | // Explore all active vertices in the stack, except for the sentinel. 62 | while (activeVertices.size() > 1) { 63 | ActiveVertex &v = activeVertices.top(); 64 | if (v.nextUnexploredEdge != graph.lastEdge(v.id)) { 65 | // There are edges out of v that have not been explored yet. Explore one of them. 66 | const int head = graph.edgeHead(v.nextUnexploredEdge); 67 | ++v.nextUnexploredEdge; 68 | if (concreteAlgo.hasBeenReached(head)) { 69 | concreteAlgo.traverseNonTreeEdge(v.id, head); 70 | } else { 71 | concreteAlgo.traverseTreeEdge(v.id, head); 72 | concreteAlgo.markAsReached(head); 73 | activeVertices.emplace(head, graph.firstEdge(head)); 74 | } 75 | } else { 76 | // All edges out of v have been explored. Return from v along the incoming tree edge. 77 | const int head = v.id; 78 | activeVertices.pop(); 79 | assert(activeVertices.size() == 1 || graph.containsEdge(activeVertices.top().id, head)); 80 | concreteAlgo.backtrack(activeVertices.top().id, head); 81 | } 82 | } 83 | } 84 | 85 | using Stack = std::stack>; 86 | 87 | ConcreteAlgoT& concreteAlgo; // The concrete DFS-based algorithm. 88 | Stack activeVertices; // The stack of active vertices. 89 | }; 90 | -------------------------------------------------------------------------------- /Algorithms/GraphTraversal/DfsNumbering.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | #include 5 | 6 | #include "Algorithms/GraphTraversal/DepthFirstSearch.h" 7 | 8 | // An algorithm that numbers the vertices of a graph in the order in which they are reached during 9 | // a DFS. The vertices may be reordered according to a DFS numbering in order to improve spatial 10 | // locality during shortest-path computations. This class is an instantiation of the general DFS 11 | // template, implementing the needed hook functions. 12 | class DfsNumbering { 13 | public: 14 | // Constructs a DFS instance computing DFS numbers. 15 | DfsNumbering() : dfs(*this), verticesReached(0) {} 16 | 17 | // Returns a vector indexed by vertices with zero-based DFS numbers. 18 | template 19 | std::vector run(const GraphT& graph) { 20 | dfs.run(graph); 21 | return std::vector(std::move(dfsNumbers)); 22 | } 23 | 24 | // Returns a vector indexed by vertices with zero-based DFS numbers. 25 | template 26 | std::vector run(const GraphT& graph, const int s) { 27 | dfs.run(graph, s); 28 | return std::vector(std::move(dfsNumbers)); 29 | } 30 | 31 | private: 32 | // The DFS implementation is allowed to call the hook functions. 33 | friend class DepthFirstSearch; 34 | 35 | // Functions for marking and unmarking vertices as reached. 36 | bool hasBeenReached(const int v) const { return dfsNumbers[v] >= 0; } 37 | void markAsReached(const int /*v*/) { /* implicitly marked as reached by hook functions */ } 38 | void unmarkVertices(const int numVertices) { dfsNumbers.assign(numVertices, -1); } 39 | 40 | // Hook functions called during the execution of the DFS. 41 | void init() { verticesReached = 0; } 42 | void root(const int s) { dfsNumbers[s] = verticesReached++; } 43 | void traverseTreeEdge(const int /*v*/, const int w) { dfsNumbers[w] = verticesReached++; } 44 | void traverseNonTreeEdge(const int /*v*/, const int /*w*/) { /* not needed */ } 45 | void backtrack(const int /*u*/, const int /*v*/) { /* not needed */ } 46 | 47 | DepthFirstSearch dfs; // The DFS instance executing the actual search. 48 | std::vector dfsNumbers; // The DFS numbers of the vertices. 49 | int verticesReached; // The number of vertices reached so far. 50 | }; 51 | -------------------------------------------------------------------------------- /Algorithms/TrafficAssignment/ObjectiveFunctions/SystemOptimum.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | 5 | // Represents the system-optimum (SO) objective function. The flow pattern that minimizes the SO 6 | // objective function (while satisfying the flow conservation constraint) minimizes the total 7 | // travel cost. The SO flow pattern is obtained by iterative shortest-path computations using 8 | // appropriate edge weights. 9 | template 10 | class SystemOptimum { 11 | public: 12 | // Constructs a SO objective function. 13 | SystemOptimum(TravelCostFunctionT function) : travelCostFunction(function) {} 14 | 15 | // Returns the value of the objective function for the specified edge flows. 16 | double operator()(const std::vector& flows) const { 17 | double sum = 0; 18 | for (int e = 0; e < flows.size(); ++e) 19 | sum += flows[e] * travelCostFunction(e, flows[e]); 20 | return sum; 21 | } 22 | 23 | // Returns the weight of edge e, given the flow x on e. 24 | double derivative(const int e, const double x) const { 25 | return travelCostFunction(e, x) + x * travelCostFunction.derivative(e, x); 26 | } 27 | 28 | // Returns the second order partial derivative with respect to the e-th variable x_e at x_e = x. 29 | double secondDerivative(const int e, const double x) const { 30 | return 2 * travelCostFunction.derivative(e, x) + x * travelCostFunction.secondDerivative(e, x); 31 | } 32 | 33 | private: 34 | TravelCostFunctionT travelCostFunction; // A functor returning the travel cost on an edge. 35 | }; 36 | -------------------------------------------------------------------------------- /Algorithms/TrafficAssignment/ObjectiveFunctions/UserEquilibrium.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | 5 | // Represents the user-equilibrium (UE) objective function. The flow pattern that minimizes the UE 6 | // objective function (while satisfying the flow conservation constraint) is such that all drivers 7 | // minimize their own travel cost. The UE flow pattern is obtained by iterative shortest-path 8 | // computations using appropriate edge weights. 9 | template 10 | class UserEquilibrium { 11 | public: 12 | // Constructs an UE objective function. 13 | UserEquilibrium(TravelCostFunctionT function) : travelCostFunction(function) {} 14 | 15 | // Returns the value of the objective function for the specified edge flows. 16 | double operator()(const std::vector& flows) const { 17 | double sum = 0; 18 | for (int e = 0; e < flows.size(); ++e) 19 | sum += travelCostFunction.integral(e, flows[e]); 20 | return sum; 21 | } 22 | 23 | // Returns the partial derivative with respect to the e-th variable x_e at x_e = x. 24 | double derivative(const int e, const double x) const { 25 | return travelCostFunction(e, x); 26 | } 27 | 28 | // Returns the second order partial derivative with respect to the e-th variable x_e at x_e = x. 29 | double secondDerivative(const int e, const double x) const { 30 | return travelCostFunction.derivative(e, x); 31 | } 32 | 33 | private: 34 | TravelCostFunctionT travelCostFunction; // A functor returning the travel cost on an edge. 35 | }; 36 | -------------------------------------------------------------------------------- /Algorithms/TrafficAssignment/TraversalCostFunctions/BprFunction.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | 5 | // The BPR travel cost function, relating the travel time on an edge to the flow on this edge. 6 | template 7 | class BprFunction { 8 | public: 9 | // Constructs a BPR function. 10 | BprFunction(const GraphT& graph) : graph(graph) {} 11 | 12 | // Returns the travel time on edge e, given the flow x on e. 13 | double operator()(const int e, const double x) const { 14 | const double tmp = x / graph.capacity(e); 15 | return graph.travelTime(e) * (1 + 1 * tmp * tmp); 16 | } 17 | 18 | // Returns the derivative of e's travel cost function at x. 19 | double derivative(const int e, const double x) const { 20 | const double tmp = x / graph.capacity(e); 21 | return graph.travelTime(e) * 1 * 2 * tmp / graph.capacity(e); 22 | } 23 | 24 | // Returns the second derivative of e's travel cost function at x. 25 | double secondDerivative(const int e, const double /*x*/) const { 26 | return graph.travelTime(e) * 1 * 2 * (2 - 1.0) / (graph.capacity(e) * graph.capacity(e)); 27 | } 28 | 29 | // Returns the antiderivative of e's travel cost function at x. 30 | double antiderivative(const int e, const double x) const { 31 | const double tmp = x / graph.capacity(e); 32 | return graph.travelTime(e) * (x + 1 * x * tmp * tmp / (2 + 1)); 33 | } 34 | 35 | // Returns the integral of e's travel cost function from 0 to b. 36 | double integral(const int e, const double b) const { 37 | return antiderivative(e, b) - antiderivative(e, 0); 38 | } 39 | 40 | // Returns the travel times on four consecutive edges starting at e, given the flows x on them. 41 | Vec4d operator()(const int e, const Vec4d& x) const { 42 | Vec4d time = to_double(Vec4i().load(&graph.travelTime(e))); 43 | Vec4d capacity = to_double(Vec4i().load(&graph.capacity(e))); 44 | return time * (1 + 1 * pow_const(x / capacity, 2)); 45 | } 46 | 47 | // Returns the derivative of e's travel cost function at x. 48 | Vec4d derivative(const int e, const Vec4d& x) const { 49 | Vec4d time = to_double(Vec4i().load(&graph.travelTime(e))); 50 | Vec4d capacity = to_double(Vec4i().load(&graph.capacity(e))); 51 | return time * 1 * 2 * pow_const(x / capacity, 2 - 1) / capacity; 52 | } 53 | 54 | private: 55 | const GraphT& graph; // The graph on whose edges we operate. 56 | }; 57 | -------------------------------------------------------------------------------- /Algorithms/TrafficAssignment/TraversalCostFunctions/DavidsonFunction.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | #include 5 | 6 | #include 7 | 8 | // The Davidson travel cost function, relating the travel time on an edge to the flow on this edge. 9 | template 10 | class DavidsonFunction { 11 | public: 12 | // Constructs a Davidson function. 13 | DavidsonFunction(const GraphT& graph) : graph(graph) {} 14 | 15 | // Returns the travel time on edge e, given the flow x on e. 16 | double operator()(const int e, const double x) const { 17 | assert(x >= 0); assert(x < graph.capacity(e)); 18 | return graph.travelTime(e) * (1 + 0.01 * x / (graph.capacity(e) - x)); 19 | } 20 | 21 | // Returns the derivative of e's travel cost function at x. 22 | double derivative(const int e, const double x) const { 23 | assert(x >= 0); assert(x < graph.capacity(e)); 24 | const double tmp = graph.capacity(e) - x; 25 | return graph.travelTime(e) * 0.01 * graph.capacity(e) / (tmp * tmp); 26 | } 27 | 28 | // Returns the second derivative of e's travel cost function at x. 29 | double secondDerivative(const int e, const double x) const { 30 | assert(x >= 0); assert(x < graph.capacity(e)); 31 | const double tmp = graph.capacity(e) - x; 32 | return graph.travelTime(e) * 0.01 * 2 * graph.capacity(e) / (tmp * tmp * tmp); 33 | } 34 | 35 | // Returns the antiderivative of e's travel cost function at x. 36 | double antiderivative(const int e, const double x) const { 37 | assert(x >= 0); assert(x < graph.capacity(e)); 38 | const int time = graph.travelTime(e); 39 | const int capacity = graph.capacity(e); 40 | return time * (x - 0.01 * (capacity * std::log(capacity - x) + x)); 41 | } 42 | 43 | // Returns the integral of e's travel cost function from 0 to b. 44 | double integral(const int e, const double b) const { 45 | return antiderivative(e, b) - antiderivative(e, 0); 46 | } 47 | 48 | // Returns the travel times on four consecutive edges starting at e, given the flows x on them. 49 | Vec4d operator()(const int e, const Vec4d& x) const { 50 | Vec4d time = to_double(Vec4i().load(&graph.travelTime(e))); 51 | Vec4d capacity = to_double(Vec4i().load(&graph.capacity(e))); 52 | return time * (1 + 0.01 * x / (capacity - x)); 53 | } 54 | 55 | // Returns the derivative of e's travel cost function at x. 56 | Vec4d derivative(const int e, const Vec4d& x) const { 57 | Vec4d time = to_double(Vec4i().load(&graph.travelTime(e))); 58 | Vec4d capacity = to_double(Vec4i().load(&graph.capacity(e))); 59 | return time * 0.01 * capacity / pow_const(capacity - x, 2); 60 | } 61 | 62 | private: 63 | const GraphT& graph; // The graph on whose edges we operate. 64 | }; 65 | -------------------------------------------------------------------------------- /Algorithms/TrafficAssignment/TraversalCostFunctions/InverseFunction.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | #include 5 | 6 | #include 7 | 8 | // An inverse travel cost function, which decreases (rather than increases) as the flow increases. 9 | // It should model the costs for operating public transit. The more people use public transit, the 10 | // lower the costs per person are. However, a traffic assignment minimizing solely the operational 11 | // cost may result in long detours for some passengers. Therefore, the (static) travel time also 12 | // contributes to the travel cost. 13 | template 14 | class InverseFunction { 15 | public: 16 | // Constructs an inverse travel cost function. 17 | InverseFunction(const GraphT& graph) : graph(graph) {} 18 | 19 | // Returns the travel cost on edge e, given the flow x on e. 20 | double operator()(const int e, const double x) const { 21 | assert(x >= 0); 22 | return 1.0 * graph.length(e) * (155 / (x + 1) + 0.85) + 0.0 * graph.travelTime(e); 23 | } 24 | 25 | // Returns the derivative of e's travel cost function at x. 26 | double derivative(const int e, const double x) const { 27 | assert(x >= 0); 28 | const double tmp = x + 1; 29 | return 1.0 * graph.length(e) * -155 / (tmp * tmp); 30 | } 31 | 32 | // Returns the second derivative of e's travel cost function at x. 33 | double secondDerivative(const int e, const double x) const { 34 | assert(x >= 0); 35 | const double tmp = x + 1; 36 | return 1.0 * graph.length(e) * 2 * 155 / (tmp * tmp * tmp); 37 | } 38 | 39 | // Returns the antiderivative of e's travel cost function at x. 40 | double antiderivative(const int e, const double x) const { 41 | assert(x >= 0); 42 | const int length = graph.length(e); 43 | const int time = graph.travelTime(e); 44 | return 1.0 * length * (155 * std::log(x + 1) + 0.85 * x) + 0.0 * time * x; 45 | } 46 | 47 | // Returns the integral of e's travel cost function from 0 to b. 48 | double integral(const int e, const double b) const { 49 | return antiderivative(e, b) - antiderivative(e, 0); 50 | } 51 | 52 | // Returns the travel costs on four consecutive edges starting at e, given the flows x on them. 53 | Vec4d operator()(const int e, const Vec4d& x) const { 54 | Vec4d length = to_double(Vec4i().load(&graph.length(e))); 55 | Vec4d time = to_double(Vec4i().load(&graph.travelTime(e))); 56 | return 1.0 * length * (155 / (x + 1) + 0.85) + 0.0 * time; 57 | } 58 | 59 | // Returns the derivative of e's travel cost function at x. 60 | Vec4d derivative(const int e, const Vec4d& x) const { 61 | Vec4d length = to_double(Vec4i().load(&graph.length(e))); 62 | return 1.0 * length * -155 / pow_const(x + 1, 2); 63 | } 64 | 65 | private: 66 | const GraphT& graph; // The graph on whose edges we operate. 67 | }; 68 | -------------------------------------------------------------------------------- /Algorithms/TrafficAssignment/TraversalCostFunctions/ModifiedDavidsonFunction.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | 5 | #include "Algorithms/TrafficAssignment/TraversalCostFunctions/DavidsonFunction.h" 6 | 7 | // The modified Davidson travel cost function. It relates the travel time on an edge to the flow on 8 | // this edge. 9 | template 10 | class ModifiedDavidsonFunction { 11 | public: 12 | // Constructs a modified Davidson function. 13 | ModifiedDavidsonFunction(const GraphT& graph) : graph(graph), davidson(graph) {} 14 | 15 | // Returns the travel time on edge e, given the flow x on e. 16 | double operator()(const int e, const double x) const { 17 | const double pt = 0.95 * graph.capacity(e); // The point at which we linearize. 18 | if (x <= pt) 19 | return davidson(e, x); 20 | else 21 | return davidson(e, pt) + davidson.derivative(e, pt) * (x - pt); 22 | } 23 | 24 | // Returns the derivative of e's travel cost function at x. 25 | double derivative(const int e, const double x) const { 26 | const double pt = 0.95 * graph.capacity(e); // The point at which we linearize. 27 | if (x <= pt) 28 | return davidson.derivative(e, x); 29 | else 30 | return davidson.derivative(e, pt); 31 | } 32 | 33 | // Returns the second derivative of e's travel cost function at x. 34 | double secondDerivative(const int e, const double x) const { 35 | const double pt = 0.95 * graph.capacity(e); // The point at which we linearize. 36 | if (x <= pt) 37 | return davidson.secondDerivative(e, x); 38 | else 39 | return 0; 40 | } 41 | 42 | // Returns the integral of e's travel cost function from 0 to b. 43 | double integral(const int e, const double b) const { 44 | const double pt = 0.95 * graph.capacity(e); // The point at which we linearize. 45 | if (b <= pt) 46 | return davidson.integral(e, b); 47 | else 48 | return davidson.integral(e, pt) + (b - pt) * (operator()(e, b) + operator()(e, pt)) / 2; 49 | } 50 | 51 | // Returns the travel times on four consecutive edges starting at e, given the flows x on them. 52 | Vec4d operator()(const int e, const Vec4d& x) const { 53 | Vec4d pt = 0.95 * to_double(Vec4i().load(&graph.capacity(e))); 54 | return davidson(e, min(x, pt)) + 55 | davidson.derivative(e, pt) * (max(x, pt) - pt); 56 | } 57 | 58 | // Returns the derivative of e's travel cost function at x. 59 | Vec4d derivative(const int e, const Vec4d& x) const { 60 | Vec4d pt = 0.95 * to_double(Vec4i().load(&graph.capacity(e))); 61 | return davidson.derivative(e, min(x, pt)); 62 | } 63 | 64 | private: 65 | const GraphT& graph; // The graph on whose edges we operate. 66 | DavidsonFunction davidson; // The original Davidson function. 67 | }; 68 | -------------------------------------------------------------------------------- /Algorithms/TrafficAssignment/UnivariateMinimization.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | 5 | // An implementation of the bisection method, also known as Bolzano search. Returns the minimum of 6 | // a ditonic function in the interval [a, b], with a tolerance of +/- epsilon. Note that the first 7 | // parameter is the derivative of the function to be minimized. 8 | template 9 | inline double bisectionMethod(DerivativeT derivative, double a, double b, double epsilon = 1e-15) { 10 | assert(a <= b); 11 | assert(epsilon > 0); 12 | 13 | if (derivative(a) >= 0) 14 | return a; 15 | if (derivative(b) <= 0) 16 | return b; 17 | 18 | // Repeatedly halve the current interval until it is no greater than 2 * epsilon. 19 | while (b - a > 2 * epsilon) { 20 | const auto midpoint = (b + a) / 2; 21 | if (derivative(midpoint) <= 0) 22 | a = midpoint; 23 | else 24 | b = midpoint; 25 | } 26 | return (b + a) / 2; 27 | } 28 | -------------------------------------------------------------------------------- /CMakeLists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required(VERSION 3.14 FATAL_ERROR) 2 | project(RoutingFramework CXX) 3 | 4 | # Directories containing .cc source files. 5 | set(SOURCE_DIRECTORIES Launchers RawData) 6 | 7 | # Determine the language standard. 8 | set(CMAKE_CXX_STANDARD 17) 9 | set(CMAKE_CXX_EXTENSIONS OFF) 10 | set(CMAKE_CXX_STANDARD_REQUIRED ON) 11 | 12 | # Flags when building for the Devel configuration. 13 | if(CMAKE_CXX_COMPILER_ID MATCHES GNU|Clang) 14 | set(CMAKE_CXX_FLAGS_DEVEL -O3) 15 | endif() 16 | if(NOT CMAKE_BUILD_TYPE) 17 | set(CMAKE_BUILD_TYPE Devel) 18 | endif() 19 | 20 | # Enable the compiler to use extended instructions in generated code. 21 | if(CMAKE_CXX_COMPILER_ID MATCHES GNU|Clang) 22 | set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -march=native") 23 | endif() 24 | option(DISABLE_AVX "Disable use of instructions in the AVX extended instruction set.") 25 | if(DISABLE_AVX) 26 | if(CMAKE_CXX_COMPILER_ID MATCHES GNU|Clang) 27 | set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -mno-avx") 28 | endif() 29 | endif() 30 | 31 | # Request warnings. 32 | if(CMAKE_CXX_COMPILER_ID STREQUAL GNU) 33 | set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Werror -Wfatal-errors -Wpedantic -pedantic-errors\ 34 | -Wall -Wextra -ftemplate-backtrace-limit=1 -Wno-unknown-pragmas -Wno-sign-compare") 35 | elseif(CMAKE_CXX_COMPILER_ID MATCHES Clang) 36 | set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Werror -Wall -Wextra -pedantic-errors -ferror-limit=1\ 37 | -ftemplate-backtrace-limit=1 -Wno-sign-compare") 38 | endif() 39 | 40 | include_directories(${CMAKE_SOURCE_DIR}) 41 | 42 | find_package(OpenMP) 43 | find_package(CGAL REQUIRED) 44 | find_library(cairo_LIBRARY cairo) 45 | find_library(PROJ_LIBRARY proj) 46 | find_library(RoutingKit_LIBRARY routingkit) 47 | 48 | # Clang does not support the option -frounding-math, thus remove it from the CGAL compile options. 49 | if(CMAKE_CXX_COMPILER_ID MATCHES Clang) 50 | set_target_properties(CGAL::CGAL PROPERTIES INTERFACE_COMPILE_OPTIONS "") 51 | endif() 52 | 53 | foreach(SRC_DIR ${SOURCE_DIRECTORIES}) 54 | add_subdirectory(${SRC_DIR}) 55 | endforeach() 56 | -------------------------------------------------------------------------------- /DataStructures/Containers/ConcurrentLocalIdMap.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | #include 5 | #include 6 | #include 7 | 8 | #include 9 | 10 | // This class maps a set of n IDs in the range 0..m - 1 to the range 0..n - 1, preserving the 11 | // relative order. We call the IDs in the larger range global IDs, and the IDs in the smaller 12 | // range local IDs. Note that the local IDs are sequential. This class takes the set of mapped 13 | // global IDs as a vector of 8-bit integers instead of as a bit vector. A zero value indicates 14 | // that a global ID is not mapped to a local ID. 15 | template 16 | class ConcurrentLocalIdMap { 17 | public: 18 | // Constructs a map from the specified set of n global IDs to the range 0..n - 1. 19 | explicit ConcurrentLocalIdMap(const std::vector& mappedGlobalIds) 20 | : mappedGlobalIds(mappedGlobalIds), 21 | numMappedGlobalIds((mappedGlobalIds.size() + k - 1) / k + 1) { 22 | std::vector sums; 23 | #pragma omp parallel 24 | { 25 | #pragma omp single 26 | sums.assign(omp_get_num_threads() + 1, 0); 27 | 28 | int sum = 0; 29 | 30 | #pragma omp for schedule(static) nowait 31 | for (int i = 0; i < mappedGlobalIds.size() / k; ++i) { 32 | for (int j = 0; j < k; ++j) 33 | sum += mappedGlobalIds[i * k + j]; 34 | numMappedGlobalIds[i + 1] = sum; 35 | } 36 | 37 | if (omp_get_num_threads() > 1) { 38 | sums[omp_get_thread_num() + 1] = sum; 39 | 40 | #pragma omp barrier 41 | 42 | #pragma omp single 43 | std::partial_sum(sums.begin(), sums.end(), sums.begin()); 44 | 45 | #pragma omp for schedule(static) nowait 46 | for (int i = 0; i < mappedGlobalIds.size() / k; ++i) 47 | numMappedGlobalIds[i + 1] += sums[omp_get_thread_num()]; 48 | } 49 | } 50 | 51 | const int i = mappedGlobalIds.size() / k; 52 | if (i + 1 < numMappedGlobalIds.size()) { 53 | numMappedGlobalIds[i + 1] = numMappedGlobalIds[i]; 54 | for (int j = i * k; j < mappedGlobalIds.size(); ++j) 55 | numMappedGlobalIds[i + 1] += mappedGlobalIds[j]; 56 | } 57 | } 58 | 59 | // Returns the size m of the range of global IDs. 60 | int numGlobalIds() const { 61 | return mappedGlobalIds.size(); 62 | } 63 | 64 | // Returns the size n of the range of local IDs. 65 | int numLocalIds() const { 66 | assert(!numMappedGlobalIds.empty()); 67 | return numMappedGlobalIds.back(); 68 | } 69 | 70 | // Returns true if globalId is mapped to a local ID. 71 | bool isGlobalIdMapped(const int globalId) const { 72 | assert(globalId >= 0); assert(globalId < numGlobalIds()); 73 | return mappedGlobalIds[globalId]; 74 | } 75 | 76 | // Returns the local ID globalId is mapped to. 77 | int toLocalId(const int globalId) const { 78 | assert(isGlobalIdMapped(globalId)); 79 | return numMappedGlobalIdsBefore(globalId); 80 | } 81 | 82 | // Returns the number of mapped global IDs before globalId. 83 | int numMappedGlobalIdsBefore(const int globalId) const { 84 | assert(globalId >= 0); assert(globalId < numGlobalIds()); 85 | int sum = numMappedGlobalIds[globalId / k]; 86 | for (int i = globalId / k * k; i < globalId; ++i) 87 | sum += mappedGlobalIds[i]; 88 | return sum; 89 | } 90 | 91 | private: 92 | const std::vector& mappedGlobalIds; // The set of mapped global IDs. 93 | std::vector numMappedGlobalIds; // Stores the nmb of mapped IDs before every k-th ID. 94 | }; 95 | -------------------------------------------------------------------------------- /DataStructures/Containers/LocalIdMap.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | #include 5 | #include 6 | #include 7 | 8 | #include 9 | 10 | #include "DataStructures/Containers/BitVector.h" 11 | #include "Tools/Bitwise.h" 12 | 13 | // This class maps a set of n IDs in the range 0..m - 1 to the range 0..n - 1, preserving the 14 | // relative order. We call the IDs in the larger range global IDs, and the IDs in the smaller 15 | // range local IDs. Note that the local IDs are sequential. 16 | template 17 | class LocalIdMap { 18 | public: 19 | // Constructs a map from the specified set of n global IDs to the range 0..n - 1. 20 | explicit LocalIdMap(const BitVector& mappedGlobalIds) 21 | : mappedGlobalIds(mappedGlobalIds), 22 | numMappedGlobalIds((mappedGlobalIds.size() + k - 1) / k + 1) { 23 | constexpr int blocksPerRank = k / BitVector::BITS_PER_BLOCK; 24 | std::vector sums; 25 | 26 | #pragma omp parallel 27 | { 28 | #pragma omp single 29 | sums.assign(omp_get_num_threads() + 1, 0); 30 | 31 | int sum = 0; 32 | 33 | #pragma omp for schedule(static) nowait 34 | for (int i = 0; i < (mappedGlobalIds.size() + BitVector::BITS_PER_BLOCK - 1) / k; ++i) { 35 | for (int j = 0; j < blocksPerRank; ++j) 36 | sum += bitCount(mappedGlobalIds.block(i * blocksPerRank + j)); 37 | numMappedGlobalIds[i + 1] = sum; 38 | } 39 | 40 | if (omp_get_num_threads() > 1) { 41 | sums[omp_get_thread_num() + 1] = sum; 42 | 43 | #pragma omp barrier 44 | 45 | #pragma omp single 46 | std::partial_sum(sums.begin(), sums.end(), sums.begin()); 47 | 48 | #pragma omp for schedule(static) nowait 49 | for (int i = 0; i < (mappedGlobalIds.size() + BitVector::BITS_PER_BLOCK - 1) / k; ++i) 50 | numMappedGlobalIds[i + 1] += sums[omp_get_thread_num()]; 51 | } 52 | } 53 | 54 | const int i = (mappedGlobalIds.size() + BitVector::BITS_PER_BLOCK - 1) / k; 55 | if (i + 1 < numMappedGlobalIds.size()) { 56 | numMappedGlobalIds[i + 1] = numMappedGlobalIds[i]; 57 | for (int j = i * blocksPerRank; j < mappedGlobalIds.numBlocks(); ++j) 58 | numMappedGlobalIds[i + 1] += bitCount(mappedGlobalIds.block(j)); 59 | } 60 | } 61 | 62 | // Returns the size m of the range of global IDs. 63 | int numGlobalIds() const { 64 | return mappedGlobalIds.size(); 65 | } 66 | 67 | // Returns the size n of the range of local IDs. 68 | int numLocalIds() const { 69 | assert(!numMappedGlobalIds.empty()); 70 | return numMappedGlobalIds.back(); 71 | } 72 | 73 | // Returns true if globalId is mapped to a local ID. 74 | bool isGlobalIdMapped(const int globalId) const { 75 | return mappedGlobalIds[globalId]; 76 | } 77 | 78 | // Returns the local ID globalId is mapped to. 79 | int toLocalId(const int globalId) const { 80 | assert(isGlobalIdMapped(globalId)); 81 | return numMappedGlobalIdsBefore(globalId); 82 | } 83 | 84 | // Returns the number of mapped global IDs before globalId. 85 | int numMappedGlobalIdsBefore(const int globalId) const { 86 | assert(globalId >= 0); assert(globalId < numGlobalIds()); 87 | int sum = numMappedGlobalIds[globalId / k]; 88 | int blockIndex = globalId / k * k / BitVector::BITS_PER_BLOCK; 89 | for (; blockIndex < globalId / BitVector::BITS_PER_BLOCK; ++blockIndex) 90 | sum += bitCount(mappedGlobalIds.block(blockIndex)); 91 | const int bitIndexWithinBlock = globalId % BitVector::BITS_PER_BLOCK; 92 | return sum + bitCountBeforeIndex(mappedGlobalIds.block(blockIndex), bitIndexWithinBlock); 93 | } 94 | 95 | private: 96 | const BitVector& mappedGlobalIds; // The set of mapped global IDs. 97 | std::vector numMappedGlobalIds; // Stores the number of mapped IDs before every k-th ID. 98 | }; 99 | -------------------------------------------------------------------------------- /DataStructures/Containers/Subset.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | #include 5 | #include 6 | 7 | #include "Tools/Constants.h" 8 | 9 | // This class represents a subset of a finite set of size n. Inserting elements, removing elements, 10 | // and testing elements for membership take constant time. Iterating through and clearing a subset 11 | // of size k both take time O(k). 12 | class Subset { 13 | public: 14 | // Constructs an empty subset of a finite set of the specified size. 15 | explicit Subset(const int size) : elementsToIndices(size, INVALID_INDEX) { 16 | elements.reserve(size); 17 | } 18 | 19 | // Returns an iterator referring to the first element in the subset. 20 | std::vector::const_iterator begin() const noexcept { 21 | return elements.begin(); 22 | } 23 | 24 | // Returns the past-the-end iterator for the subset. 25 | std::vector::const_iterator end() const noexcept { 26 | return elements.end(); 27 | } 28 | 29 | // Returns the number of elements in the subset. 30 | int size() const noexcept { 31 | return elements.size(); 32 | } 33 | 34 | // Inserts the specified element into the subset. Invalidates only the past-the-end iterator. 35 | bool insert(const int element) { 36 | if (contains(element)) 37 | return false; 38 | elementsToIndices[element] = elements.size(); 39 | elements.push_back(element); 40 | return true; 41 | } 42 | 43 | // Removes the specified element from the subset. May invalidate all iterators. 44 | bool remove(const int element) { 45 | if (!contains(element)) 46 | return false; 47 | elements[elementsToIndices[element]] = elements.back(); 48 | elementsToIndices[elements.back()] = elementsToIndices[element]; 49 | elements.pop_back(); 50 | elementsToIndices[element] = INVALID_INDEX; 51 | return true; 52 | } 53 | 54 | // Removes all elements in the subset. May invalidate all iterators. 55 | void clear() { 56 | for (const auto element : elements) 57 | elementsToIndices[element] = INVALID_INDEX; 58 | elements.clear(); 59 | } 60 | 61 | // Returns true if the subset contains the specified element. 62 | bool contains(const int element) const { 63 | assert(element >= 0); assert(element < elementsToIndices.size()); 64 | return elementsToIndices[element] != INVALID_INDEX; 65 | } 66 | 67 | private: 68 | std::vector elements; // The elements contained in the subset. 69 | std::vector elementsToIndices; // The index in the element array of each element. 70 | }; 71 | -------------------------------------------------------------------------------- /DataStructures/Geometry/CoordinateTransformation.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | #include 5 | 6 | #include 7 | 8 | // This class provides coordinate transformation between two coordinate reference systems, which 9 | // are specified as EPSG codes. 10 | class CoordinateTransformation { 11 | public: 12 | // EPSG codes for some widely used coordinate systems. 13 | static constexpr int ETRS89_LAEA_EUROPE = 3035; 14 | static constexpr int WGS_84 = 4326; 15 | static constexpr int OSGB_1936_BRITISH_NATIONAL_GRID = 27700; 16 | static constexpr int DHDN_GAUSS_KRUGER_ZONE_3 = 31467; 17 | static constexpr int DHDN_GAUSS_KRUGER_ZONE_4 = 31468; 18 | 19 | // Constructs a transformation between the two coordinate systems specified as EPSG codes. 20 | CoordinateTransformation(const int sourceCrs, const int targetCrs) { 21 | threadingContext = proj_context_create(); 22 | const auto src = "EPSG:" + std::to_string(sourceCrs); 23 | const auto dst = "EPSG:" + std::to_string(targetCrs); 24 | const auto trans = proj_create_crs_to_crs(threadingContext, src.c_str(), dst.c_str(), nullptr); 25 | assert(trans != 0); 26 | transformation = proj_normalize_for_visualization(threadingContext, trans); 27 | assert(transformation != 0); 28 | proj_destroy(trans); 29 | } 30 | 31 | // Copy constructor. 32 | CoordinateTransformation(const CoordinateTransformation& other) { 33 | threadingContext = proj_context_create(); 34 | transformation = proj_normalize_for_visualization(threadingContext, other.transformation); 35 | assert(transformation != 0); 36 | } 37 | 38 | // Releases all resources. 39 | ~CoordinateTransformation() { 40 | proj_destroy(transformation); 41 | proj_context_destroy(threadingContext); 42 | } 43 | 44 | // Transforms a coordinate given in the source CRS into a coordinate in the target CRS. 45 | void forward(const double srcX, const double srcY, double& dstX, double& dstY) { 46 | const auto result = proj_trans(transformation, PJ_FWD, {{srcX, srcY, 0, 0}}); 47 | dstX = result.xy.x; 48 | dstY = result.xy.y; 49 | } 50 | 51 | // Transforms a coordinate given in the target CRS into a coordinate in the source CRS. 52 | void reverse(const double srcX, const double srcY, double& dstX, double& dstY) { 53 | const auto result = proj_trans(transformation, PJ_INV, {{srcX, srcY, 0, 0}}); 54 | dstX = result.xy.x; 55 | dstY = result.xy.y; 56 | } 57 | 58 | private: 59 | PJ_CONTEXT* threadingContext; // The PROJ threading context. 60 | PJ* transformation; // The PROJ transformation object. 61 | }; 62 | -------------------------------------------------------------------------------- /DataStructures/Geometry/Helpers.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "DataStructures/Geometry/Point.h" 4 | #include "DataStructures/Geometry/Rectangle.h" 5 | #include "Tools/Math.h" 6 | 7 | // Returns the normal vector for the line l through p and q, oriented towards the left of l. 8 | inline Point normal(const Point& p, const Point& q) { 9 | return {p.y() - q.y(), q.x() - p.x()}; 10 | } 11 | 12 | // Returns 1, -1, or 0 as r lies to the left of, to the right of, or on the line through p and q. 13 | inline int orientation(const Point& p, const Point& q, const Point& r) { 14 | return signum(normal(p, q) * (r - p)); 15 | } 16 | 17 | // Returns true if the line segments pq and rs intersect. 18 | inline bool intersection(const Point& p, const Point& q, const Point& r, const Point& s) { 19 | const int o1 = orientation(p, q, r); 20 | const int o2 = orientation(p, q, s); 21 | if (o1 != o2 && orientation(r, s, p) != orientation(r, s, q)) 22 | return true; 23 | if (o1 != 0 || o2 != 0) 24 | return false; 25 | // All points are collinear. 26 | Rectangle pq(p); 27 | Rectangle rs(r); 28 | pq.extend(q); 29 | rs.extend(s); 30 | return pq.intersects(rs); 31 | } 32 | -------------------------------------------------------------------------------- /DataStructures/Geometry/Point.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | 11 | // A point on a two-dimensional plane. 12 | class Point { 13 | public: 14 | // Constructs a point at the origin. 15 | Point() noexcept : coordinates{0, 0} {} 16 | 17 | // Constructs a point at the specified location. 18 | Point(const int x, const int y) noexcept : coordinates{x, y} {} 19 | 20 | // Returns a reference to the i-th coordinate. 21 | int& operator[](const int i) { 22 | assert(i == 0 || i == 1); 23 | return coordinates[i]; 24 | } 25 | 26 | // Returns the i-th coordinate. 27 | int operator[](const int i) const { 28 | assert(i == 0 || i == 1); 29 | return coordinates[i]; 30 | } 31 | 32 | // Returns a reference to the x-coordinate. 33 | int& x() { 34 | return coordinates[0]; 35 | } 36 | 37 | // Returns the x-coordinate. 38 | int x() const { 39 | return coordinates[0]; 40 | } 41 | 42 | // Returns a reference to the y-coordinate. 43 | int& y() { 44 | return coordinates[1]; 45 | } 46 | 47 | // Returns the y-coordinate. 48 | int y() const { 49 | return coordinates[1]; 50 | } 51 | 52 | // Some useful arithmetic operators. 53 | friend Point operator+(const Point& lhs, const Point& rhs) { 54 | return {lhs.x() + rhs.x(), lhs.y() + rhs.y()}; 55 | } 56 | 57 | friend Point operator-(const Point& lhs, const Point& rhs) { 58 | return {lhs.x() - rhs.x(), lhs.y() - rhs.y()}; 59 | } 60 | 61 | friend int64_t operator*(const Point& lhs, const Point& rhs) { 62 | return static_cast(lhs.x()) * rhs.x() + static_cast(lhs.y()) * rhs.y(); 63 | } 64 | 65 | // Writes a character representation to the specified output stream. 66 | friend std::ostream& operator<<(std::ostream& os, const Point& p) { 67 | os << '(' << p.x() << ", " << p.y() << ')'; 68 | return os; 69 | } 70 | 71 | // Returns true if lhs and rhs coincide. 72 | friend bool operator==(const Point& lhs, const Point& rhs) { 73 | return lhs.coordinates == rhs.coordinates; 74 | } 75 | 76 | // Returns true if lhs and rhs do not coincide. 77 | friend bool operator!=(const Point& lhs, const Point& rhs) { 78 | return !(lhs == rhs); 79 | } 80 | 81 | // Takes the coordinate-wise minimum of this and the specified point. 82 | void min(const Point& p) { 83 | x() = std::min(x(), p.x()); 84 | y() = std::min(y(), p.y()); 85 | } 86 | 87 | // Takes the coordinate-wise maximum of this and the specified point. 88 | void max(const Point& p) { 89 | x() = std::max(x(), p.x()); 90 | y() = std::max(y(), p.y()); 91 | } 92 | 93 | // Returns the Manhattan or "city block" distance to the specified point. 94 | int getManhattanDistanceTo(const Point& p) const { 95 | return std::abs(x() - p.x()) + std::abs(y() - p.y()); 96 | } 97 | 98 | // Returns the Euclidean distance to the specified point. 99 | double getEuclideanDistanceTo(const Point& p) const { 100 | return std::sqrt(getSquaredEuclideanDistanceTo(p)); 101 | } 102 | 103 | // Returns the squared Euclidean distance to the specified point. 104 | int64_t getSquaredEuclideanDistanceTo(const Point& p) const { 105 | int64_t deltaX = x() - p.x(); 106 | int64_t deltaY = y() - p.y(); 107 | return deltaX * deltaX + deltaY * deltaY; 108 | } 109 | 110 | // Returns the chessboard, Chebyshev, or sup norm distance to the specified point. 111 | int getChebyshevDistanceTo(const Point& p) const { 112 | return std::max(std::abs(x() - p.x()), std::abs(y() - p.y())); 113 | } 114 | 115 | private: 116 | std::array coordinates; // The coordinates of this point. 117 | }; 118 | -------------------------------------------------------------------------------- /DataStructures/Geometry/PointSet.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | #include 5 | 6 | #include "DataStructures/Geometry/Point.h" 7 | #include "DataStructures/Geometry/Rectangle.h" 8 | 9 | // A set of points on a two-dimensional plane. 10 | class PointSet { 11 | public: 12 | // Constructs an empty set of points. 13 | explicit PointSet(const int minCapacity = 0) { 14 | reserve(minCapacity); 15 | } 16 | 17 | // Returns the point with index idx. 18 | const Point& operator[](const int idx) const { 19 | assert(idx >= 0); assert(idx < points.size()); 20 | return points[idx]; 21 | } 22 | 23 | // Returns a bounding box containing all points of this set. 24 | const Rectangle& getBoundingBox() const { 25 | assert(!empty()); 26 | return boundingBox; 27 | } 28 | 29 | // Returns true if this set contains no points. 30 | bool empty() const { 31 | return points.empty(); 32 | } 33 | 34 | // Returns the number of points in this set. 35 | int size() const { 36 | return points.size(); 37 | } 38 | 39 | // Ensures that this set can hold at least minCapacity points without requiring reallocation. 40 | void reserve(const int minCapacity) { 41 | assert(minCapacity >= 0); 42 | points.reserve(minCapacity); 43 | } 44 | 45 | // Inserts the point p into this set. 46 | void insert(const Point& p) { 47 | points.push_back(p); 48 | boundingBox.extend(p); 49 | } 50 | 51 | // Removes all points from this set. 52 | void clear() { 53 | points.clear(); 54 | } 55 | 56 | private: 57 | std::vector points; // The points of this set. 58 | Rectangle boundingBox; // A bounding box containing all points of this set. 59 | }; 60 | -------------------------------------------------------------------------------- /DataStructures/Geometry/Rectangle.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | #include 5 | 6 | #include "DataStructures/Geometry/Point.h" 7 | #include "Tools/Constants.h" 8 | 9 | // A rectangle on a two-dimensional plane with sides parallel to the x- and y-axis. 10 | class Rectangle { 11 | public: 12 | // Constructs an empty bounding box that can be gradually extended. 13 | Rectangle() noexcept : sw(INFTY, INFTY), ne(-INFTY, -INFTY) {} 14 | 15 | // Constructs a rectangle from a single point. 16 | explicit Rectangle(const Point& p) noexcept : sw(p), ne(p) {} 17 | 18 | // Constructs a rectangle from the points at its south-west and north-east corners. 19 | Rectangle(const Point& sw, const Point& ne) noexcept : sw(sw), ne(ne) { 20 | assert(sw.x() <= ne.x()); 21 | assert(sw.y() <= ne.y()); 22 | } 23 | 24 | // Constructs a bounding box containing all specified points. 25 | template 26 | Rectangle(PointIteratorT first, PointIteratorT last) : Rectangle() { 27 | extend(first, last); 28 | } 29 | 30 | // Returns a reference to the south-west corner. 31 | Point& southWest() noexcept { 32 | return sw; 33 | } 34 | 35 | // Returns the south-west corner. 36 | const Point& southWest() const noexcept { 37 | return sw; 38 | } 39 | 40 | // Returns a reference to the north-east corner. 41 | Point& northEast() noexcept { 42 | return ne; 43 | } 44 | 45 | // Returns the north-east corner. 46 | const Point& northEast() const noexcept { 47 | return ne; 48 | } 49 | 50 | // Returns true if p is inside the boundary of this rectangle. 51 | bool contains(const Point& p) const { 52 | return sw.x() <= p.x() && p.x() <= ne.x() && sw.y() <= p.y() && p.y() <= ne.y(); 53 | } 54 | 55 | // Returns true if this and the specified rectangle intersect. 56 | bool intersects(const Rectangle& rect) const { 57 | return ne.x() >= rect.sw.x() && sw.x() <= rect.ne.x() && 58 | ne.y() >= rect.sw.y() && sw.y() <= rect.ne.y(); 59 | } 60 | 61 | // Writes a character representation to the specified output stream. 62 | friend std::ostream& operator<<(std::ostream& os, const Rectangle& rect) { 63 | os << "(SW=" << rect.sw << ", NE=" << rect.ne << ")"; 64 | return os; 65 | } 66 | 67 | // Returns true if all corners of lhs and rhs coincide. 68 | friend bool operator==(const Rectangle& lhs, const Rectangle& rhs) { 69 | return lhs.sw == rhs.sw && lhs.ne == rhs.ne; 70 | } 71 | 72 | // Returns true if at least one corner of lhs and rhs does not coincide. 73 | friend bool operator!=(const Rectangle& lhs, const Rectangle& rhs) { 74 | return !(lhs == rhs); 75 | } 76 | 77 | // Extends this rectangle to contain the point p. 78 | void extend(const Point& p) { 79 | sw.min(p); 80 | ne.max(p); 81 | } 82 | 83 | // Extends this rectangle to contain the specified points. 84 | template 85 | void extend(PointIteratorT first, PointIteratorT last) { 86 | for (; first != last; ++first) 87 | extend(*first); 88 | } 89 | 90 | private: 91 | Point sw; // The south-west corner. 92 | Point ne; // The north-east corner. 93 | }; 94 | -------------------------------------------------------------------------------- /DataStructures/Graph/Attributes/AbstractAttribute.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "Tools/Simd/AlignedVector.h" 4 | 5 | // The common base class for all attributes. It associates a value of type T with each vertex/edge. 6 | template 7 | class AbstractAttribute { 8 | public: 9 | using Type = T; // The attribute's underlying type. 10 | 11 | // Returns the attribute's default value. 12 | static Type defaultValue() { 13 | return Type(); 14 | } 15 | 16 | protected: 17 | // Ensures that the attribute can hold at least num values without requiring reallocation. 18 | void reserve(const int num) { 19 | values.reserve(num); 20 | } 21 | 22 | AlignedVector values; // The attribute's values for the vertices/edges. 23 | }; 24 | -------------------------------------------------------------------------------- /DataStructures/Graph/Attributes/AbstractBitAttribute.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | 5 | // The common base class for all bit attributes. It associates a single bit with each vertex/edge. 6 | class AbstractBitAttribute { 7 | public: 8 | using Type = bool; // The attribute's underlying type. 9 | 10 | // Returns the attribute's default value. 11 | static Type defaultValue() { 12 | return Type(); 13 | } 14 | 15 | protected: 16 | // Ensures that the attribute can hold at least num values without requiring reallocation. 17 | void reserve(const int /*num*/) { 18 | // boost::dynamic_bitset does not support the operation reserve. 19 | } 20 | 21 | boost::dynamic_bitset<> values; // The attribute's values for the vertices/edges. 22 | }; 23 | -------------------------------------------------------------------------------- /DataStructures/Graph/Attributes/CapacityAttribute.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | 5 | #include "DataStructures/Graph/Attributes/AbstractAttribute.h" 6 | 7 | // An attribute associating a capacity with each edge of a graph. 8 | class CapacityAttribute : public AbstractAttribute { 9 | public: 10 | // Returns the capacity in vehicles/h of edge e. 11 | const Type& capacity(const int e) const { 12 | assert(e >= 0); assert(e < values.size()); 13 | return values[e]; 14 | } 15 | 16 | // Returns a reference to the capacity in vehicles/h of edge e. 17 | Type& capacity(const int e) { 18 | assert(e >= 0); assert(e < values.size()); 19 | return values[e]; 20 | } 21 | 22 | protected: 23 | static constexpr const char* NAME = "capacity"; // The attribute's unique name. 24 | }; 25 | -------------------------------------------------------------------------------- /DataStructures/Graph/Attributes/CoordinateAttribute.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | 5 | #include "DataStructures/Geometry/Point.h" 6 | #include "DataStructures/Graph/Attributes/AbstractAttribute.h" 7 | 8 | // An attribute associating a coordinate with each vertex of a graph. 9 | class CoordinateAttribute : public AbstractAttribute { 10 | public: 11 | // Returns the coordinate of vertex v. 12 | const Type& coordinate(const int v) const { 13 | assert(v >= 0); assert(v < values.size()); 14 | return values[v]; 15 | } 16 | 17 | // Returns a reference to the coordinate of vertex v. 18 | Type& coordinate(const int v) { 19 | assert(v >= 0); assert(v < values.size()); 20 | return values[v]; 21 | } 22 | 23 | protected: 24 | static constexpr const char* NAME = "coordinate"; // The attribute's unique name. 25 | }; 26 | -------------------------------------------------------------------------------- /DataStructures/Graph/Attributes/EdgeIdAttribute.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | 5 | #include "DataStructures/Graph/Attributes/AbstractAttribute.h" 6 | #include "Tools/Constants.h" 7 | 8 | // An attribute associating an ID with each edge of a graph. 9 | class EdgeIdAttribute : public AbstractAttribute { 10 | public: 11 | // Returns the attribute's default value. 12 | static Type defaultValue() { 13 | return INVALID_ID; 14 | } 15 | 16 | // Returns the ID of edge e. 17 | const Type& edgeId(const int e) const { 18 | assert(e >= 0); assert(e < values.size()); 19 | return values[e]; 20 | } 21 | 22 | // Returns a reference to the ID of edge e. 23 | Type& edgeId(const int e) { 24 | assert(e >= 0); assert(e < values.size()); 25 | return values[e]; 26 | } 27 | 28 | protected: 29 | static constexpr const char* NAME = "edge_id"; // The attribute's unique name. 30 | }; 31 | -------------------------------------------------------------------------------- /DataStructures/Graph/Attributes/EdgeTailAttribute.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | 5 | #include "DataStructures/Graph/Attributes/AbstractAttribute.h" 6 | #include "Tools/Constants.h" 7 | 8 | // An attribute storing explicitly the tail vertex with each edge of a graph. 9 | class EdgeTailAttribute : public AbstractAttribute { 10 | public: 11 | // Returns the attribute's default value. 12 | static Type defaultValue() { 13 | return INVALID_VERTEX; 14 | } 15 | 16 | // Returns the tail vertex of edge e. 17 | const Type& edgeTail(const int e) const { 18 | assert(e >= 0); assert(e < values.size()); 19 | return values[e]; 20 | } 21 | 22 | // Returns a reference to the tail vertex of edge e. 23 | Type& edgeTail(const int e) { 24 | assert(e >= 0); assert(e < values.size()); 25 | return values[e]; 26 | } 27 | 28 | protected: 29 | static constexpr const char* NAME = "edge_tail"; // The attribute's unique name. 30 | }; 31 | -------------------------------------------------------------------------------- /DataStructures/Graph/Attributes/FreeFlowSpeedAttribute.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | 5 | #include "DataStructures/Graph/Attributes/AbstractAttribute.h" 6 | 7 | // An attribute associating a free-flow speed (the speed at zero flow) with each edge of a graph. 8 | class FreeFlowSpeedAttribute : public AbstractAttribute { 9 | public: 10 | // Returns the free-flow speed in km/h on edge e. 11 | const Type& freeFlowSpeed(const int e) const { 12 | assert(e >= 0); assert(e < values.size()); 13 | return values[e]; 14 | } 15 | 16 | // Returns a reference to the free-flow speed in km/h on edge e. 17 | Type& freeFlowSpeed(const int e) { 18 | assert(e >= 0); assert(e < values.size()); 19 | return values[e]; 20 | } 21 | 22 | protected: 23 | static constexpr const char* NAME = "free_flow_speed"; // The attribute's unique name. 24 | }; 25 | -------------------------------------------------------------------------------- /DataStructures/Graph/Attributes/LatLngAttribute.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | 5 | #include "DataStructures/Geometry/LatLng.h" 6 | #include "DataStructures/Graph/Attributes/AbstractAttribute.h" 7 | 8 | // An attribute associating a LatLng with each vertex of a graph. 9 | class LatLngAttribute : public AbstractAttribute { 10 | public: 11 | // Returns the LatLng of vertex v. 12 | const Type& latLng(const int v) const { 13 | assert(v >= 0); assert(v < values.size()); 14 | return values[v]; 15 | } 16 | 17 | // Returns a reference to the LatLng of vertex v. 18 | Type& latLng(const int v) { 19 | assert(v >= 0); assert(v < values.size()); 20 | return values[v]; 21 | } 22 | 23 | protected: 24 | static constexpr const char* NAME = "lat_lng"; // The attribute's unique name. 25 | }; 26 | -------------------------------------------------------------------------------- /DataStructures/Graph/Attributes/LengthAttribute.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | 5 | #include "DataStructures/Graph/Attributes/AbstractAttribute.h" 6 | #include "Tools/Constants.h" 7 | 8 | // An attribute associating a physical length with each edge of a graph. 9 | class LengthAttribute : public AbstractAttribute { 10 | public: 11 | // Returns the attribute's default value. 12 | static Type defaultValue() { 13 | return INFTY; 14 | } 15 | 16 | // Returns the length in meters of edge e. 17 | const Type& length(const int e) const { 18 | assert(e >= 0); assert(e < values.size()); 19 | return values[e]; 20 | } 21 | 22 | // Returns a reference to the length in meters of edge e. 23 | Type& length(const int e) { 24 | assert(e >= 0); assert(e < values.size()); 25 | return values[e]; 26 | } 27 | 28 | protected: 29 | static constexpr const char* NAME = "length"; // The attribute's unique name. 30 | }; 31 | -------------------------------------------------------------------------------- /DataStructures/Graph/Attributes/NumLanesAttribute.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | 5 | #include "DataStructures/Graph/Attributes/AbstractAttribute.h" 6 | 7 | // An attribute associating a number of lanes with each edge of a graph. 8 | class NumLanesAttribute : public AbstractAttribute { 9 | public: 10 | // Returns the number of lanes of edge e. 11 | const Type& numLanes(const int e) const { 12 | assert(e >= 0); assert(e < values.size()); 13 | return values[e]; 14 | } 15 | 16 | // Returns a reference to the number of lanes of edge e. 17 | Type& numLanes(const int e) { 18 | assert(e >= 0); assert(e < values.size()); 19 | return values[e]; 20 | } 21 | 22 | protected: 23 | static constexpr const char* NAME = "num_lanes"; // The attribute's unique name. 24 | }; 25 | -------------------------------------------------------------------------------- /DataStructures/Graph/Attributes/NumOpportunitiesAttribute.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | 5 | #include "DataStructures/Graph/Attributes/AbstractAttribute.h" 6 | 7 | // An attribute associating a number of opportunities with each vertex of a graph. 8 | class NumOpportunitiesAttribute : public AbstractAttribute { 9 | public: 10 | // Returns the number of opportunities at vertex v. 11 | const Type& numOpportunities(const int v) const { 12 | assert(v >= 0); assert(v < values.size()); 13 | return values[v]; 14 | } 15 | 16 | // Returns a reference to the number of opportunities at vertex v. 17 | Type& numOpportunities(const int v) { 18 | assert(v >= 0); assert(v < values.size()); 19 | return values[v]; 20 | } 21 | 22 | protected: 23 | static constexpr const char* NAME = "num_opportunities"; // The attribute's unique name. 24 | }; 25 | -------------------------------------------------------------------------------- /DataStructures/Graph/Attributes/OsmRoadCategoryAttribute.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | #include 5 | 6 | #include "DataStructures/Graph/Attributes/AbstractAttribute.h" 7 | #include "Tools/EnumParser.h" 8 | 9 | // Road categories defined by OpenStreetMap. 10 | enum class OsmRoadCategory { 11 | MOTORWAY, 12 | MOTORWAY_LINK, 13 | TRUNK, 14 | TRUNK_LINK, 15 | PRIMARY, 16 | PRIMARY_LINK, 17 | SECONDARY, 18 | SECONDARY_LINK, 19 | TERTIARY, 20 | TERTIARY_LINK, 21 | UNCLASSIFIED, 22 | RESIDENTIAL, 23 | LIVING_STREET, 24 | ROAD, 25 | }; 26 | 27 | // Make EnumParser usable with OsmRoadCategory. 28 | template <> 29 | void EnumParser::initNameToEnumMap() { 30 | nameToEnum = { 31 | {"motorway", OsmRoadCategory::MOTORWAY}, 32 | {"motorway_link", OsmRoadCategory::MOTORWAY_LINK}, 33 | {"trunk", OsmRoadCategory::TRUNK}, 34 | {"trunk_link", OsmRoadCategory::TRUNK_LINK}, 35 | {"primary", OsmRoadCategory::PRIMARY}, 36 | {"primary_link", OsmRoadCategory::PRIMARY_LINK}, 37 | {"secondary", OsmRoadCategory::SECONDARY}, 38 | {"secondary_link", OsmRoadCategory::SECONDARY_LINK}, 39 | {"tertiary", OsmRoadCategory::TERTIARY}, 40 | {"tertiary_link", OsmRoadCategory::TERTIARY_LINK}, 41 | {"unclassified", OsmRoadCategory::UNCLASSIFIED}, 42 | {"residential", OsmRoadCategory::RESIDENTIAL}, 43 | {"living_street", OsmRoadCategory::LIVING_STREET}, 44 | {"road", OsmRoadCategory::ROAD} 45 | }; 46 | } 47 | 48 | // Writes the character representation of the specified OSM road category to the given stream. 49 | inline std::ostream& operator<<(std::ostream& os, const OsmRoadCategory cat) { 50 | switch (cat) { 51 | case OsmRoadCategory::MOTORWAY: os << "motorway"; break; 52 | case OsmRoadCategory::MOTORWAY_LINK: os << "motorway_link"; break; 53 | case OsmRoadCategory::TRUNK: os << "trunk"; break; 54 | case OsmRoadCategory::TRUNK_LINK: os << "trunk_link"; break; 55 | case OsmRoadCategory::PRIMARY: os << "primary"; break; 56 | case OsmRoadCategory::PRIMARY_LINK: os << "primary_link"; break; 57 | case OsmRoadCategory::SECONDARY: os << "secondary"; break; 58 | case OsmRoadCategory::SECONDARY_LINK: os << "secondary_link"; break; 59 | case OsmRoadCategory::TERTIARY: os << "tertiary"; break; 60 | case OsmRoadCategory::TERTIARY_LINK: os << "tertiary_link"; break; 61 | case OsmRoadCategory::UNCLASSIFIED: os << "unclassified"; break; 62 | case OsmRoadCategory::RESIDENTIAL: os << "residential"; break; 63 | case OsmRoadCategory::LIVING_STREET: os << "living_street"; break; 64 | case OsmRoadCategory::ROAD: os << "road"; break; 65 | } 66 | return os; 67 | } 68 | 69 | // An attribute associating an OSM road category with each edge of a graph. 70 | class OsmRoadCategoryAttribute : public AbstractAttribute { 71 | public: 72 | // Returns the attribute's default value. 73 | static Type defaultValue() { 74 | return OsmRoadCategory::ROAD; 75 | } 76 | 77 | // Returns the OSM road category of edge e. 78 | const Type& osmRoadCategory(const int e) const { 79 | assert(e >= 0); assert(e < values.size()); 80 | return values[e]; 81 | } 82 | 83 | // Returns a reference to the OSM road category of edge e. 84 | Type& osmRoadCategory(const int e) { 85 | assert(e >= 0); assert(e < values.size()); 86 | return values[e]; 87 | } 88 | 89 | protected: 90 | static constexpr const char* NAME = "osm_road_category"; // The attribute's unique name. 91 | }; 92 | -------------------------------------------------------------------------------- /DataStructures/Graph/Attributes/PopulationAttribute.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | 5 | #include "DataStructures/Graph/Attributes/AbstractAttribute.h" 6 | 7 | // An attribute associating a population size with each vertex of a graph. 8 | class PopulationAttribute : public AbstractAttribute { 9 | public: 10 | // Returns the population of vertex v. 11 | const Type& population(const int v) const { 12 | assert(v >= 0); assert(v < values.size()); 13 | return values[v]; 14 | } 15 | 16 | // Returns a reference to the population of vertex v. 17 | Type& population(const int v) { 18 | assert(v >= 0); assert(v < values.size()); 19 | return values[v]; 20 | } 21 | 22 | protected: 23 | static constexpr const char* NAME = "population"; // The attribute's unique name. 24 | }; 25 | -------------------------------------------------------------------------------- /DataStructures/Graph/Attributes/RoadGeometryAttribute.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | #include 5 | 6 | #include "DataStructures/Geometry/LatLng.h" 7 | #include "DataStructures/Graph/Attributes/AbstractAttribute.h" 8 | 9 | // An attribute associating road geometry data with each edge of a graph. 10 | class RoadGeometryAttribute : public AbstractAttribute> { 11 | public: 12 | // Returns a vector of LatLngs representing the road geometry of edge e. 13 | const Type& roadGeometry(const int e) const { 14 | assert(e >= 0); assert(e < values.size()); 15 | return values[e]; 16 | } 17 | 18 | // Returns a reference to a vector of LatLngs representing the road geometry of edge e. 19 | Type& roadGeometry(const int e) { 20 | assert(e >= 0); assert(e < values.size()); 21 | return values[e]; 22 | } 23 | 24 | protected: 25 | static constexpr const char* NAME = "road_geometry"; // The attribute's unique name. 26 | }; 27 | -------------------------------------------------------------------------------- /DataStructures/Graph/Attributes/SequentialVertexIdAttribute.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | 5 | #include "DataStructures/Graph/Attributes/AbstractAttribute.h" 6 | #include "Tools/Constants.h" 7 | 8 | // An attribute associating a sequential original ID with each vertex of a graph. The attribute can 9 | // be used to store, for each vertex of a subgraph, the corresponding vertex in the supergraph. 10 | class SequentialVertexIdAttribute : public AbstractAttribute { 11 | public: 12 | // Returns the attribute's default value. 13 | static Type defaultValue() { 14 | return INVALID_VERTEX; 15 | } 16 | 17 | // Returns a reference to the sequential original ID of vertex v. 18 | Type& sequentialVertexId(const int v) { 19 | assert(v >= 0); assert(v < values.size()); 20 | return values[v]; 21 | } 22 | 23 | // Returns a const reference to the sequential original ID of vertex v. 24 | const Type& sequentialVertexId(const int v) const { 25 | assert(v >= 0); assert(v < values.size()); 26 | return values[v]; 27 | } 28 | 29 | protected: 30 | static constexpr const char* NAME = "sequential_vertex_id"; // The attribute's unique name. 31 | }; 32 | -------------------------------------------------------------------------------- /DataStructures/Graph/Attributes/SpeedLimitAttribute.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | 5 | #include "DataStructures/Graph/Attributes/AbstractAttribute.h" 6 | 7 | // An attribute associating a speed limit with each edge of a graph. 8 | class SpeedLimitAttribute : public AbstractAttribute { 9 | public: 10 | // Returns the speed limit in km/h on edge e. 11 | const Type& speedLimit(const int e) const { 12 | assert(e >= 0); assert(e < values.size()); 13 | return values[e]; 14 | } 15 | 16 | // Returns a reference to the speed limit in km/h on edge e. 17 | Type& speedLimit(const int e) { 18 | assert(e >= 0); assert(e < values.size()); 19 | return values[e]; 20 | } 21 | 22 | protected: 23 | static constexpr const char* NAME = "speed_limit"; // The attribute's unique name. 24 | }; 25 | -------------------------------------------------------------------------------- /DataStructures/Graph/Attributes/TravelCostAttribute.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | 5 | #include "DataStructures/Graph/Attributes/AbstractAttribute.h" 6 | #include "Tools/Constants.h" 7 | 8 | // An attribute associating a travel cost with each edge of a graph. 9 | class TravelCostAttribute : public AbstractAttribute { 10 | public: 11 | // Returns the attribute's default value. 12 | static Type defaultValue() { 13 | return INFTY; 14 | } 15 | 16 | // Returns the travel cost on edge e. 17 | const Type& travelCost(const int e) const { 18 | assert(e >= 0); assert(e < values.size()); 19 | return values[e]; 20 | } 21 | 22 | // Returns a reference to the travel cost on edge e. 23 | Type& travelCost(const int e) { 24 | assert(e >= 0); assert(e < values.size()); 25 | return values[e]; 26 | } 27 | 28 | protected: 29 | static constexpr const char* NAME = "travel_cost"; // The attribute's unique name. 30 | }; 31 | -------------------------------------------------------------------------------- /DataStructures/Graph/Attributes/TravelTimeAttribute.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | 5 | #include "DataStructures/Graph/Attributes/AbstractAttribute.h" 6 | #include "Tools/Constants.h" 7 | 8 | // An attribute associating a travel time with each edge of a graph. 9 | class TravelTimeAttribute : public AbstractAttribute { 10 | public: 11 | // Returns the attribute's default value. 12 | static Type defaultValue() { 13 | return INFTY; 14 | } 15 | 16 | // Returns the travel time in tenths of a second on edge e. 17 | const Type& travelTime(const int e) const { 18 | assert(e >= 0); assert(e < values.size()); 19 | return values[e]; 20 | } 21 | 22 | // Returns a reference to the travel time in tenths of a second on edge e. 23 | Type& travelTime(const int e) { 24 | assert(e >= 0); assert(e < values.size()); 25 | return values[e]; 26 | } 27 | 28 | protected: 29 | static constexpr const char* NAME = "travel_time"; // The attribute's unique name. 30 | }; 31 | -------------------------------------------------------------------------------- /DataStructures/Graph/Attributes/TraversalCostAttribute.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | 5 | #include "DataStructures/Graph/Attributes/AbstractAttribute.h" 6 | #include "Tools/Constants.h" 7 | 8 | // An attribute associating a generic traversal cost with each edge of a graph. 9 | class TraversalCostAttribute : public AbstractAttribute { 10 | public: 11 | // Returns the attribute's default value. 12 | static Type defaultValue() { 13 | return INFTY; 14 | } 15 | 16 | // Returns the traversal cost of edge e. 17 | const Type& traversalCost(const int e) const { 18 | assert(e >= 0); assert(e < values.size()); 19 | return values[e]; 20 | } 21 | 22 | // Returns a reference to the traversal cost of edge e. 23 | Type& traversalCost(const int e) { 24 | assert(e >= 0); assert(e < values.size()); 25 | return values[e]; 26 | } 27 | 28 | protected: 29 | static constexpr const char* NAME = "traversal_cost"; // The attribute's unique name. 30 | }; 31 | -------------------------------------------------------------------------------- /DataStructures/Graph/Attributes/UnpackingInfoAttribute.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | 5 | #include "DataStructures/Graph/Attributes/AbstractAttribute.h" 6 | #include "Tools/Constants.h" 7 | 8 | // An attribute associating unpacking information with each edge of a CH search graph. The unpacking 9 | // information is a pair of 32-bit integers. In the case of shortcut edges, the first integer is the 10 | // index of the first originating edge in the downward graph, and the second integer is the index of 11 | // the second originating edge in the upward graph. In the case of input edges, the first integer is 12 | // the index of this edge in the input graph, and the second integer is set to INVALID_EDGE. 13 | class UnpackingInfoAttribute : public AbstractAttribute> { 14 | public: 15 | // Returns the attribute's default value. 16 | static Type defaultValue() { 17 | return {INVALID_EDGE, INVALID_EDGE}; 18 | } 19 | 20 | // Returns the unpacking information of edge e. 21 | const Type& unpackingInfo(const int e) const { 22 | assert(e >= 0); assert(e < values.size()); 23 | return values[e]; 24 | } 25 | 26 | // Returns a reference to the unpacking information of edge e. 27 | Type& unpackingInfo(const int e) { 28 | assert(e >= 0); assert(e < values.size()); 29 | return values[e]; 30 | } 31 | 32 | protected: 33 | static constexpr const char* NAME = "unpacking_info"; // The attribute's unique name. 34 | }; 35 | -------------------------------------------------------------------------------- /DataStructures/Graph/Attributes/VertexIdAttribute.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | 5 | #include "DataStructures/Graph/Attributes/AbstractAttribute.h" 6 | #include "Tools/Constants.h" 7 | 8 | // An attribute associating an ID with each vertex of a graph. 9 | class VertexIdAttribute : public AbstractAttribute { 10 | public: 11 | // Returns the attribute's default value. 12 | static Type defaultValue() { 13 | return INVALID_ID; 14 | } 15 | 16 | // Returns the ID of vertex v. 17 | const Type& vertexId(const int v) const { 18 | assert(v >= 0); assert(v < values.size()); 19 | return values[v]; 20 | } 21 | 22 | // Returns a reference to the ID of vertex v. 23 | Type& vertexId(const int v) { 24 | assert(v >= 0); assert(v < values.size()); 25 | return values[v]; 26 | } 27 | 28 | protected: 29 | static constexpr const char* NAME = "vertex_id"; // The attribute's unique name. 30 | }; 31 | -------------------------------------------------------------------------------- /DataStructures/Graph/Attributes/XatfRoadCategoryAttribute.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | 5 | #include "DataStructures/Graph/Attributes/AbstractAttribute.h" 6 | 7 | // Road categories defined by the XATF file format. 8 | enum class XatfRoadCategory { 9 | MOTORWAY_FAST = 1, 10 | MOTORWAY_MEDIUM = 2, 11 | MOTORWAY_SLOW = 3, 12 | NATIONAL_ROAD_FAST = 4, 13 | NATIONAL_ROAD_MEDIUM = 5, 14 | NATIONAL_ROAD_SLOW = 6, 15 | REGIONAL_ROAD_FAST = 7, 16 | REGIONAL_ROAD_MEDIUM = 8, 17 | REGIONAL_ROAD_SLOW = 9, 18 | URBAN_STREET_FAST = 10, 19 | URBAN_STREET_MEDIUM = 11, 20 | URBAN_STREET_SLOW = 12, 21 | FERRY = 13, 22 | UNUSED = 14, 23 | FOREST_ROAD = 15, 24 | }; 25 | 26 | // An attribute associating an XATF road category with each edge of a graph. 27 | class XatfRoadCategoryAttribute : public AbstractAttribute { 28 | public: 29 | // Returns the attribute's default value. 30 | static Type defaultValue() { 31 | return XatfRoadCategory::UNUSED; 32 | } 33 | 34 | // Returns the XATF road category of edge e. 35 | const Type& xatfRoadCategory(const int e) const { 36 | assert(e >= 0); assert(e < values.size()); 37 | return values[e]; 38 | } 39 | 40 | // Returns a reference to the XATF road category of edge e. 41 | Type& xatfRoadCategory(const int e) { 42 | assert(e >= 0); assert(e < values.size()); 43 | return values[e]; 44 | } 45 | 46 | protected: 47 | static constexpr const char* NAME = "xatf_road_category"; // The attribute's unique name. 48 | }; 49 | -------------------------------------------------------------------------------- /DataStructures/Graph/Export/DefaultExporter.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | class DefaultExporter { public: DefaultExporter(bool) {} void ignoreAttribute(std::string) {} }; 3 | -------------------------------------------------------------------------------- /DataStructures/Labels/Containers/SimpleDistanceLabelContainer.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | #include 5 | #include 6 | 7 | #include "Tools/Simd/AlignedVector.h" 8 | #include "Tools/Constants.h" 9 | 10 | // The simplest implementation of a container maintaining distance labels during a shortest-path 11 | // search. The distance labels are explicitly initialized with a linear sweep over all labels. 12 | template 13 | class SimpleDistanceLabelContainer { 14 | public: 15 | // Constructs a distance label container with explicit initialization. 16 | explicit SimpleDistanceLabelContainer(const int numLabels) { 17 | resize(numLabels); 18 | } 19 | 20 | // Ensures that this container can hold the specified number of distance labels. 21 | void resize(const int numLabels) { 22 | const auto currentSize = distanceLabels.size(); 23 | if (numLabels < currentSize) 24 | distanceLabels.erase(distanceLabels.begin() + numLabels, distanceLabels.end()); 25 | else 26 | distanceLabels.insert(distanceLabels.end(), numLabels - currentSize, INFTY); 27 | } 28 | 29 | // Initializes all distance labels to infinity. 30 | void init() { 31 | std::fill(distanceLabels.begin(), distanceLabels.end(), INFTY); 32 | } 33 | 34 | // Returns a reference to the distance label of vertex v. 35 | DistanceLabelT& operator[](const int v) { 36 | assert(v >= 0); assert(v < distanceLabels.size()); 37 | return distanceLabels[v]; 38 | } 39 | 40 | private: 41 | AlignedVector distanceLabels; // The distance labels of the vertices. 42 | }; 43 | -------------------------------------------------------------------------------- /DataStructures/Labels/Containers/StampedDistanceLabelContainer.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | #include 5 | #include 6 | 7 | #include "Tools/Simd/AlignedVector.h" 8 | #include "Tools/CompilerSpecific.h" 9 | #include "Tools/Constants.h" 10 | 11 | // A container maintaining distance labels. It stores a global clock and a timestamp for each 12 | // distance label. The timestamp indicates whether a distance label has a valid value or not. 13 | template 14 | class StampedDistanceLabelContainer { 15 | public: 16 | // Constructs a distance label container using timestamps. 17 | explicit StampedDistanceLabelContainer(const int numVertices) : clock(0) { 18 | resize(numVertices); 19 | } 20 | 21 | // Ensures that this container can hold the specified number of distance labels. 22 | void resize(const int numVertices) { 23 | const auto currentSize = distanceLabels.size(); 24 | if (numVertices < currentSize) { 25 | distanceLabels.erase(distanceLabels.begin() + numVertices, distanceLabels.end()); 26 | timestamps.erase(timestamps.begin() + numVertices, timestamps.end()); 27 | } else { 28 | distanceLabels.insert(distanceLabels.end(), numVertices - currentSize, DistanceLabelT()); 29 | timestamps.insert(timestamps.end(), numVertices - currentSize, 0); 30 | } 31 | } 32 | 33 | // Initializes all distance labels to infinity. 34 | void init() { 35 | ++clock; 36 | if (UNLIKELY(clock < 0)) { 37 | // Clock overflow occurred. Extremely unlikely. 38 | std::fill(timestamps.begin(), timestamps.end(), 0); 39 | clock = 1; 40 | } 41 | } 42 | 43 | // Returns a reference to the distance label of v. 44 | DistanceLabelT& operator[](const int v) { 45 | assert(v >= 0); assert(v < distanceLabels.size()); 46 | if (timestamps[v] != clock) { 47 | assert(timestamps[v] < clock); 48 | distanceLabels[v] = INFTY; 49 | timestamps[v] = clock; 50 | } 51 | return distanceLabels[v]; 52 | } 53 | 54 | private: 55 | AlignedVector distanceLabels; // The distance labels of the vertices. 56 | std::vector timestamps; // The timestamps indicating if a label is valid. 57 | int clock; // The global clock. 58 | }; 59 | -------------------------------------------------------------------------------- /DataStructures/Labels/ParentInfo.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | // This enum specifies the different kinds of parent information that can be collected by Dijkstra. 4 | enum class ParentInfo { 5 | NO_PARENT_INFO, 6 | PARENT_VERTICES_ONLY, 7 | FULL_PARENT_INFO, 8 | }; 9 | -------------------------------------------------------------------------------- /DataStructures/Partitioning/SeparatorDecomposition.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | #include 5 | #include 6 | #include 7 | 8 | #include "DataStructures/Utilities/Permutation.h" 9 | #include "Tools/BinaryIO.h" 10 | 11 | // A separator decomposition of an undirected n-vertex graph G = (V, E) is a rooted tree T whose 12 | // nodes are disjoint subsets of V and that is recursively defined as follows. If n = 1, then T 13 | // consists of a single node equal to V. If n > 1, then T consists of a root whose removal separates 14 | // G into several subgraphs. The children of the root are the roots of separator decompositions of 15 | // these subgraphs. 16 | struct SeparatorDecomposition { 17 | // A node in the separator decomposition. 18 | struct Node { 19 | int32_t leftChild; // The index of the left child. 20 | int32_t rightSibling; // The index of the right sibling. 21 | int32_t firstSeparatorVertex; // The index of the first separator vertex. 22 | int32_t lastSeparatorVertex; // The index one past the last separator vertex. 23 | }; 24 | 25 | // Returns the index in the tree of the left child of this node. 26 | int leftChild(const int node) const noexcept { 27 | assert(node >= 0); assert(node < tree.size()); 28 | return tree[node].leftChild; 29 | } 30 | 31 | // Returns the index in the tree of the right sibling of this node. 32 | int rightSibling(const int node) const noexcept { 33 | assert(node >= 0); assert(node < tree.size()); 34 | return tree[node].rightSibling; 35 | } 36 | 37 | // Returns the index in the order of the first separator vertex contained in this node. 38 | int firstSeparatorVertex(const int node) const noexcept { 39 | assert(node >= 0); assert(node < tree.size()); 40 | return tree[node].firstSeparatorVertex; 41 | } 42 | 43 | // Returns the index in the order one past the last separator vertex contained in this node. 44 | int lastSeparatorVertex(const int node) const noexcept { 45 | assert(node >= 0); assert(node < tree.size()); 46 | return tree[node].lastSeparatorVertex; 47 | } 48 | 49 | // Reads the separator decomposition from the specified binary file. 50 | void readFrom(std::ifstream& in) { 51 | bio::read(in, tree); 52 | order.readFrom(in); 53 | } 54 | 55 | // Writes the separator decomposition to the specified binary file. 56 | void writeTo(std::ofstream& out) const { 57 | bio::write(out, tree); 58 | order.writeTo(out); 59 | } 60 | 61 | std::vector tree; // The rooted tree representing this separator decomposition. 62 | Permutation order; // The associated nested dissection order. 63 | }; 64 | -------------------------------------------------------------------------------- /DataStructures/Queues/TournamentTree.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | #include 5 | #include 6 | 7 | #include "Tools/Math.h" 8 | 9 | // A tournament tree, also known as selection tree or loser tree. Suppose we have k sorted sequences 10 | // that are to be merged into a single output sequence. We repeatedly have to find the smallest from 11 | // the leading elements in the k sequences. This can be done efficiently by a tournament tree. 12 | template 13 | class TournamentTree { 14 | public: 15 | static constexpr int K = 1 << logK; // The number of sequences that are to be merged. 16 | 17 | // Constructs a tournament tree given the leading elements in the k sequences. 18 | explicit TournamentTree(const std::array& keys) { 19 | build(keys); 20 | } 21 | 22 | // Builds a tournament tree given the leading elements in the k sequences. 23 | void build(const std::array& keys) { 24 | std::array winners; 25 | for (int i = K - 2; i >= 0; i -= 2) 26 | minmax({keys[i], i}, {keys[i + 1], i + 1}, winners[getParent(i + K)], tree[getParent(i + K)]); 27 | for (int i = K - 2; i > 0; i -= 2) 28 | minmax(winners[i], winners[i + 1], winners[getParent(i)], tree[getParent(i)]); 29 | tree[0] = K != 1 ? winners[1] : Vertex{keys[0], 0}; 30 | } 31 | 32 | // Returns the key of the smallest element. 33 | int minKey() const { 34 | return tree[0].key; 35 | } 36 | 37 | // Returns the index of the sequence where the smallest element comes from. 38 | int minSeq() const { 39 | return tree[0].seq; 40 | } 41 | 42 | // Deletes the smallest element and inserts the next element from the corresponding sequence. 43 | void deleteMin(const int keyOfNextElement) { 44 | Vertex& winner = tree[0]; 45 | winner.key = keyOfNextElement; 46 | int parent = winner.seq + K; 47 | for (int i = 0; i < logK; ++i) { 48 | parent = getParent(parent); 49 | if (tree[parent] < winner) 50 | std::swap(tree[parent], winner); 51 | } 52 | } 53 | 54 | private: 55 | // A vertex in the tournament tree. It represents the leading element from one of the sequences. 56 | struct Vertex { 57 | // Returns true if lhs wins against rhs. 58 | friend bool operator<(const Vertex& lhs, const Vertex& rhs) { 59 | return lhs.key < rhs.key; 60 | } 61 | 62 | int key; // The key of the element. 63 | int seq; // The index of the sequence where the element comes from. 64 | }; 65 | 66 | // Returns the index of the parent of the specified child. 67 | static constexpr int getParent(const int child) { 68 | assert(child > 0); assert(child < 2 * K); 69 | return child / 2; 70 | } 71 | 72 | std::array tree; // The actual tournament tree. 73 | }; 74 | -------------------------------------------------------------------------------- /DataStructures/Utilities/Matrix.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | #include 5 | 6 | // A rectangular array of elements in rows and columns. 7 | template 8 | class Matrix { 9 | public: 10 | // Constructs a matrix with the specified number of rows and columns. 11 | Matrix(const int numRows = 0, const int numCols = 0, const E& val = E()) 12 | : data(numRows * numCols, val), rowCount(numRows), colCount(numCols) { 13 | assert(numRows >= 0); 14 | assert(numCols >= 0); 15 | } 16 | 17 | // Replaces elements in this matrix with numRows x numCols copies of val. 18 | void assign(const int numRows, const int numCols, const E& val) { 19 | assert(numRows >= 0); 20 | assert(numCols >= 0); 21 | data.assign(numRows * numCols, val); 22 | rowCount = numRows; 23 | colCount = numCols; 24 | } 25 | 26 | // Returns the element of the matrix in row i and column j. 27 | E& operator()(const int i, const int j) { 28 | assert(i >= 0); assert(i < rowCount); 29 | assert(j >= 0); assert(j < colCount); 30 | return data[i * colCount + j]; 31 | } 32 | 33 | // Returns the element of the matrix in row i and column j. 34 | const E& operator()(const int i, const int j) const { 35 | assert(i >= 0); assert(i < rowCount); 36 | assert(j >= 0); assert(j < colCount); 37 | return data[i * colCount + j]; 38 | } 39 | 40 | // Returns the number of rows in the matrix. 41 | int numRows() const { 42 | return rowCount; 43 | } 44 | 45 | // Returns the number of columns in the matrix. 46 | int numCols() const { 47 | return colCount; 48 | } 49 | 50 | private: 51 | std::vector data; // The elements of the matrix in row-major order. 52 | int rowCount; // The number of rows in the matrix. 53 | int colCount; // The number of columns in the matrix. 54 | }; 55 | -------------------------------------------------------------------------------- /DataStructures/Utilities/OriginDestination.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | #include 5 | #include 6 | 7 | #include 8 | 9 | #include "Tools/Constants.h" 10 | 11 | // An origin-destination (OD) pair, representing a travel demand or a query. 12 | struct OriginDestination { 13 | // Constructs an OD-pair from o to d. 14 | OriginDestination(const int o, const int d) 15 | : origin(o), destination(d) {} 16 | 17 | // Compares this OD-pair with rhs lexicographically. 18 | bool operator<(const OriginDestination& rhs) const { 19 | return origin < rhs.origin || (origin == rhs.origin && destination < rhs.destination); 20 | } 21 | 22 | int origin; 23 | int destination; 24 | }; 25 | 26 | // An origin-destination (OD) pair that additionally stores an origin zone and a destination zone. 27 | // Zones or traffic cells represent for example residential or commercial areas. 28 | struct ClusteredOriginDestination : public OriginDestination { 29 | // Constructs a clustered OD-pair from o to d. 30 | ClusteredOriginDestination(const int o, const int d, const int oZone, const int dZone) 31 | : OriginDestination(o, d), originZone(oZone), destinationZone(dZone) {} 32 | 33 | // Compares this clustered OD-pair with rhs lexicographically. 34 | bool operator<(const ClusteredOriginDestination& rhs) const { 35 | if (originZone < rhs.originZone) 36 | return true; 37 | if (originZone > rhs.originZone) 38 | return false; 39 | if (destinationZone < rhs.destinationZone) 40 | return true; 41 | if (destinationZone > rhs.destinationZone) 42 | return false; 43 | return OriginDestination::operator<(rhs); 44 | } 45 | 46 | // Returns true if the OD-pair has the same origin and destination zone as the specified one. 47 | bool hasSameZones(const ClusteredOriginDestination& other) const { 48 | return originZone == other.originZone && destinationZone == other.destinationZone; 49 | } 50 | 51 | int originZone; 52 | int destinationZone; 53 | }; 54 | 55 | // Reads the specified file into a vector of OD-pairs. 56 | std::vector importODPairsFrom(const std::string& infile) { 57 | std::vector pairs; 58 | int origin, destination; 59 | using TrimPolicy = io::trim_chars<>; 60 | using QuotePolicy = io::no_quote_escape<','>; 61 | using OverflowPolicy = io::throw_on_overflow; 62 | using CommentPolicy = io::single_line_comment<'#'>; 63 | io::CSVReader<2, TrimPolicy, QuotePolicy, OverflowPolicy, CommentPolicy> in(infile); 64 | in.read_header(io::ignore_extra_column, "origin", "destination"); 65 | while (in.read_row(origin, destination)) { 66 | assert(origin >= 0); 67 | assert(destination >= 0); 68 | pairs.emplace_back(origin, destination); 69 | } 70 | return pairs; 71 | } 72 | 73 | // Reads the specified file into a vector of clustered OD-pairs. 74 | std::vector importClusteredODPairsFrom(const std::string& infile) { 75 | std::vector pairs; 76 | int origin, destination, originZone = INVALID_ID, destinationZone = INVALID_ID; 77 | using TrimPolicy = io::trim_chars<>; 78 | using QuotePolicy = io::no_quote_escape<','>; 79 | using OverflowPolicy = io::throw_on_overflow; 80 | using CommentPolicy = io::single_line_comment<'#'>; 81 | io::CSVReader<4, TrimPolicy, QuotePolicy, OverflowPolicy, CommentPolicy> in(infile); 82 | const io::ignore_column ignore = io::ignore_extra_column | io::ignore_missing_column; 83 | in.read_header(ignore, "origin", "destination", "origin_zone", "destination_zone"); 84 | while (in.read_row(origin, destination, originZone, destinationZone)) { 85 | assert(origin >= 0); 86 | assert(destination >= 0); 87 | pairs.emplace_back(origin, destination, originZone, destinationZone); 88 | } 89 | return pairs; 90 | } 91 | -------------------------------------------------------------------------------- /DataStructures/Utilities/UnionFind.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | #include 5 | 6 | // This class maintains a partition of the set 0..n under the following operations: testing whether 7 | // two elements are in the same subset and joining two subsets into one. This implementation uses 8 | // three optimizations: union by rank, path compression, and storing parent pointers and ranks in 9 | // a single array. 10 | class UnionFind { 11 | public: 12 | // Constructs a partition with each element being a block on its own. 13 | explicit UnionFind(const int numElements) : parent(numElements, numElements) {} 14 | 15 | // Returns the representative of the block containing i. 16 | int find(int i) { 17 | assert(i >= 0); assert(i < parent.size()); 18 | int rep = i; 19 | // Find the representative of i. 20 | while (parent[rep] < parent.size()) 21 | rep = parent[rep]; 22 | // Redirect the parent pointers. 23 | while (parent[i] < parent.size()) { 24 | const int tmp = parent[i]; 25 | parent[i] = rep; 26 | i = tmp; 27 | } 28 | return rep; 29 | } 30 | 31 | // Joins the blocks containing i and j (i and j must be representatives of different blocks). 32 | void link(const int i, const int j) { 33 | assert(find(i) == i); 34 | assert(find(j) == j); 35 | assert(i != j); 36 | if (parent[i] < parent[j]) { 37 | parent[i] = j; 38 | } else { 39 | if (parent[i] == parent[j]) 40 | ++parent[i]; 41 | parent[j] = i; 42 | } 43 | } 44 | 45 | // Joins the blocks containing i and j. 46 | void unite(const int i, const int j) { 47 | if (find(i) != find(j)) 48 | link(find(i), find(j)); 49 | } 50 | 51 | private: 52 | std::vector parent; // parent[i] stores parent for each nonrep i, and rank for each rep i. 53 | }; 54 | -------------------------------------------------------------------------------- /External/randomc/ex-ran.cpp: -------------------------------------------------------------------------------- 1 | /*************************** ex-ran.cpp ********************************** 2 | * Author: Agner Fog 3 | * Date created: 2007-09-23 4 | * Last modified: 2008-11-28 5 | * Project: randomc.zip 6 | * Source URL: www.agner.org/random 7 | * 8 | * Description: 9 | * Example showing how to use random number generators from class library. * 10 | * * 11 | * Instructions: * 12 | * Compile for console mode, and run. * 13 | * * 14 | * This example uses the "Mersenne twister" random number generator. * 15 | * To use another random number generator, replace the class name 16 | * CRandomMersenne with another random number generator class and 17 | * include the necessary source file or library for that class. 18 | * * 19 | * Further documentation: 20 | * The file ran-instructions.pdf contains further documentation and 21 | * instructions. 22 | * 23 | * Copyright 2007-2008 by Agner Fog. 24 | * GNU General Public License http://www.gnu.org/licenses/gpl.html 25 | *****************************************************************************/ 26 | 27 | #include // define time() 28 | #include "randomc.h" // define classes for random number generators 29 | 30 | #ifndef MULTIFILE_PROJECT 31 | // If compiled as a single file then include these cpp files, 32 | // If compiled as a project then compile and link in these cpp files. 33 | // Include code for the chosen random number generator: 34 | #include "mersenne.cpp" 35 | // define system specific user interface: 36 | #include "userintf.cpp" 37 | #endif 38 | 39 | 40 | int main() { 41 | int seed = (int)time(0); // random seed 42 | 43 | // choose one of the random number generators: 44 | CRandomMersenne RanGen(seed); // make instance of random number generator 45 | 46 | int i; // loop counter 47 | int ir; // random integer number 48 | double fr; // random floating point number 49 | 50 | 51 | // make random integers in interval from 0 to 99, inclusive: 52 | printf("\n\nRandom integers in interval from 0 to 99:\n"); 53 | for (i = 0; i < 40; i++) { 54 | ir = RanGen.IRandom(0,99); 55 | printf ("%6i ", ir); 56 | } 57 | 58 | // make random floating point numbers in interval from 0 to 1: 59 | printf("\n\nRandom floating point numbers in interval from 0 to 1:\n"); 60 | for (i = 0; i < 32; i++) { 61 | fr = RanGen.Random(); 62 | printf ("%8.6f ", fr); 63 | } 64 | 65 | // make random bits 66 | printf("\n\nRandom bits (hexadecimal):\n"); 67 | for (i = 0; i < 32; i++) { 68 | ir = RanGen.BRandom(); 69 | printf ("%08lX ", ir); 70 | } 71 | 72 | EndOfProgram(); // system-specific exit code 73 | return 0; 74 | } 75 | 76 | -------------------------------------------------------------------------------- /External/randomc/mother.cpp: -------------------------------------------------------------------------------- 1 | /************************** mother.cpp ************************************ 2 | * Author: Agner Fog 3 | * Date created: 1999 4 | * Last modified: 2008-11-16 5 | * Project: randomc.h 6 | * Platform: This implementation uses 64-bit integers for intermediate calculations. 7 | * Works only on compilers that support 64-bit integers. 8 | * Description: 9 | * Random Number generator of type 'Mother-Of-All generator'. 10 | * 11 | * This is a multiply-with-carry type of random number generator 12 | * invented by George Marsaglia. The algorithm is: 13 | * S = 2111111111*X[n-4] + 1492*X[n-3] + 1776*X[n-2] + 5115*X[n-1] + C 14 | * X[n] = S modulo 2^32 15 | * C = floor(S / 2^32) 16 | * 17 | * Further documentation: 18 | * The file ran-instructions.pdf contains further documentation and 19 | * instructions. 20 | * 21 | * Copyright 1999-2008 by Agner Fog. 22 | * GNU General Public License http://www.gnu.org/licenses/gpl.html 23 | ******************************************************************************/ 24 | 25 | #include "randomc.h" 26 | 27 | 28 | // Output random bits 29 | uint32_t CRandomMother::BRandom() { 30 | uint64_t sum; 31 | sum = (uint64_t)2111111111UL * (uint64_t)x[3] + 32 | (uint64_t)1492 * (uint64_t)(x[2]) + 33 | (uint64_t)1776 * (uint64_t)(x[1]) + 34 | (uint64_t)5115 * (uint64_t)(x[0]) + 35 | (uint64_t)x[4]; 36 | x[3] = x[2]; x[2] = x[1]; x[1] = x[0]; 37 | x[4] = (uint32_t)(sum >> 32); // Carry 38 | x[0] = (uint32_t)sum; // Low 32 bits of sum 39 | return x[0]; 40 | } 41 | 42 | 43 | // returns a random number between 0 and 1: 44 | double CRandomMother::Random() { 45 | return (double)BRandom() * (1./(65536.*65536.)); 46 | } 47 | 48 | 49 | // returns integer random number in desired interval: 50 | int CRandomMother::IRandom(int min, int max) { 51 | // Output random integer in the interval min <= x <= max 52 | // Relative error on frequencies < 2^-32 53 | if (max <= min) { 54 | if (max == min) return min; else return 0x80000000; 55 | } 56 | // Assume 64 bit integers supported. Use multiply and shift method 57 | uint32_t interval; // Length of interval 58 | uint64_t longran; // Random bits * interval 59 | uint32_t iran; // Longran / 2^32 60 | 61 | interval = (uint32_t)(max - min + 1); 62 | longran = (uint64_t)BRandom() * interval; 63 | iran = (uint32_t)(longran >> 32); 64 | // Convert back to signed and return result 65 | return (int32_t)iran + min; 66 | } 67 | 68 | 69 | // this function initializes the random number generator: 70 | void CRandomMother::RandomInit (int seed) { 71 | int i; 72 | uint32_t s = seed; 73 | // make random numbers and put them into the buffer 74 | for (i = 0; i < 5; i++) { 75 | s = s * 29943829 - 1; 76 | x[i] = s; 77 | } 78 | // randomize some more 79 | for (i=0; i<19; i++) BRandom(); 80 | } 81 | -------------------------------------------------------------------------------- /External/randomc/ran-instructions.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/vbuchhold/routing-framework/c739dc8e81fef506a1bb8eb53ce930bfae5d8a36/External/randomc/ran-instructions.pdf -------------------------------------------------------------------------------- /External/randomc/rancombi.cpp: -------------------------------------------------------------------------------- 1 | /*************************** rancombi.cpp ********************************** 2 | * Author: Agner Fog 3 | * Date created: 2001-10-18 4 | * Last modified: 2008-11-30 5 | * Project: randomc.zip 6 | * Source URL: www.agner.org/random 7 | * 8 | * Description: 9 | * This file defines a template class for combining two different 10 | * random number generators. A combination of two random number 11 | * generators is generally better than any of the two alone. 12 | * The two generators should preferably be of very different design. 13 | * 14 | * Instructions: 15 | * To make a combined random number generator, insert the class names 16 | * of any two random number generators, as shown in the example below. 17 | * 18 | * Further documentation: 19 | * The file ran-instructions.pdf contains further documentation and 20 | * instructions. 21 | * 22 | * Copyright 2001-2008 by Agner Fog. 23 | * GNU General Public License http://www.gnu.org/licenses/gpl.html 24 | *****************************************************************************/ 25 | 26 | #include "randomc.h" 27 | 28 | // This template class combines two different random number generators 29 | // for improved randomness. R1 and R2 are any two different random number 30 | // generator classes. 31 | template 32 | class TRandomCombined : private RG1, private RG2 { 33 | public: 34 | TRandomCombined(int seed) : RG1(seed), RG2(seed+1) {}; 35 | 36 | void RandomInit(int seed) { // re-seed 37 | RG1::RandomInit(seed); 38 | RG2::RandomInit(seed+1); 39 | } 40 | 41 | double Random() { 42 | double r = RG1::Random() + RG2::Random(); 43 | if (r >= 1.) r -= 1.; 44 | return r; 45 | } 46 | 47 | int IRandom(int min, int max){ // output random integer 48 | // get integer random number in desired interval 49 | int iinterval = max - min + 1; 50 | if (iinterval <= 0) return 0x80000000; // error 51 | int r = int(iinterval * Random()); // truncate 52 | if (r >= iinterval) r = iinterval-1; 53 | return min + r; 54 | } 55 | }; 56 | 57 | #if 1 58 | ////////////////////////////////////////////////////////////////////////// 59 | // Example showing how to use the combined random number generator: 60 | #include 61 | #include 62 | #include "userintf.cpp" 63 | #include "mersenne.cpp" 64 | #include "mother.cpp" 65 | 66 | int main() { 67 | // Make an object of the template class. The names inside <> define the 68 | // class names of the two random number generators to combine. 69 | // Use time as seed. 70 | int seed = (int)time(0); 71 | int i; 72 | // Declare object of combined generator 73 | TRandomCombined RG(seed); 74 | 75 | for (i = 0; i < 20; i++) { 76 | // generate 20 random floating point numbers and 20 random integers 77 | printf("\n%14.10f %2i", RG.Random(), RG.IRandom(0,99)); 78 | } 79 | 80 | printf("\n"); 81 | EndOfProgram(); 82 | return 0; 83 | } 84 | #endif -------------------------------------------------------------------------------- /External/randomc/testirandomx.cpp: -------------------------------------------------------------------------------- 1 | /************************ testirandomx.cpp ****************************** 2 | * Author: Agner Fog 3 | * Date created: 2008-11-16 4 | * Last modified: 2008-11-28 5 | * Project: randoma and randomc 6 | * Description: 7 | * This program tests the difference between the functions IRandom and IRandomX 8 | * in the worst case scenario. In less extreme cases the difference between 9 | * IRandom and IRandomX is negligible. 10 | * 11 | * Instructions: 12 | * Compile for console mode and run. 13 | * The output shows the frequencies of different values modulo period = 3. 14 | * The values are approximately equal if the distribution is perfectly 15 | * uniform (IRandomX) within a few standard deviations (= squareroot of value). 16 | * The values are different by more than a possible sampling error for 17 | * IRandom, which shows that this function does not give an exactly 18 | * uniform distribution. It is recommended to use IRandomX rather than IRandom 19 | * if the interval length (imax-imin+1) is large. 20 | * 21 | * Copyright 2008 by Agner Fog. 22 | * GNU General Public License http://www.gnu.org/licenses/gpl.html 23 | *******************************************************************************/ 24 | 25 | #include 26 | 27 | #if 1 // Choose between Mersenne Twister and SFMT generator 28 | #include "mersenne.cpp" 29 | #define STOC_BASE CRandomMersenne // define random number generator base class 30 | #else 31 | #include "sfmt.cpp" 32 | #define STOC_BASE CRandomSFMT 33 | #endif 34 | 35 | int main() { 36 | // Define constants 37 | const int nsamp = 8005000; // Number of samples 38 | const int seed = 1; // Random number seed 39 | const int imin = -0x5FFFFFFF; // Lower limit for uniform random integers 40 | const int imax = 0x60000000; // Upper limit for uniform random integers 41 | const int period = 3; // Periodicity 42 | 43 | unsigned int i; // Loop counter 44 | unsigned int x[period]; // Sample counters 45 | int r; // Random integer 46 | 47 | STOC_BASE ran1(seed); // Make instance of random number generator 48 | for (i=0; i 0) { 54 | x[(unsigned int)r % period]++; 55 | } 56 | } 57 | printf("\nTest difference between IRandom and IRandomX"); 58 | printf("\n\nSample counts for IRandom:"); 59 | for (i = 0; i < period; i++) printf("\n%i %9u", i, x[i]); 60 | 61 | // Repeat test with IRandomX 62 | ran1.RandomInit(seed); // Reset generator with same seed 63 | for (i=0; i 0) { 69 | x[(unsigned int)r % period]++; 70 | } 71 | } 72 | printf("\n\nSample counts for IRandomX:"); 73 | for (i = 0; i < period; i++) printf("\n%i %9u", i, x[i]); 74 | 75 | printf("\n\n"); 76 | return 0; 77 | } 78 | -------------------------------------------------------------------------------- /External/randomc/userintf.cpp: -------------------------------------------------------------------------------- 1 | /*************************** userintf.cpp ********************************** 2 | * Author: Agner Fog 3 | * Date created: 4 | * Last modified: 2008-11-21 5 | * Project: stocc.zip 6 | * Source URL: www.agner.org/random 7 | * 8 | * Description: 9 | * This file specifies system-dependent input/output functions for test 10 | * programs. Must be modified according to whether the program has a console- 11 | * mode or a graphical user interface. 12 | * 13 | * Further documentation: 14 | * The file ran-instructions.pdf contains further documentation and 15 | * instructions. 16 | * 17 | * Copyright 1997-2008 by Agner Fog. 18 | * GNU General Public License http://www.gnu.org/licenses/gpl.html 19 | *****************************************************************************/ 20 | 21 | #include // define printf() function 22 | #include // define exit() function 23 | 24 | #if (defined (__BORLANDC__) || defined (_MSC_VER)) && ! defined(_WINDOWS_) 25 | #include // define getch() function 26 | #define _GETCH_DEFINED_ 27 | #endif 28 | 29 | 30 | /*********************************************************************** 31 | End of program 32 | ***********************************************************************/ 33 | 34 | void EndOfProgram() { 35 | // This function takes care of whatever is necessary to do when the 36 | // program is finished 37 | 38 | // It may be necessary to wait for the user to press a key 39 | // in order to prevent the output window from disappearing. 40 | // Remove the #ifdef and #endif lines to unconditionally wait for a key press; 41 | // Remove all three lines to not wait: 42 | #ifdef _GETCH_DEFINED_ 43 | getch(); // wait for user to press a key 44 | #endif 45 | 46 | // It may be necessary to end the program with a linefeed: 47 | #if defined (__unix__) || defined (_MSC_VER) 48 | printf("\n"); // end program with a linefeed 49 | #endif 50 | } 51 | 52 | 53 | /*********************************************************************** 54 | Error message function 55 | ***********************************************************************/ 56 | 57 | void FatalError(const char * ErrorText) { 58 | // This function outputs an error message and aborts the program. 59 | 60 | // Important: There is no universally portable way of outputting an 61 | // error message. You may have to modify this function to output 62 | // the error message in a way that is appropriate for your system. 63 | 64 | 65 | // Check if FatalAppExit exists (this macro is defined in winbase.h) 66 | #ifdef FatalAppExit 67 | 68 | // in Windows, use FatalAppExit: 69 | FatalAppExit(0, ErrorText); 70 | 71 | #else 72 | 73 | // in console mode, print error message 74 | printf ("\n%s\n", ErrorText); 75 | EndOfProgram(); 76 | 77 | #endif 78 | 79 | // Terminate program with error code 80 | exit(1); 81 | } 82 | -------------------------------------------------------------------------------- /External/rapidxml/license.txt: -------------------------------------------------------------------------------- 1 | Use of this software is granted under one of the following two licenses, 2 | to be chosen freely by the user. 3 | 4 | 1. Boost Software License - Version 1.0 - August 17th, 2003 5 | =============================================================================== 6 | 7 | Copyright (c) 2006, 2007 Marcin Kalicinski 8 | 9 | Permission is hereby granted, free of charge, to any person or organization 10 | obtaining a copy of the software and accompanying documentation covered by 11 | this license (the "Software") to use, reproduce, display, distribute, 12 | execute, and transmit the Software, and to prepare derivative works of the 13 | Software, and to permit third-parties to whom the Software is furnished to 14 | do so, all subject to the following: 15 | 16 | The copyright notices in the Software and this entire statement, including 17 | the above license grant, this restriction and the following disclaimer, 18 | must be included in all copies of the Software, in whole or in part, and 19 | all derivative works of the Software, unless such copies or derivative 20 | works are solely in the form of machine-executable object code generated by 21 | a source language processor. 22 | 23 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 24 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 25 | FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT 26 | SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE 27 | FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, 28 | ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 29 | DEALINGS IN THE SOFTWARE. 30 | 31 | 2. The MIT License 32 | =============================================================================== 33 | 34 | Copyright (c) 2006, 2007 Marcin Kalicinski 35 | 36 | Permission is hereby granted, free of charge, to any person obtaining a copy 37 | of this software and associated documentation files (the "Software"), to deal 38 | in the Software without restriction, including without limitation the rights 39 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies 40 | of the Software, and to permit persons to whom the Software is furnished to do so, 41 | subject to the following conditions: 42 | 43 | The above copyright notice and this permission notice shall be included in all 44 | copies or substantial portions of the Software. 45 | 46 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 47 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 48 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 49 | THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 50 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 51 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS 52 | IN THE SOFTWARE. 53 | -------------------------------------------------------------------------------- /External/stocc/distrib.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/vbuchhold/routing-framework/c739dc8e81fef506a1bb8eb53ce930bfae5d8a36/External/stocc/distrib.pdf -------------------------------------------------------------------------------- /External/stocc/ex-cards.cpp: -------------------------------------------------------------------------------- 1 | /*************************** ex-cards.cpp ********************************** 2 | * Author: Agner Fog 3 | * Date created: 2001-11-11 4 | * Last modified: 2008-12-12 5 | * Project: stocc.zip 6 | * Source URL: www.agner.org/random 7 | * 8 | * Description: 9 | * Example of using non-uniform random variate generator library to shuffle * 10 | * a list of numbers. * 11 | * * 12 | * This example shuffles a deck of cards. * 13 | * * 14 | * Instructions: 15 | * Compile for console mode and run. 16 | * 17 | * Further documentation: 18 | * The file ran-instructions.pdf contains further documentation and 19 | * instructions. 20 | * 21 | * Copyright 2001-2008 by Agner Fog. 22 | * GNU General Public License http://www.gnu.org/licenses/gpl.html 23 | *****************************************************************************/ 24 | 25 | #include // define time() 26 | #include "randomc.h" // define random number generator classes 27 | #include "stocc.h" // define random library classes 28 | 29 | #ifndef MULTIFILE_PROJECT 30 | // If compiled as a single file then include these cpp files, 31 | // If compiled as a project then compile and link in these cpp files. 32 | #include "mersenne.cpp" // code for random number generator 33 | #include "stoc1.cpp" // random library source code 34 | #include "userintf.cpp" // define system specific user interface 35 | #endif 36 | 37 | 38 | int main () { 39 | int seed = (int)time(0); // generate random seed 40 | StochasticLib1 sto(seed); // make instance of random library 41 | int deck[52]; // deck of 52 cards 42 | const char * ColorNames[] = { // names of 4 colors 43 | "clubs", "diamonds", "hearts", "spades" 44 | }; 45 | const char * ValueNames[] = { // names of 13 card values 46 | "A", "2", "3", "4", "5", "6", "7", "8", "9", "10", "J", "Q", "K" 47 | }; 48 | int i; // loop counter 49 | int color; // card color 50 | int value; // card value 51 | 52 | // Make shuffled list of cards. 53 | // The 52 cards are numbered from 0 to 51, where 0 = A-clubs, 1 = A-diamonds, 54 | // 51 = K-spades: 55 | sto.Shuffle(deck, 0, 52); 56 | 57 | // output heading text 58 | printf("Shuffled deck of cards:\n\n"); 59 | 60 | // loop for all cards 61 | for (i = 0; i < 52; i++) { 62 | // translate card number into color and value 63 | color = deck[i] % 4; 64 | value = deck[i] / 4; 65 | 66 | // output card 67 | printf("%8s %2s ", ColorNames[color], ValueNames[value]); 68 | // make linefeed for every four cards 69 | if (i % 4 == 3) printf("\n"); 70 | } 71 | 72 | EndOfProgram(); // system-specific exit code 73 | return 0; 74 | } 75 | -------------------------------------------------------------------------------- /External/stocc/ex-lotto.cpp: -------------------------------------------------------------------------------- 1 | /*************************** ex-lotto.cpp ********************************** 2 | * Author: Agner Fog 3 | * Date created: 2001-11-11 4 | * Last modified: 2008-11-28 5 | * Project: randomc.zip 6 | * Source URL: www.agner.org/random 7 | * 8 | * Description: 9 | * Example of using random library to generate a sequence of integer 10 | * numbers where no number occurs more than once. 11 | * 12 | * This example generates a Lotto coupon, drawing "select" different 13 | * numbers from the interval from "nmin" to "nmax", inclusive. 14 | * 15 | * Instructions: 16 | * 1. Set the parameters nmin, nmax, select to the desired values. 17 | * 2. Compile for console mode and run. 18 | * 19 | * Further documentation: 20 | * The file ran-instructions.pdf contains further documentation and 21 | * instructions. 22 | * 23 | * Copyright 2001-2008 by Agner Fog. 24 | * GNU General Public License http://www.gnu.org/licenses/gpl.html 25 | *****************************************************************************/ 26 | 27 | 28 | #include // define time() 29 | #include "stocc.h" // define random library classes 30 | 31 | #ifndef MULTIFILE_PROJECT 32 | // If compiled as a single file then include these cpp files, 33 | // If compiled as a project then compile and link in these cpp files. 34 | #include "mersenne.cpp" // code for random number generator 35 | #include "stoc1.cpp" // random library source code 36 | #include "userintf.cpp" // define system specific user interface 37 | #endif 38 | 39 | 40 | int main () { 41 | // define constants 42 | const int nmin = 1; // set the lowest allowed number 43 | const int nmax = 36; // set the highest allowed number 44 | const int select = 6; // the number of numbers to draw 45 | 46 | int seed = (int)time(0); // generate random seed 47 | StochasticLib1 sto(seed); // make instance of random library 48 | int urn[nmax-nmin+1]; // contains the shuffled numbers 49 | int i; // loop counter 50 | 51 | // Make shuffled list of numbers from nmin to nmax: 52 | sto.Shuffle(urn, nmin, nmax-nmin+1); 53 | 54 | // output heading text 55 | printf("Random numbers without duplicates:\n\n"); 56 | 57 | // loop to output the first "select" numbers 58 | for (i = 0; i < select; i++) { 59 | if (i < nmax-nmin+1) { 60 | // output number 61 | printf("%4i ", urn[i]); 62 | } 63 | } 64 | 65 | EndOfProgram(); // system-specific exit code 66 | return 0; 67 | } 68 | -------------------------------------------------------------------------------- /External/stocc/ex-stoc.cpp: -------------------------------------------------------------------------------- 1 | /*************************** ex-stoc.cpp ********************************** 2 | * Author: Agner Fog 3 | * Date created: 2001-11-11 4 | * Last modified: 2008-11-28 5 | * Project: stocc.zip 6 | * Source URL: www.agner.org/random 7 | * 8 | * Description: 9 | * Example showing how to use non-uniform random variate generator library. * 10 | * Necessary files are in stocc.zip. * 11 | * * 12 | * Instructions: 13 | * Compile for console mode and run. 14 | * 15 | * Further documentation: 16 | * The file ran-instructions.pdf contains further documentation and 17 | * instructions. 18 | * 19 | * Copyright 2001-2008 by Agner Fog. 20 | * GNU General Public License http://www.gnu.org/licenses/gpl.html 21 | *****************************************************************************/ 22 | 23 | #include // define time() 24 | #include "randomc.h" // define classes for random number generators 25 | #include "stocc.h" // define random library classes 26 | 27 | #ifndef MULTIFILE_PROJECT 28 | // If compiled as a single file then include these cpp files, 29 | // If compiled as a project then compile and link in these cpp files. 30 | #include "mersenne.cpp" // code for random number generator 31 | #include "stoc1.cpp" // random library source code 32 | #include "userintf.cpp" // define system specific user interface 33 | #endif 34 | 35 | 36 | int main() { 37 | int seed = (int)time(0); // random seed 38 | StochasticLib1 sto(seed); // make instance of random library 39 | int i; // loop counter 40 | double r; // random number 41 | int ir; // random integer number 42 | 43 | // make random numbers with uniform distribution 44 | printf("Random numbers with uniform distribution:\n"); 45 | for (i=0; i<16; i++) { 46 | ir = sto.IRandom(0, 20); 47 | printf("%8i ", ir); 48 | } 49 | 50 | // make random numbers with normal distribution 51 | printf("\n\nRandom numbers with normal distribution:\n"); 52 | for (i=0; i<16; i++) { 53 | r = sto.Normal(10, 4); 54 | printf("%8.5f ", r); 55 | } 56 | 57 | // make random numbers with poisson distribution 58 | printf("\n\nRandom numbers with poisson distribution:\n"); 59 | for (i=0; i<16; i++) { 60 | ir = sto.Poisson(10); 61 | printf("%8i ", ir); 62 | } 63 | 64 | // make random numbers with binomial distribution 65 | printf("\n\nRandom numbers with binomial distribution:\n"); 66 | for (i=0; i<16; i++) { 67 | ir = sto.Binomial(40, 0.25); 68 | printf("%8i ", ir); 69 | } 70 | 71 | // make random numbers with hypergeometric distribution 72 | printf("\n\nRandom numbers with hypergeometric distribution:\n"); 73 | for (i=0; i<16; i++) { 74 | ir = sto.Hypergeometric(20, 20, 40); 75 | printf("%8i ", ir); 76 | } 77 | 78 | EndOfProgram(); // system-specific exit code 79 | return 0; 80 | } 81 | -------------------------------------------------------------------------------- /External/stocc/ran-instructions.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/vbuchhold/routing-framework/c739dc8e81fef506a1bb8eb53ce930bfae5d8a36/External/stocc/ran-instructions.pdf -------------------------------------------------------------------------------- /External/stocc/sampmet.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/vbuchhold/routing-framework/c739dc8e81fef506a1bb8eb53ce930bfae5d8a36/External/stocc/sampmet.pdf -------------------------------------------------------------------------------- /External/stocc/wnchyppr.cpp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/vbuchhold/routing-framework/c739dc8e81fef506a1bb8eb53ce930bfae5d8a36/External/stocc/wnchyppr.cpp -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2020 Valentin Buchhold 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /Launchers/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | add_executable(AssignTraffic AssignTraffic.cc) 2 | target_compile_definitions(AssignTraffic PRIVATE CSV_IO_NO_THREAD) 3 | target_link_libraries(AssignTraffic ${RoutingKit_LIBRARY}) 4 | if(OpenMP_FOUND) 5 | target_link_libraries(AssignTraffic OpenMP::OpenMP_CXX) 6 | endif() 7 | 8 | option(TA_USE_CFW "Make each descent direction conjugate to the last direction." ON) 9 | option(TA_USE_SIMD_SEARCH "Use SIMD optimizations for the centralized shortest-path search." ON) 10 | set(TA_LOG_K "" CACHE STRING "Choose the number of simultaneous shortest-path computations.") 11 | 12 | if(NOT TA_USE_CFW) 13 | target_compile_definitions(AssignTraffic PRIVATE TA_NO_CFW) 14 | endif() 15 | if(NOT TA_USE_SIMD_SEARCH) 16 | target_compile_definitions(AssignTraffic PRIVATE TA_NO_SIMD_SEARCH) 17 | endif() 18 | if(NOT TA_LOG_K STREQUAL "") 19 | target_compile_definitions(AssignTraffic PRIVATE TA_LOG_K=${TA_LOG_K}) 20 | endif() 21 | 22 | add_executable( 23 | CalculateDemand CalculateDemand.cc 24 | ../External/randomc/mersenne.cpp ../External/randomc/userintf.cpp ../External/stocc/stoc1.cpp) 25 | target_compile_definitions(CalculateDemand PRIVATE CSV_IO_NO_THREAD) 26 | target_link_libraries(CalculateDemand ${PROJ_LIBRARY} ${RoutingKit_LIBRARY}) 27 | if(OpenMP_FOUND) 28 | target_link_libraries(CalculateDemand OpenMP::OpenMP_CXX) 29 | endif() 30 | 31 | set(DC_MAX_NUM_SOURCES "" CACHE STRING "Choose the number of sources to be substituted in FRAD.") 32 | if(NOT DC_MAX_NUM_SOURCES STREQUAL "") 33 | target_compile_definitions(CalculateDemand PRIVATE DC_MAX_NUM_SOURCES=${DC_MAX_NUM_SOURCES}) 34 | endif() 35 | 36 | add_executable(RunP2PAlgo RunP2PAlgo.cc) 37 | target_compile_definitions(RunP2PAlgo PRIVATE CSV_IO_NO_THREAD) 38 | target_link_libraries(RunP2PAlgo ${RoutingKit_LIBRARY}) 39 | if(OpenMP_FOUND) 40 | target_link_libraries(RunP2PAlgo OpenMP::OpenMP_CXX) 41 | endif() 42 | 43 | option(USE_FAST_ELIMINATION_TREE_QUERY "Use the fast elimination tree query." ON) 44 | if(NOT USE_FAST_ELIMINATION_TREE_QUERY) 45 | target_compile_definitions(RunP2PAlgo PRIVATE NO_FAST_ELIMINATION_TREE_QUERY) 46 | endif() 47 | 48 | add_executable(RunPoiAlgo RunPoiAlgo.cc) 49 | target_link_libraries(RunPoiAlgo ${RoutingKit_LIBRARY}) 50 | if(OpenMP_FOUND) 51 | target_link_libraries(RunPoiAlgo OpenMP::OpenMP_CXX) 52 | endif() 53 | -------------------------------------------------------------------------------- /Publications/FastTA/ALENEX18/ConductP2P: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | cd ${BASH_SOURCE%/*}/../../.. 3 | EXEC=Build/Release/Launchers/RunP2PAlgo 4 | INPUT_GRAPH=$1/Inputs/Graphs/DIMACS_eur.gr.bin 5 | ORDER=$1/Inputs/Orders/DIMACS_eur.nd30.ord.bin 6 | OD_DIR=$1/Inputs/ODPairs/P2P 7 | OUTPUT_DIR=$1/Experiments/FastTA/ALENEX18/P2P 8 | mkdir --parents $OUTPUT_DIR 9 | 10 | scons variant=Release RunP2PAlgo 11 | $EXEC -a CH -ch $1/Inputs/CH/DIMACS_eur.time.ch.bin -od $OD_DIR/DIMACS_eur.time.rank.csv -o $OUTPUT_DIR/LocalQueries_time_CH 12 | $EXEC -a CH -ch $1/Inputs/CH/DIMACS_eur.dist.ch.bin -od $OD_DIR/DIMACS_eur.dist.rank.csv -o $OUTPUT_DIR/LocalQueries_dist_CH 13 | 14 | $EXEC -a CCH-Dij -s -g $INPUT_GRAPH -ord $ORDER -od $OD_DIR/DIMACS_eur.time.rank.csv -o $OUTPUT_DIR/LocalQueries_time_CCHDij 15 | $EXEC -a CCH-Dij -s -g $INPUT_GRAPH -ord $ORDER -od $OD_DIR/DIMACS_eur.dist.rank.csv -o $OUTPUT_DIR/LocalQueries_dist_CCHDij -l 16 | 17 | $EXEC -a CCH-tree -g $INPUT_GRAPH -ord $ORDER -od $OD_DIR/DIMACS_eur.time.rank.csv -o $OUTPUT_DIR/LocalQueries_time_CCHTreeFast 18 | $EXEC -a CCH-tree -g $INPUT_GRAPH -ord $ORDER -od $OD_DIR/DIMACS_eur.dist.rank.csv -o $OUTPUT_DIR/LocalQueries_dist_CCHTreeFast -l 19 | 20 | scons variant=Release def=NO_FAST_ELIMINATION_TREE_QUERY RunP2PAlgo 21 | $EXEC -a CCH-tree -g $INPUT_GRAPH -ord $ORDER -od $OD_DIR/DIMACS_eur.time.rank.csv -o $OUTPUT_DIR/LocalQueries_time_CCHTree 22 | $EXEC -a CCH-tree -g $INPUT_GRAPH -ord $ORDER -od $OD_DIR/DIMACS_eur.dist.rank.csv -o $OUTPUT_DIR/LocalQueries_dist_CCHTree -l 23 | -------------------------------------------------------------------------------- /Publications/FastTA/ALENEX18/PrepareP2P: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | cd ${BASH_SOURCE%/*}/../../.. 3 | BUILD_DIR=Build/Release 4 | INPUT_GRAPH=$2/Inputs/Graphs/DIMACS_eur.gr.bin 5 | CH=$2/Inputs/CH/DIMACS_eur 6 | OD_DIR=$2/Inputs/ODPairs/P2P 7 | mkdir --parents ${INPUT_GRAPH%/*} 8 | mkdir --parents ${CH%/*} 9 | mkdir --parents $2/Inputs/Orders 10 | mkdir --parents $OD_DIR 11 | 12 | scons variant=Release 13 | $BUILD_DIR/RawData/ConvertGraph -s xatf -d binary -scc -a capacity free_flow_speed lat_lng length num_lanes travel_time xatf_road_category -i $1 -o ${INPUT_GRAPH%%.*} 14 | $BUILD_DIR/Launchers/RunP2PAlgo -a CH -g $INPUT_GRAPH -o $CH 15 | $BUILD_DIR/Launchers/RunP2PAlgo -a CH -g $INPUT_GRAPH -o $CH -l 16 | $BUILD_DIR/Launchers/RunP2PAlgo -a CCH -b 30 -g $INPUT_GRAPH -o $2/Inputs/Orders/DIMACS_eur 17 | 18 | $BUILD_DIR/RawData/GenerateODPairs -n 1000 -i $INPUT_GRAPH -o $OD_DIR/DIMACS_eur.time.rank -r {7..24} 19 | $BUILD_DIR/RawData/GenerateODPairs -n 1000 -i $INPUT_GRAPH -o $OD_DIR/DIMACS_eur.dist.rank -r {7..24} -len 20 | -------------------------------------------------------------------------------- /Publications/FastTA/ALENEX18/PrepareTA: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | cd ${BASH_SOURCE%/*}/../../.. 3 | BUILD_DIR=Build/Release/RawData 4 | INPUT_GRAPH=$3/Inputs/Graphs/Stuttgart.gr.bin 5 | OD_DIR=$3/Inputs/ODPairs/TA 6 | mkdir --parents ${INPUT_GRAPH%/*} 7 | mkdir --parents $OD_DIR 8 | 9 | scons variant=Release RawData 10 | $BUILD_DIR/ConvertGraph -s visum -d binary -scc -a capacity coordinate free_flow_speed lat_lng length num_lanes travel_time -i $1 -o ${INPUT_GRAPH%%.*} 11 | $BUILD_DIR/ParseMobiTopp -g $INPUT_GRAPH -v $1 -o $OD_DIR/Stuttgart 12 | 13 | $BUILD_DIR/ParseMobiTopp -ed Tue -et 07:00 -ld Tue -lt 07:15:00 -g $INPUT_GRAPH -vs $OD_DIR/Stuttgart.vs.bin -od $2 -o $OD_DIR/Stuttgart_Tue15m.tmp 14 | $BUILD_DIR/ParseMobiTopp -ed Tue -et 07:00 -ld Tue -lt 07:30:00 -g $INPUT_GRAPH -vs $OD_DIR/Stuttgart.vs.bin -od $2 -o $OD_DIR/Stuttgart_Tue30m.tmp 15 | $BUILD_DIR/ParseMobiTopp -ed Tue -et 07:00 -ld Tue -lt 09:00:00 -g $INPUT_GRAPH -vs $OD_DIR/Stuttgart.vs.bin -od $2 -o $OD_DIR/Stuttgart_Tue02h.tmp 16 | $BUILD_DIR/ParseMobiTopp -ed Tue -et 00:00 -ld Tue -lt 23:59:59 -g $INPUT_GRAPH -vs $OD_DIR/Stuttgart.vs.bin -od $2 -o $OD_DIR/Stuttgart_Tue24h.tmp 17 | $BUILD_DIR/ParseMobiTopp -ed Mon -et 00:00 -ld Sun -lt 23:59:59 -g $INPUT_GRAPH -vs $OD_DIR/Stuttgart.vs.bin -od $2 -o $OD_DIR/Stuttgart_MonSun.tmp 18 | 19 | $BUILD_DIR/ComputeDijkstraRanks -od $OD_DIR/Stuttgart_Tue15m.tmp.csv -g $INPUT_GRAPH -o $OD_DIR/Stuttgart_Tue15m 20 | $BUILD_DIR/ComputeDijkstraRanks -od $OD_DIR/Stuttgart_Tue30m.tmp.csv -g $INPUT_GRAPH -o $OD_DIR/Stuttgart_Tue30m 21 | $BUILD_DIR/ComputeDijkstraRanks -od $OD_DIR/Stuttgart_Tue02h.tmp.csv -g $INPUT_GRAPH -o $OD_DIR/Stuttgart_Tue02h 22 | $BUILD_DIR/ComputeDijkstraRanks -od $OD_DIR/Stuttgart_Tue24h.tmp.csv -g $INPUT_GRAPH -o $OD_DIR/Stuttgart_Tue24h 23 | $BUILD_DIR/ComputeDijkstraRanks -od $OD_DIR/Stuttgart_MonSun.tmp.csv -g $INPUT_GRAPH -o $OD_DIR/Stuttgart_MonSun 24 | rm $OD_DIR/*.tmp.csv 25 | -------------------------------------------------------------------------------- /Publications/FastTA/JEA/ConductP2P: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | cd ${BASH_SOURCE%/*}/../../.. 3 | 4 | binaryDir=Build/Release 5 | inputDir=$1/Inputs 6 | outputDir=$1/Experiments/FastTA/JEA 7 | 8 | mkdir --parents $outputDir/P2P 9 | 10 | cmake -D CMAKE_BUILD_TYPE=Release -S . -B $binaryDir 11 | cmake --build $binaryDir 12 | 13 | export LC_ALL=C 14 | export OMP_DYNAMIC=false 15 | export OMP_PROC_BIND=true 16 | export OMP_PLACES=cores 17 | 18 | for numCores in 1 2 4 8 12 16; do 19 | export OMP_NUM_THREADS=$numCores 20 | $binaryDir/Launchers/RunP2PAlgo -a CCH-custom -g $inputDir/Graphs/Visum_Stuttgart.gr.bin -s $inputDir/SepDecomps/Visum_Stuttgart_nd30.sep.bin -o $outputDir/P2P/Customization_Stuttgart_${numCores}cores 21 | $binaryDir/Launchers/RunP2PAlgo -a CCH-custom -g $inputDir/Graphs/DIMACS_eur.gr.bin -s $inputDir/SepDecomps/DIMACS_eur_nd30.sep.bin -o $outputDir/P2P/Customization_Europe_${numCores}cores 22 | done 23 | 24 | $binaryDir/Launchers/RunP2PAlgo -a CH -h $inputDir/CHs/DIMACS_eur_time.ch.bin -d $inputDir/ODPairs/P2P/DIMACS_eur_rank_time.csv -o $outputDir/P2P/LocalQueries_time_CH 25 | $binaryDir/Launchers/RunP2PAlgo -a CH -h $inputDir/CHs/DIMACS_eur_dist.ch.bin -d $inputDir/ODPairs/P2P/DIMACS_eur_rank_dist.csv -o $outputDir/P2P/LocalQueries_dist_CH 26 | 27 | $binaryDir/Launchers/RunP2PAlgo -a CCH-Dij -no-stall -g $inputDir/Graphs/DIMACS_eur.gr.bin -s $inputDir/SepDecomps/DIMACS_eur_nd30.sep.bin -d $inputDir/ODPairs/P2P/DIMACS_eur_rank_time.csv -o $outputDir/P2P/LocalQueries_time_CCHDij 28 | $binaryDir/Launchers/RunP2PAlgo -a CCH-Dij -no-stall -g $inputDir/Graphs/DIMACS_eur.gr.bin -s $inputDir/SepDecomps/DIMACS_eur_nd30.sep.bin -d $inputDir/ODPairs/P2P/DIMACS_eur_rank_dist.csv -o $outputDir/P2P/LocalQueries_dist_CCHDij -l 29 | 30 | cmake -D CMAKE_BUILD_TYPE=Release -D USE_FAST_ELIMINATION_TREE_QUERY=OFF -S . -B $binaryDir 31 | cmake --build $binaryDir --target RunP2PAlgo 32 | $binaryDir/Launchers/RunP2PAlgo -a CCH-tree -g $inputDir/Graphs/DIMACS_eur.gr.bin -s $inputDir/SepDecomps/DIMACS_eur_nd30.sep.bin -d $inputDir/ODPairs/P2P/DIMACS_eur_rank_time.csv -o $outputDir/P2P/LocalQueries_time_CCHTree 33 | $binaryDir/Launchers/RunP2PAlgo -a CCH-tree -g $inputDir/Graphs/DIMACS_eur.gr.bin -s $inputDir/SepDecomps/DIMACS_eur_nd30.sep.bin -d $inputDir/ODPairs/P2P/DIMACS_eur_rank_dist.csv -o $outputDir/P2P/LocalQueries_dist_CCHTree -l 34 | cmake -D CMAKE_BUILD_TYPE=Release -D USE_FAST_ELIMINATION_TREE_QUERY=ON -S . -B $binaryDir 35 | cmake --build $binaryDir --target RunP2PAlgo 36 | 37 | $binaryDir/Launchers/RunP2PAlgo -a CCH-tree -g $inputDir/Graphs/DIMACS_eur.gr.bin -s $inputDir/SepDecomps/DIMACS_eur_nd30.sep.bin -d $inputDir/ODPairs/P2P/DIMACS_eur_rank_time.csv -o $outputDir/P2P/LocalQueries_time_CCHTreeFast 38 | $binaryDir/Launchers/RunP2PAlgo -a CCH-tree -g $inputDir/Graphs/DIMACS_eur.gr.bin -s $inputDir/SepDecomps/DIMACS_eur_nd30.sep.bin -d $inputDir/ODPairs/P2P/DIMACS_eur_rank_dist.csv -o $outputDir/P2P/LocalQueries_dist_CCHTreeFast -l 39 | -------------------------------------------------------------------------------- /Publications/FastTA/JEA/DrawNetworks: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | cd ${BASH_SOURCE%/*}/../../.. 3 | 4 | binaryDir=Build/Release 5 | baseDir=$1 6 | outputDir=$2 7 | 8 | cmake -D CMAKE_BUILD_TYPE=Release -S . -B $binaryDir 9 | cmake --build $binaryDir 10 | 11 | export LC_ALL=C 12 | export OMP_DYNAMIC=false 13 | export OMP_PROC_BIND=true 14 | export OMP_PLACES=cores 15 | 16 | $binaryDir/RawData/DrawNetwork -stuttgart -w 6.5 -h 6.0 -g $baseDir/Inputs/Graphs/Visum_Stuttgart.gr.bin -o $outputDir/StuttgartRegion 17 | $binaryDir/RawData/DrawNetwork -stuttgart -w 6.5 -h 6.0 -g $baseDir/Inputs/Graphs/Visum_Stuttgart.gr.bin -o $outputDir/Stuttgart -c $baseDir/Inputs/RawData/Visum/Stuttgart/Stuttgart.poly 18 | $binaryDir/RawData/DrawNetwork -stuttgart -w 6.5 -h 6.0 -g $baseDir/Inputs/Graphs/Visum_Stuttgart.gr.bin -o $outputDir/Stuttgart_S-morn -c $baseDir/Inputs/RawData/Visum/Stuttgart/Stuttgart.poly -f $baseDir/Experiments/FastTA/JEA_/TA/FlowPatterns/S-morn.csv 19 | 20 | mv $outputDir/Stuttgart_S-morn.png $outputDir/Stuttgart_S-morn_1.png 21 | 22 | convert $outputDir/StuttgartRegion.png -alpha Remove $outputDir/StuttgartRegion.png 23 | convert $outputDir/Stuttgart.png -alpha Remove $outputDir/Stuttgart.png 24 | convert $outputDir/Stuttgart_S-morn_1.png -alpha Remove $outputDir/Stuttgart_S-morn_1.png 25 | convert $outputDir/Stuttgart_S-morn_2.png -alpha Remove $outputDir/Stuttgart_S-morn_2.png 26 | -------------------------------------------------------------------------------- /Publications/FastTA/JEA/PrepareP2P: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | cd ${BASH_SOURCE%/*}/../../.. 3 | 4 | binaryDir=Build/Release 5 | stuttgartData=$1 6 | londonData=$2 7 | xatfData=$3 8 | inputDir=$4/Inputs 9 | 10 | mkdir --parents $inputDir/CHs 11 | mkdir --parents $inputDir/Graphs 12 | mkdir --parents $inputDir/ODPairs/P2P 13 | mkdir --parents $inputDir/RawData/XATF_sorted 14 | mkdir --parents $inputDir/SepDecomps 15 | 16 | cmake -D CMAKE_BUILD_TYPE=Release -S . -B $binaryDir 17 | cmake --build $binaryDir 18 | 19 | export LC_ALL=C 20 | export OMP_DYNAMIC=false 21 | export OMP_PROC_BIND=true 22 | export OMP_PLACES=cores 23 | 24 | RawData/XatfMergeCountries.py -I $xatfData -O $inputDir/RawData/XATF_sorted -o eur 25 | $binaryDir/RawData/ConvertGraph -s xatf -d binary -scc -a capacity free_flow_speed lat_lng length num_lanes travel_time xatf_road_category -i $inputDir/RawData/XATF_sorted/eur/eur -o $inputDir/Graphs/DIMACS_eur 26 | 27 | $binaryDir/RawData/ConvertGraph -s visum -d binary -scc -ts P -cs 31467 -cp 1 -ap 10 -a capacity coordinate free_flow_speed lat_lng length num_lanes road_geometry travel_time -i $stuttgartData -o $inputDir/Graphs/Visum_Stuttgart 28 | $binaryDir/RawData/ConvertGraph -s visum -d binary -scc -ts C -cs 27700 -cp 1000 -ap 1 -a capacity coordinate free_flow_speed lat_lng length num_lanes road_geometry travel_time -i $londonData -o $inputDir/Graphs/Visum_London 29 | 30 | $binaryDir/Launchers/RunP2PAlgo -a CH -g $inputDir/Graphs/DIMACS_eur.gr.bin -o $inputDir/CHs/DIMACS_eur_time 31 | $binaryDir/Launchers/RunP2PAlgo -a CH -g $inputDir/Graphs/DIMACS_eur.gr.bin -o $inputDir/CHs/DIMACS_eur_dist -l 32 | 33 | $binaryDir/Launchers/RunP2PAlgo -a CCH -g $inputDir/Graphs/Visum_Stuttgart.gr.bin -o $inputDir/SepDecomps/Visum_Stuttgart_nd30 34 | $binaryDir/Launchers/RunP2PAlgo -a CCH -g $inputDir/Graphs/Visum_London.gr.bin -o $inputDir/SepDecomps/Visum_London_nd30 35 | $binaryDir/Launchers/RunP2PAlgo -a CCH -g $inputDir/Graphs/DIMACS_eur.gr.bin -o $inputDir/SepDecomps/DIMACS_eur_nd30 36 | 37 | $binaryDir/RawData/GenerateODPairs -n 1000 -r $(for exp in {6..24}; do echo $((2**exp)); done) -g $inputDir/Graphs/DIMACS_eur.gr.bin -o $inputDir/ODPairs/P2P/DIMACS_eur_rank_time 38 | $binaryDir/RawData/GenerateODPairs -n 1000 -r $(for exp in {6..24}; do echo $((2**exp)); done) -g $inputDir/Graphs/DIMACS_eur.gr.bin -o $inputDir/ODPairs/P2P/DIMACS_eur_rank_dist -l 39 | -------------------------------------------------------------------------------- /Publications/FastTA/JEA/PrepareTA: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | cd ${BASH_SOURCE%/*}/../../.. 3 | 4 | binaryDir=Build/Release 5 | stuttgartData=$1 6 | londonData=$2 7 | mobiToppData=$3 8 | inputDir=$4/Inputs 9 | 10 | mkdir --parents $inputDir/Graphs $inputDir/ODPairs/TA 11 | 12 | cmake -D CMAKE_BUILD_TYPE=Release -S . -B $binaryDir 13 | cmake --build $binaryDir 14 | 15 | export LC_ALL=C 16 | export OMP_DYNAMIC=false 17 | export OMP_PROC_BIND=true 18 | export OMP_PLACES=cores 19 | 20 | $binaryDir/RawData/ConvertGraph -s visum -d binary -scc -ts P -cs 31467 -cp 1 -ap 10 -a capacity coordinate free_flow_speed lat_lng length num_lanes road_geometry travel_time -i $stuttgartData -o $inputDir/Graphs/Visum_Stuttgart 21 | $binaryDir/RawData/ConvertGraph -s visum -d binary -scc -ts C -cs 27700 -cp 1000 -ap 1 -a capacity coordinate free_flow_speed lat_lng length num_lanes road_geometry travel_time -i $londonData -o $inputDir/Graphs/Visum_London 22 | 23 | $binaryDir/RawData/ComputeUnionBoundary -crs 31467 -val S -i $inputDir/RawData/Visum/Stuttgart -o $inputDir/RawData/Visum/Stuttgart/Stuttgart 24 | 25 | $binaryDir/RawData/ParseMobiToppFile -ed Tue -et 07:30:00 -ld Tue -lt 08:29:59 -g $inputDir/Graphs/Visum_Stuttgart.gr.bin -v $stuttgartData -m $mobiToppData -o $inputDir/ODPairs/TA/Visum_Stuttgart_morn 26 | $binaryDir/RawData/ParseMobiToppFile -ed Tue -et 16:30:00 -ld Tue -lt 17:29:59 -g $inputDir/Graphs/Visum_Stuttgart.gr.bin -v $stuttgartData -m $mobiToppData -o $inputDir/ODPairs/TA/Visum_Stuttgart_even 27 | $binaryDir/RawData/ParseMobiToppFile -ed Tue -et 00:00:00 -ld Tue -lt 23:59:59 -g $inputDir/Graphs/Visum_Stuttgart.gr.bin -v $stuttgartData -m $mobiToppData -o $inputDir/ODPairs/TA/Visum_Stuttgart_day 28 | $binaryDir/RawData/ParseMobiToppFile -ed Mon -et 00:00:00 -ld Sun -lt 23:59:59 -g $inputDir/Graphs/Visum_Stuttgart.gr.bin -v $stuttgartData -m $mobiToppData -o $inputDir/ODPairs/TA/Visum_Stuttgart_week 29 | 30 | $binaryDir/RawData/ParseMtxFile -p 1000 -col BOROUGH_NO -val $(seq 1.000 33) -g $inputDir/Graphs/Visum_London.gr.bin -v $londonData -m $londonData/ONE_5692_AM_ME2_C.mtx -o $inputDir/ODPairs/TA/Visum_London_peak 31 | -------------------------------------------------------------------------------- /Publications/FastTA/SEA18/ConductP2P: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | cd ${BASH_SOURCE%/*}/../../.. 3 | PROG=Build/Release/Launchers/RunP2PAlgo 4 | INPUT_GRAPH=$1/Inputs/Graphs/DIMACS_eur.gr.bin 5 | ORDER=$1/Inputs/Partitions/DIMACS_eur.nd30.ord.bin 6 | OD_DIR=$1/Inputs/ODPairs/P2P 7 | OUTPUT_DIR=$1/Experiments/FastTA/SEA18/P2P 8 | mkdir --parents $OUTPUT_DIR 9 | 10 | scons variant=Release RunP2PAlgo 11 | $PROG -a CH -ch $1/Inputs/CH/DIMACS_eur.time.ch.bin -od $OD_DIR/DIMACS_eur.time.rank.csv -o $OUTPUT_DIR/LocalQueries_time_CH 12 | $PROG -a CH -ch $1/Inputs/CH/DIMACS_eur.dist.ch.bin -od $OD_DIR/DIMACS_eur.dist.rank.csv -o $OUTPUT_DIR/LocalQueries_dist_CH 13 | 14 | $PROG -a CCH-Dij -s -g $INPUT_GRAPH -ord $ORDER -od $OD_DIR/DIMACS_eur.time.rank.csv -o $OUTPUT_DIR/LocalQueries_time_CCHDij 15 | $PROG -a CCH-Dij -s -g $INPUT_GRAPH -ord $ORDER -od $OD_DIR/DIMACS_eur.dist.rank.csv -o $OUTPUT_DIR/LocalQueries_dist_CCHDij -l 16 | 17 | $PROG -a CCH-tree -g $INPUT_GRAPH -ord $ORDER -od $OD_DIR/DIMACS_eur.time.rank.csv -o $OUTPUT_DIR/LocalQueries_time_CCHTreeFast 18 | $PROG -a CCH-tree -g $INPUT_GRAPH -ord $ORDER -od $OD_DIR/DIMACS_eur.dist.rank.csv -o $OUTPUT_DIR/LocalQueries_dist_CCHTreeFast -l 19 | 20 | scons variant=Release def=NO_FAST_ELIMINATION_TREE_QUERY RunP2PAlgo 21 | $PROG -a CCH-tree -g $INPUT_GRAPH -ord $ORDER -od $OD_DIR/DIMACS_eur.time.rank.csv -o $OUTPUT_DIR/LocalQueries_time_CCHTree 22 | $PROG -a CCH-tree -g $INPUT_GRAPH -ord $ORDER -od $OD_DIR/DIMACS_eur.dist.rank.csv -o $OUTPUT_DIR/LocalQueries_dist_CCHTree -l 23 | -------------------------------------------------------------------------------- /Publications/FastTA/SEA18/PrepareP2P: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | cd ${BASH_SOURCE%/*}/../../.. 3 | BUILD_DIR=Build/Release 4 | INPUT_GRAPH=$2/Inputs/Graphs/DIMACS_eur.gr.bin 5 | ORDER=$2/Inputs/Partitions/DIMACS_eur 6 | CH=$2/Inputs/CH/DIMACS_eur 7 | OD_DIR=$2/Inputs/ODPairs/P2P 8 | mkdir --parents ${INPUT_GRAPH%/*} 9 | mkdir --parents ${ORDER%/*} 10 | mkdir --parents ${CH%/*} 11 | mkdir --parents $OD_DIR 12 | 13 | scons variant=Release 14 | $BUILD_DIR/RawData/ConvertGraph -s xatf -d binary -scc -a capacity lat_lng length num_lanes travel_time xatf_road_category -i $1 -o ${INPUT_GRAPH%%.*} 15 | $BUILD_DIR/Launchers/RunP2PAlgo -a CH -g $INPUT_GRAPH -o $CH 16 | $BUILD_DIR/Launchers/RunP2PAlgo -a CH -g $INPUT_GRAPH -o $CH -l 17 | $BUILD_DIR/Launchers/RunP2PAlgo -a CCH -b 30 -g $INPUT_GRAPH -o $ORDER 18 | 19 | $BUILD_DIR/RawData/GenerateODPairs -n 1000 -i $INPUT_GRAPH -o $OD_DIR/DIMACS_eur.time.rank -r {7..24} 20 | $BUILD_DIR/RawData/GenerateODPairs -n 1000 -i $INPUT_GRAPH -o $OD_DIR/DIMACS_eur.dist.rank -r {7..24} -len 21 | -------------------------------------------------------------------------------- /Publications/FastTA/SEA18/PrepareTA: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | cd ${BASH_SOURCE%/*}/../../.. 3 | BUILD_DIR=Build/Release/RawData 4 | INPUT_GRAPH=$3/Inputs/Graphs/Visum_Stuttgart.gr.bin 5 | OD_DIR=$3/Inputs/ODPairs/TA 6 | mkdir --parents ${INPUT_GRAPH%/*} 7 | mkdir --parents $OD_DIR 8 | 9 | scons variant=Release RawData 10 | $BUILD_DIR/ConvertGraph -s visum -d binary -scc -a capacity coordinate free_flow_speed lat_lng length num_lanes travel_time vertex_id -i $1 -o ${INPUT_GRAPH%%.*} 11 | $BUILD_DIR/ParseMobiTopp -g $INPUT_GRAPH -v $1 -o $OD_DIR/Visum_Stuttgart 12 | 13 | $BUILD_DIR/ParseMobiTopp -ed Tue -et 07:00 -ld Tue -lt 07:30:00 -g $INPUT_GRAPH -vs $OD_DIR/Visum_Stuttgart.vs.bin -od $2 -o $OD_DIR/Visum_Stuttgart_Tue30m.tmp 14 | $BUILD_DIR/ParseMobiTopp -ed Tue -et 07:00 -ld Tue -lt 08:00:00 -g $INPUT_GRAPH -vs $OD_DIR/Visum_Stuttgart.vs.bin -od $2 -o $OD_DIR/Visum_Stuttgart_Tue01h.tmp 15 | $BUILD_DIR/ParseMobiTopp -ed Tue -et 07:00 -ld Tue -lt 09:00:00 -g $INPUT_GRAPH -vs $OD_DIR/Visum_Stuttgart.vs.bin -od $2 -o $OD_DIR/Visum_Stuttgart_Tue02h.tmp 16 | $BUILD_DIR/ParseMobiTopp -ed Tue -et 00:00 -ld Tue -lt 23:59:59 -g $INPUT_GRAPH -vs $OD_DIR/Visum_Stuttgart.vs.bin -od $2 -o $OD_DIR/Visum_Stuttgart_Tue24h.tmp 17 | $BUILD_DIR/ParseMobiTopp -ed Mon -et 00:00 -ld Sun -lt 23:59:59 -g $INPUT_GRAPH -vs $OD_DIR/Visum_Stuttgart.vs.bin -od $2 -o $OD_DIR/Visum_Stuttgart_MonSun.tmp 18 | 19 | $BUILD_DIR/ComputeDijkstraRanks -od $OD_DIR/Visum_Stuttgart_Tue30m.tmp.csv -g $INPUT_GRAPH -o $OD_DIR/Visum_Stuttgart_Tue30m 20 | $BUILD_DIR/ComputeDijkstraRanks -od $OD_DIR/Visum_Stuttgart_Tue01h.tmp.csv -g $INPUT_GRAPH -o $OD_DIR/Visum_Stuttgart_Tue01h 21 | $BUILD_DIR/ComputeDijkstraRanks -od $OD_DIR/Visum_Stuttgart_Tue02h.tmp.csv -g $INPUT_GRAPH -o $OD_DIR/Visum_Stuttgart_Tue02h 22 | $BUILD_DIR/ComputeDijkstraRanks -od $OD_DIR/Visum_Stuttgart_Tue24h.tmp.csv -g $INPUT_GRAPH -o $OD_DIR/Visum_Stuttgart_Tue24h 23 | $BUILD_DIR/ComputeDijkstraRanks -od $OD_DIR/Visum_Stuttgart_MonSun.tmp.csv -g $INPUT_GRAPH -o $OD_DIR/Visum_Stuttgart_MonSun 24 | rm $OD_DIR/*.tmp.csv 25 | -------------------------------------------------------------------------------- /Publications/NearestNeighbors/SEA21/RunExperiments: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | xatfData=$1 3 | europeanGrid=$2 4 | baseDir=$3 5 | 6 | inputDir=$baseDir/Inputs 7 | outputDir=$baseDir/Experiments/NearestNeighbors/SEA21 8 | 9 | sourceDir=${BASH_SOURCE%/*}/../../.. 10 | binaryDir=$sourceDir/Build/Release 11 | 12 | mkdir -p $inputDir/CHs $inputDir/Graphs $inputDir/RawData/XATF_sorted $inputDir/SepDecomps 13 | mkdir -p $outputDir/POIs $outputDir/TravelDemand 14 | 15 | cmake -D CMAKE_BUILD_TYPE=Release -S $sourceDir -B $binaryDir 16 | cmake --build $binaryDir 17 | 18 | export OMP_NUM_THREADS=1 19 | export OMP_DYNAMIC=false 20 | export OMP_PROC_BIND=true 21 | export OMP_PLACES=cores 22 | 23 | ####################################################### 24 | # Building the Graph, CH, and Separator Decomposition # 25 | ####################################################### 26 | 27 | $sourceDir/RawData/XatfMergeCountries.py -I $xatfData -O $inputDir/RawData/XATF_sorted -o eur 28 | $binaryDir/RawData/ConvertGraph -s xatf -d binary -scc -a capacity free_flow_speed lat_lng length num_lanes travel_time xatf_road_category -i $inputDir/RawData/XATF_sorted/eur/eur -o $inputDir/Graphs/DIMACS_eur 29 | 30 | $binaryDir/Launchers/RunP2PAlgo -a CH -g $inputDir/Graphs/DIMACS_eur.gr.bin -o $inputDir/CHs/DIMACS_eur_time 31 | $binaryDir/Launchers/RunP2PAlgo -a CCH -g $inputDir/Graphs/DIMACS_eur.gr.bin -o $inputDir/SepDecomps/DIMACS_eur_nd30 32 | 33 | ########################### 34 | # Closest-POI Experiments # 35 | ########################### 36 | 37 | ballSizes=$(for exp in {14..24}; do echo $((2**exp)); done) 38 | poiSetSizes=$(for exp in {2..18}; do echo $((2**exp)); done) 39 | 40 | for algo in Dij BCH BCCH CCH; do 41 | $binaryDir/Launchers/RunPoiAlgo -a $algo -b $((2**20)) -p $((2**12)) -k 1 4 8 -g $inputDir/Graphs/DIMACS_eur.gr.bin -h $inputDir/CHs/DIMACS_eur_time.ch.bin -d $inputDir/SepDecomps/DIMACS_eur_nd30.sep.bin -o $outputDir/POIs/b20_p12_$algo 42 | $binaryDir/Launchers/RunPoiAlgo -a $algo -b $((2**25)) -p $((2**14)) -k 1 4 8 -g $inputDir/Graphs/DIMACS_eur.gr.bin -h $inputDir/CHs/DIMACS_eur_time.ch.bin -d $inputDir/SepDecomps/DIMACS_eur_nd30.sep.bin -o $outputDir/POIs/b25_p14_$algo 43 | $binaryDir/Launchers/RunPoiAlgo -a $algo -b $ballSizes -p $((2**14)) -k 4 -g $inputDir/Graphs/DIMACS_eur.gr.bin -h $inputDir/CHs/DIMACS_eur_time.ch.bin -d $inputDir/SepDecomps/DIMACS_eur_nd30.sep.bin -o $outputDir/POIs/VaryingBallSize_$algo 44 | $binaryDir/Launchers/RunPoiAlgo -a $algo -b $((2**25)) -p $poiSetSizes -k 4 -g $inputDir/Graphs/DIMACS_eur.gr.bin -h $inputDir/CHs/DIMACS_eur_time.ch.bin -d $inputDir/SepDecomps/DIMACS_eur_nd30.sep.bin -o $outputDir/POIs/VaryingPOISetSize_$algo 45 | done 46 | 47 | ############################# 48 | # Travel Demand Experiments # 49 | ############################# 50 | 51 | for algo in Dij CCH kd-tree; do 52 | for ((i = 1; i <= 10; ++i)); do 53 | lambda=$(bc -l <<< "1 - 1/10^4 / $i^2") 54 | $binaryDir/Launchers/CalculateDemand -t -n 100000 -l $lambda -r 0 -f EU -m $algo -g $inputDir/Graphs/DIMACS_eur.gr.bin -pop $europeanGrid -sep $inputDir/SepDecomps/DIMACS_eur_nd30.sep.bin -o $outputDir/TravelDemand/${algo}_$(($i**2)).csv > $outputDir/TravelDemand/${algo}_$(($i**2)).log 55 | done 56 | done 57 | -------------------------------------------------------------------------------- /RawData/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | add_executable(CalibrateOsm CalibrateOsm.cc) 2 | target_link_libraries(CalibrateOsm ${RoutingKit_LIBRARY}) 3 | 4 | add_executable(ComputeDijkstraRanks ComputeDijkstraRanks.cc) 5 | target_compile_definitions(ComputeDijkstraRanks PRIVATE CSV_IO_NO_THREAD) 6 | 7 | add_executable(ComputeDistances ComputeDistances.cc) 8 | target_compile_definitions(ComputeDistances PRIVATE CSV_IO_NO_THREAD) 9 | 10 | add_executable(ComputeUnionBoundary ComputeUnionBoundary.cc) 11 | target_compile_definitions(ComputeUnionBoundary PRIVATE CSV_IO_NO_THREAD) 12 | target_link_libraries(ComputeUnionBoundary CGAL::CGAL ${PROJ_LIBRARY}) 13 | 14 | add_executable(ConvertGraph ConvertGraph.cc) 15 | target_compile_definitions(ConvertGraph PRIVATE CSV_IO_NO_THREAD) 16 | target_link_libraries(ConvertGraph ${PROJ_LIBRARY} ${RoutingKit_LIBRARY}) 17 | 18 | add_executable(DrawNetwork DrawNetwork.cc) 19 | target_compile_definitions(DrawNetwork PRIVATE CSV_IO_NO_THREAD) 20 | target_link_libraries(DrawNetwork ${cairo_LIBRARY}) 21 | 22 | add_executable(GenerateMatchingODPairs GenerateMatchingODPairs.cc) 23 | target_link_libraries(GenerateMatchingODPairs ${RoutingKit_LIBRARY}) 24 | 25 | add_executable(GenerateODPairs GenerateODPairs.cc) 26 | target_compile_definitions(GenerateODPairs PRIVATE CSV_IO_NO_THREAD) 27 | if(OpenMP_FOUND) 28 | target_link_libraries(GenerateODPairs OpenMP::OpenMP_CXX) 29 | endif() 30 | 31 | add_executable(MeanDistancePerRank MeanDistancePerRank.cc) 32 | target_compile_definitions(MeanDistancePerRank PRIVATE CSV_IO_NO_THREAD) 33 | target_link_libraries(MeanDistancePerRank ${PROJ_LIBRARY}) 34 | if(OpenMP_FOUND) 35 | target_link_libraries(MeanDistancePerRank OpenMP::OpenMP_CXX) 36 | endif() 37 | 38 | add_executable(ParseMobiToppFile ParseMobiToppFile.cc) 39 | target_compile_definitions(ParseMobiToppFile PRIVATE CSV_IO_NO_THREAD) 40 | 41 | add_executable(ParseMtxFile ParseMtxFile.cc) 42 | target_compile_definitions(ParseMtxFile PRIVATE CSV_IO_NO_THREAD) 43 | 44 | add_executable(RadiationModel RadiationModel.cc) 45 | target_compile_definitions(RadiationModel PRIVATE CSV_IO_NO_THREAD) 46 | target_link_libraries(RadiationModel ${PROJ_LIBRARY}) 47 | 48 | add_executable(VisumExtractPoi VisumExtractPoi.cc) 49 | target_compile_definitions(VisumExtractPoi PRIVATE CSV_IO_NO_THREAD) 50 | target_link_libraries(VisumExtractPoi ${PROJ_LIBRARY}) 51 | -------------------------------------------------------------------------------- /RawData/OsmComputeUnionOfBoundaries.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/python3 2 | 3 | import argparse 4 | import json 5 | import osmium 6 | from shapely import geometry 7 | from shapely import wkb 8 | from shapely.geometry import multipolygon 9 | 10 | def parseCommandLine(): 11 | ap = argparse.ArgumentParser( 12 | description='Extract the specified boundaries from an OSM file, compute their union, and ' 13 | 'output the largest component as a POLY file.') 14 | ap.add_argument('-c', '--coastline', type=argparse.FileType(), help="Compute the intersection of " 15 | "the union boundary and the specified coastline data.", metavar='GEOJSON-FILE') 16 | ap.add_argument('-o', '--output', default='-', type=argparse.FileType('w'), 17 | help="The name of the output file. Default is '-' (STDOUT).", metavar='FILE') 18 | ap.add_argument('osm_file', help='The name of the OSM file.', metavar='osm-file') 19 | ap.add_argument('boundary_id', nargs='+', type=int, 20 | help='The IDs of the boundaries that are to be joined.', metavar='boundary-id') 21 | return ap.parse_args() 22 | 23 | class BoundaryHandler(osmium.SimpleHandler): 24 | 25 | def __init__(self, boundaryIds): 26 | osmium.SimpleHandler.__init__(self) 27 | self.boundaryIds = boundaryIds 28 | self.union = None 29 | self.wkbFactory = osmium.geom.WKBFactory() 30 | 31 | def area(self, osmMultipolygon): 32 | if osmMultipolygon.id // 2 in self.boundaryIds: 33 | self.boundaryIds.remove(osmMultipolygon.id // 2) 34 | bin = self.wkbFactory.create_multipolygon(osmMultipolygon) 35 | multipolygon = wkb.loads(bin, True) 36 | if not multipolygon.is_valid: 37 | print('Invalid boundary: ' + osmMultipolygon.id // 2) 38 | elif self.union is None: 39 | self.union = multipolygon 40 | else: 41 | self.union = self.union.union(multipolygon) 42 | 43 | def readCoastlineDataFrom(file): 44 | coastlineData = [] 45 | for feature in json.load(file)['features']: 46 | coastlineData.append(geometry.shape(feature['geometry'])) 47 | return multipolygon.MultiPolygon(coastlineData) 48 | 49 | def getLargestComponent(boundary): 50 | if boundary.geom_type == 'Polygon': 51 | return geometry.Polygon(boundary.exterior) 52 | elif boundary.geom_type == 'MultiPolygon': 53 | largestComp = None 54 | largestCompArea = 0 55 | for comp in boundary: 56 | compWithoutHoles = geometry.Polygon(comp.exterior) 57 | if abs(compWithoutHoles.area) > largestCompArea: 58 | largestComp = compWithoutHoles 59 | largestCompArea = abs(compWithoutHoles.area) 60 | return largestComp 61 | else: 62 | print('Unknown type: ' + boundary.geom_type) 63 | 64 | def writePolyFile(polygon, file): 65 | print('(c) OpenStreetMap contributors', file=file) 66 | print('1', file=file) 67 | for vertex in polygon.exterior.coords: 68 | print('\t{lng:.7f}\t{lat:.7f}'.format(lng=vertex[0], lat=vertex[1]), file=file) 69 | print('END', file=file) 70 | print('END', file=file) 71 | 72 | def main(): 73 | args = parseCommandLine() 74 | handler = BoundaryHandler(set(args.boundary_id)) 75 | handler.apply_file(args.osm_file, True) 76 | if handler.boundaryIds: 77 | print('Missing boundaries:', end='') 78 | for id in handler.boundaryIds: 79 | print(' {}'.format(id), end='') 80 | print() 81 | boundary = handler.union 82 | 83 | if boundary is not None and args.coastline is not None: 84 | coastline = readCoastlineDataFrom(args.coastline) 85 | if coastline is not None: 86 | boundary = boundary.intersection(coastline) 87 | 88 | if boundary is not None: 89 | writePolyFile(getLargestComponent(boundary), args.output) 90 | 91 | if __name__ == '__main__': 92 | main() 93 | -------------------------------------------------------------------------------- /RawData/SimplifyOsmPolyFile.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | 3 | import argparse 4 | 5 | from shapely.geometry import MultiPolygon 6 | 7 | def parseCommandLine(): 8 | 'Parses the command line.' 9 | ap = argparse.ArgumentParser( 10 | description='This program reads an OSM POLY file from disk, simplifies the polygons and ' 11 | 'outputs the result as an OSM POLY file.') 12 | ap.add_argument('-t', '--tolerance', default=0.0, type=float, 13 | help='the maximum tolerance for the simplification algorithm', metavar='FLOAT') 14 | ap.add_argument('infile', type=argparse.FileType('rt'), help='the input POLY file') 15 | ap.add_argument('outfile', type=argparse.FileType('wt'), help='the output POLY file') 16 | args = ap.parse_args() 17 | return args 18 | 19 | def parseOsmPolyFile(infile): 20 | 'Reads the specified OSM POLY file from disk.' 21 | inPolygon = False 22 | coordinates = [] 23 | fileAndSectionNames = [] 24 | fileAndSectionNames.append(next(infile).strip()) 25 | for line in infile: 26 | line = line.strip() 27 | if not inPolygon and line == 'END': 28 | # End-of-file occurred. 29 | area = MultiPolygon(coordinates) 30 | assert area.is_valid 31 | return area, iter(fileAndSectionNames) 32 | elif not inPolygon: 33 | # Section header occurred. 34 | inPolygon = True 35 | fileAndSectionNames.append(line) 36 | if line[0] == '!': 37 | coordinates[-1][1].append([]) 38 | currentPolygon = coordinates[-1][1][-1] 39 | else: 40 | coordinates.append(([], [])) 41 | currentPolygon = coordinates[-1][0] 42 | elif inPolygon and line == 'END': 43 | # End-of-section occurred. 44 | inPolygon = False 45 | elif inPolygon: 46 | # Vertex record occurred. 47 | tokens = line.split() 48 | assert len(tokens) == 2 49 | currentPolygon.append((float(tokens[0]), float(tokens[1]))) 50 | assert False 51 | 52 | def writeClosedChainToOsmPolyFile(outfile, closedChain, name): 53 | 'Writes the specified closed polygonal chain to the given OSM POLY file.' 54 | print(name, file=outfile) 55 | if not closedChain is None: 56 | for vertex in closedChain.coords: 57 | print(' {lng:E} {lat:E}'.format(lng=vertex[0], lat=vertex[1]), file=outfile) 58 | print('END', file=outfile) 59 | 60 | def main(): 61 | args = parseCommandLine() 62 | area, fileAndSectionNames = parseOsmPolyFile(args.infile) 63 | simplifiedPolygons = [] 64 | for polygon in area: 65 | simplifiedPolygons.append(polygon.simplify(args.tolerance)) 66 | area = MultiPolygon(simplifiedPolygons) 67 | assert area.is_valid 68 | numVertices = 0 69 | print(next(fileAndSectionNames), file=args.outfile) 70 | for polygon in area: 71 | writeClosedChainToOsmPolyFile(args.outfile, polygon.exterior, next(fileAndSectionNames)) 72 | numVertices += len(polygon.exterior.coords) 73 | for hole in polygon.interiors: 74 | writeClosedChainToOsmPolyFile(args.outfile, hole, next(fileAndSectionNames)) 75 | numVertices += len(hole.coords) 76 | print('END', file=args.outfile) 77 | print('Number of Vertices:', numVertices) 78 | 79 | if __name__ == '__main__': 80 | main() 81 | -------------------------------------------------------------------------------- /RawData/VisumExtractPoi.cc: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | 9 | #include 10 | 11 | #include "DataStructures/Geometry/CoordinateTransformation.h" 12 | #include "Tools/CommandLine/CommandLineParser.h" 13 | #include "Tools/StringHelpers.h" 14 | 15 | inline void printUsage() { 16 | std::cout << 17 | "Usage: VisumExtractPoi -crs -i -o \n" 18 | "Extracts points of interest (e.g. schools and hospitals) from given Visum files.\n" 19 | " -crs coordinate reference system used in the Visum network files\n" 20 | " -i directory that contains the Visum network files\n" 21 | " -o place output in \n" 22 | " -help display this help and exit\n"; 23 | } 24 | 25 | int main(int argc, char* argv[]) { 26 | try { 27 | CommandLineParser clp(argc, argv); 28 | if (clp.isSet("help")) { 29 | printUsage(); 30 | return EXIT_SUCCESS; 31 | } 32 | 33 | const auto crs = clp.getValue("crs"); 34 | const auto visumPathName = clp.getValue("i"); 35 | auto outputFileName = clp.getValue("o"); 36 | if (!endsWith(outputFileName, ".csv")) 37 | outputFileName += ".csv"; 38 | 39 | CoordinateTransformation trans(crs, CoordinateTransformation::WGS_84); 40 | std::ofstream outputFile(outputFileName); 41 | if (!outputFile.good()) 42 | throw std::invalid_argument("file cannot be opened -- '" + outputFileName + "'"); 43 | outputFile << std::fixed; 44 | outputFile << "# Source: " << visumPathName << "\n"; 45 | outputFile << "category,longitude,latitude\n"; 46 | 47 | std::cout << "Reading POI categories..." << std::flush; 48 | std::map poiCategories; 49 | int id; 50 | char* name; 51 | using VisumFileReader = io::CSVReader<2, io::trim_chars<>, io::no_quote_escape<';'>>; 52 | VisumFileReader poiCatFileReader(visumPathName + "/POIKATEGORIE.csv"); 53 | poiCatFileReader.read_header(io::ignore_extra_column, "NR", "NAME"); 54 | while (poiCatFileReader.read_row(id, name)) { 55 | assert(*name != '\0'); 56 | assert(poiCategories.find(id) == poiCategories.end()); 57 | poiCategories[id] = name; 58 | } 59 | std::cout << " done.\n"; 60 | 61 | for (const auto& cat : poiCategories) { 62 | const auto poiFileName = visumPathName + "/POIOFCAT_" + std::to_string(cat.first) + ".csv"; 63 | std::ifstream poiFile(poiFileName); 64 | if (poiFile.good()) { 65 | std::cout << "Extracting POIs of category " << cat.second << "..." << std::flush; 66 | double easting, northing; 67 | double lng, lat; 68 | VisumFileReader poiFileReader(poiFileName, poiFile); 69 | poiFileReader.read_header(io::ignore_extra_column, "XKOORD", "YKOORD"); 70 | while (poiFileReader.read_row(easting, northing)) { 71 | trans.forward(easting, northing, lng, lat); 72 | outputFile << cat.second << ',' << lng << ',' << lat << '\n'; 73 | } 74 | std::cout << " done.\n"; 75 | } 76 | } 77 | } catch (std::exception& e) { 78 | std::cerr << argv[0] << ": " << e.what() << '\n'; 79 | std::cerr << "Try '" << argv[0] <<" -help' for more information.\n"; 80 | return EXIT_FAILURE; 81 | } 82 | return EXIT_SUCCESS; 83 | } 84 | -------------------------------------------------------------------------------- /RawData/VisumExtractTables.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | 3 | import argparse 4 | import os 5 | 6 | def parseCommandLine(): 7 | 'Parses the command line.' 8 | ap = argparse.ArgumentParser( 9 | description='This program reads a Visum NET file and stores its tables as single CSV files.') 10 | ap.add_argument('-o', '--output-directory', default='.', 11 | help='place the output CSV files in DIR', metavar='DIR') 12 | ap.add_argument('infile', type=argparse.FileType(encoding='latin-1'), 13 | help='the Visum network file (file extension: .net)') 14 | args = ap.parse_args() 15 | return args 16 | 17 | def main(): 18 | args = parseCommandLine() 19 | args.infile.readline() 20 | outfile = None 21 | for line in args.infile: 22 | if line[0] == '*': 23 | # Comment. Skip it. 24 | pass 25 | elif line[0] == '$': 26 | # Begin of a new table. Open a new output file. 27 | name, columns = tuple(line.split(':')) 28 | print('Writing', name[1:] + '.csv...', end='', flush=True) 29 | outfile = open(os.path.join(args.output_directory, name[1:] + '.csv'), 'w') 30 | outfile.write(columns) 31 | elif not line.strip(): 32 | # End of the current table. Close the current output file. 33 | outfile.close() 34 | print(' done.') 35 | else: 36 | # Normal record line. Write it to the current output file. 37 | outfile.write(line) 38 | 39 | if __name__ == '__main__': 40 | main() 41 | -------------------------------------------------------------------------------- /Stats/TrafficAssignment/AllOrNothingAssignmentStats.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | #include 5 | 6 | // Statistics about an iterative all-or-nothing assignment, including checksums and running times. 7 | struct AllOrNothingAssignmentStats { 8 | // Constructs a struct collecting statistics about an iterative all-or-nothing assignment. 9 | AllOrNothingAssignmentStats(const int numODPairs) 10 | : lastChecksum(0), 11 | totalChecksum(0), 12 | prevMinPathCost(0), 13 | lastDistances(numODPairs, -1), 14 | avgChangeInDistances(0), 15 | maxChangeInDistances(0), 16 | lastCustomizationTime(0), 17 | lastQueryTime(0), 18 | lastRoutingTime(0), 19 | totalPreprocessingTime(0), 20 | totalCustomizationTime(0), 21 | totalQueryTime(0), 22 | totalRoutingTime(0), 23 | numIterations(0) {} 24 | 25 | // Resets the values from the last iteration. 26 | void startIteration() { 27 | lastChecksum = 0; 28 | prevMinPathCost = 0; 29 | avgChangeInDistances = 0; 30 | maxChangeInDistances = 0; 31 | } 32 | 33 | // Adds the values from the last iteration to the totals. 34 | void finishIteration() { 35 | lastRoutingTime = lastCustomizationTime + lastQueryTime; 36 | totalChecksum += lastChecksum; 37 | totalCustomizationTime += lastCustomizationTime; 38 | totalQueryTime += lastQueryTime; 39 | totalRoutingTime += lastRoutingTime; 40 | } 41 | 42 | int64_t lastChecksum; // The sum of the distances computed in the last iteration. 43 | int64_t totalChecksum; // The total sum of distances computed. 44 | int64_t prevMinPathCost; // The sum of distances between OD pairs sampled in previous iteration. 45 | 46 | std::vector lastDistances; // The OD distances from the last iteration. 47 | double avgChangeInDistances; // The avg change in OD distances between last two iterations. 48 | double maxChangeInDistances; // The max change in OD distances between last two iterations. 49 | 50 | int lastCustomizationTime; // The time spent on customization in the last iteration. 51 | int lastQueryTime; // The time spent on queries in the last iteration. 52 | int lastRoutingTime; // The time spent on routing in the last iteration. 53 | 54 | int totalPreprocessingTime; // The total time spent on preprocessing. 55 | int totalCustomizationTime; // The total time spent on customization. 56 | int totalQueryTime; // The total time spent on queries. 57 | int totalRoutingTime; // The total time spent on routing. 58 | 59 | int numIterations; // The number of iterations performed. 60 | }; 61 | -------------------------------------------------------------------------------- /Stats/TrafficAssignment/FrankWolfeAssignmentStats.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | 5 | // Statistics about a Frank-Wolfe assignment, including times and measures of solution quality. 6 | struct FrankWolfeAssignmentStats { 7 | // Constructs a struct collecting statistics about a Frank-Wolfe assignment. 8 | FrankWolfeAssignmentStats() 9 | : prevTotalTraversalCost(0), 10 | prevTotalPathCost(0), 11 | prevRelGap(std::numeric_limits::infinity()), 12 | lastLineSearchTime(0), 13 | lastRunningTime(0), 14 | totalLineSearchTime(0), 15 | totalRunningTime(0) {} 16 | 17 | // Resets the values from the last iteration. 18 | void startIteration() { 19 | prevTotalTraversalCost = 0; 20 | prevTotalPathCost = 0; 21 | } 22 | 23 | // Adds the values from the last iteration to the totals. 24 | void finishIteration() { 25 | totalLineSearchTime += lastLineSearchTime; 26 | totalRunningTime += lastRunningTime; 27 | } 28 | 29 | double prevTotalTraversalCost; // The total traversal cost after the previous iteration. 30 | double prevTotalPathCost; // The total path cost after the previous iteration. 31 | double prevRelGap; // The relative gap after the previous iteration. 32 | 33 | int lastLineSearchTime; // The time spent on the line search in the last iteration. 34 | int lastRunningTime; // The running time for the last iteration. 35 | 36 | int totalLineSearchTime; // The total time spent on the line search. 37 | int totalRunningTime; // The total running time. 38 | }; 39 | -------------------------------------------------------------------------------- /Tools/Bitwise.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | #include 5 | #include 6 | 7 | namespace bitwise { 8 | 9 | // We add an overloaded version of __builtin_clz. 10 | inline int builtin_clz(const unsigned int x) { return __builtin_clz(x); } 11 | inline int builtin_clz(const unsigned long x) { return __builtin_clzl(x); } 12 | inline int builtin_clz(const unsigned long long x) { return __builtin_clzll(x); } 13 | 14 | // We add an overloaded version of __builtin_ctz. 15 | inline int builtin_ctz(const unsigned int x) { return __builtin_ctz(x); } 16 | inline int builtin_ctz(const unsigned long x) { return __builtin_ctzl(x); } 17 | inline int builtin_ctz(const unsigned long long x) { return __builtin_ctzll(x); } 18 | 19 | } 20 | 21 | // Returns the bit with the specified index in val. 22 | template 23 | inline bool getBit(const UIntT val, const int bitIndex) { 24 | assert(bitIndex >= 0); assert(bitIndex < std::numeric_limits::digits); 25 | return (val >> bitIndex) & 1; 26 | } 27 | 28 | // Sets the bit with the specified index in val to bitValue. 29 | template 30 | inline void setBit(UIntT& val, const int bitIndex, const bool bitValue = true) { 31 | assert(bitIndex >= 0); assert(bitIndex < std::numeric_limits::digits); 32 | val ^= (-bitValue ^ val) & (UIntT{1} << bitIndex); 33 | } 34 | 35 | // Returns the number of zero-bits preceding the highest-order one-bit in val. 36 | template 37 | inline int numLeadingZeros(const UIntT val) { 38 | // A good compiler will generate a single LZCNT instruction for the following. 39 | if (val == 0) return std::numeric_limits::digits; 40 | return bitwise::builtin_clz(val); 41 | } 42 | 43 | // Returns the number of zero-bits following the lowest-order one-bit in val. 44 | template 45 | inline int numTrailingZeros(const UIntT val) { 46 | // A good compiler will generate a single TZCNT instruction for the following. 47 | if (val == 0) return std::numeric_limits::digits; 48 | return bitwise::builtin_ctz(val); 49 | } 50 | 51 | // Returns the number of one-bits in the value representation of val. 52 | template 53 | inline int bitCount(const UIntT val) { 54 | // A good compiler will generate a single POPCNT instruction for the following. 55 | return std::bitset::digits>(val).count(); 56 | } 57 | 58 | // Returns the number of one-bits in val that occur before the specified index. 59 | template 60 | inline int bitCountBeforeIndex(const UIntT val, const int bitIndex) { 61 | assert(bitIndex >= 0); assert(bitIndex < std::numeric_limits::digits); 62 | return bitCount(val & ((UIntT{1} << bitIndex) - 1)); 63 | } 64 | 65 | // Returns the index of the highest-order one-bit in val, or -1 if val is zero. 66 | template 67 | inline int highestOneBit(const UIntT val) { 68 | return std::numeric_limits::digits - numLeadingZeros(val) - 1; 69 | } 70 | 71 | // Returns the index of the lowest-order one-bit in val, or -1 if val is zero. 72 | template 73 | inline int lowestOneBit(const UIntT val) { 74 | if (val == 0) return -1; 75 | return numTrailingZeros(val); 76 | } 77 | 78 | // Returns the index of the highest-order differing bit, or -1 if x and y are equal. 79 | template 80 | inline int highestDifferingBit(const UIntT x, const UIntT y) { 81 | return highestOneBit(x ^ y); 82 | } 83 | -------------------------------------------------------------------------------- /Tools/CommandLine/CommandLineParser.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | #include 5 | #include 6 | #include 7 | 8 | #include "Tools/LexicalCast.h" 9 | 10 | // A simple tool for obtaining command line options. 11 | class CommandLineParser { 12 | public: 13 | // Constructs an uninitialized command line parser. 14 | CommandLineParser() = default; 15 | 16 | // Constructs a command line parser and parses the command line. 17 | CommandLineParser(int argc, char* argv[]) { 18 | parse(argc, argv); 19 | } 20 | 21 | // Parses the command line. 22 | void parse(int argc, char* argv[]) { 23 | for (int i = 1; i < argc; ++i) { 24 | // Check if the current token is an option name. 25 | if (argv[i][0] != '-') 26 | throw std::invalid_argument("missing option name before '" + std::string(argv[i]) + "'"); 27 | 28 | // The current option's name. 29 | std::string nm(&argv[i][1]); 30 | 31 | // Fetch the current option's value(s). 32 | options.erase(nm); 33 | for (; i + 1 < argc && argv[i + 1][0] != '-'; ++i) 34 | options.emplace(nm, argv[i + 1]); 35 | 36 | if (options.count(nm) == 0) 37 | options.emplace(nm, ""); 38 | } 39 | } 40 | 41 | // Returns true if the specified option is set on the command line. 42 | bool isSet(const std::string& nm) const { 43 | return options.count(nm) > 0; 44 | } 45 | 46 | // Returns the (first) value of the specified option, or dflt if the option is not set. 47 | template 48 | T getValue(const std::string& nm, const T& dflt = T()) const { 49 | return isSet(nm) ? lexicalCast(options.lower_bound(nm)->second) : dflt; 50 | } 51 | 52 | // Returns a vector of all values of the specified option. 53 | template 54 | std::vector getValues(const std::string& nm) const { 55 | std::vector values; 56 | for (auto iter = options.lower_bound(nm); iter != options.upper_bound(nm); ++iter) 57 | values.push_back(lexicalCast(iter->second)); 58 | return values; 59 | } 60 | 61 | private: 62 | std::multimap options; // The command line options as name/value pairs. 63 | }; 64 | -------------------------------------------------------------------------------- /Tools/CommandLine/ProgressBar.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | #include 5 | #include 6 | #include 7 | 8 | #include 9 | 10 | // A textual indicator of progress towards some goal. 11 | class ProgressBar { 12 | public: 13 | // Constructs an uninitialized progress bar. 14 | explicit ProgressBar(bool verbose = true, std::ostream& os = std::cout) 15 | : os(os), numSteps(0), stepsDone(0), percentageDone(0), 16 | percentageOutputInterval(20), dotOutputInterval(5), verbose(verbose) {} 17 | 18 | // Constructs a progress bar with the specified number of steps. 19 | template 20 | explicit ProgressBar(ArithmeticT numSteps, bool verbose = true, std::ostream& os = std::cout) 21 | : ProgressBar(verbose, os) { 22 | init(numSteps); 23 | } 24 | 25 | // Initialize the progress bar with the specified number of steps. 26 | void init(const int64_t steps) { 27 | assert(steps >= 0); 28 | numSteps = steps; 29 | stepsDone = 0; 30 | percentageDone = 0; 31 | if (verbose) 32 | os << "0% " << std::flush; 33 | } 34 | 35 | // Set the percentage points between two printed percentages. 36 | void setPercentageOutputInterval(const int points) { 37 | percentageOutputInterval = points; 38 | } 39 | 40 | // Set the percentage points between two printed dots. 41 | void setDotOutputInterval(const int points) { 42 | dotOutputInterval = points; 43 | } 44 | 45 | // Advances the progress bar to the specified step. 46 | void advanceTo(const int64_t step) { 47 | if (!verbose) 48 | return; 49 | assert(step >= stepsDone); assert(step <= numSteps); 50 | stepsDone = step; 51 | print(stepsDone * 100 / numSteps); 52 | } 53 | 54 | // Advances the progress bar to 100 %. 55 | void finish() { 56 | advanceTo(numSteps); 57 | } 58 | 59 | // Advances the progress bar by one step. 60 | void operator++() { 61 | if (!verbose) 62 | return; 63 | int64_t done; 64 | #pragma omp atomic capture 65 | done = ++stepsDone; 66 | #ifdef _OPENMP 67 | if (omp_get_thread_num() == 0) 68 | #endif 69 | print(done * 100 / numSteps); 70 | } 71 | 72 | // Advances the progress bar by the specified number of steps. 73 | void operator+=(const int64_t steps) { 74 | assert(steps >= 0); 75 | if (!verbose) 76 | return; 77 | int64_t done; 78 | #pragma omp atomic capture 79 | done = stepsDone += steps; 80 | #ifdef _OPENMP 81 | if (omp_get_thread_num() == 0) 82 | #endif 83 | print(done * 100 / numSteps); 84 | } 85 | 86 | private: 87 | // Prints the progress bar until the specified percentage. 88 | void print(const int until) { 89 | assert(until <= 100); 90 | for (int i = percentageDone + 1; i <= until; ++i) 91 | if (i % percentageOutputInterval == 0) 92 | os << " " << i << "% " << std::flush; 93 | else if (i % dotOutputInterval == 0) 94 | os << "." << std::flush; 95 | percentageDone = until; 96 | } 97 | 98 | std::ostream& os; // The output stream the progress bar is printed to. 99 | 100 | int64_t numSteps; // The number of steps that have to be done. 101 | int64_t stepsDone; // The number of steps that have already been done. 102 | int percentageDone; // The percentage that has already been done. 103 | 104 | int percentageOutputInterval; // Percentage points between two printed percentages. 105 | int dotOutputInterval; // Percentage points between two printed dots. 106 | bool verbose; // Indicates if the progress bar should be printed. 107 | }; 108 | -------------------------------------------------------------------------------- /Tools/CompilerSpecific.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | // Hints to the compiler that the specified condition is expected to be true. 4 | #ifdef __GNUC__ // GNU compiler. 5 | # define LIKELY(cond) __builtin_expect(!!(cond), 1) 6 | #endif 7 | #ifndef LIKELY // Default definition. 8 | # define LIKELY(cond) (cond) 9 | #endif 10 | 11 | // Hints to the compiler that the specified condition is expected to be false. 12 | #ifdef __GNUC__ // GNU compiler. 13 | # define UNLIKELY(cond) __builtin_expect(!!(cond), 0) 14 | #endif 15 | #ifndef UNLIKELY // Default definition. 16 | # define UNLIKELY(cond) (cond) 17 | #endif 18 | 19 | // The weakest alignment a type shall have for use with SIMD instructions. 20 | #if defined __AVX2__ 21 | constexpr int MIN_ALIGNMENT = 32; 22 | #elif defined __SSE4_2__ 23 | constexpr int MIN_ALIGNMENT = 16; 24 | #else 25 | constexpr int MIN_ALIGNMENT = 1; 26 | #endif 27 | -------------------------------------------------------------------------------- /Tools/ConcurrentHelpers.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | // Atomically replaces the value of the first argument with the smaller of two values. 4 | template 5 | inline void atomicFetchMin(T& a, const T& b) { 6 | T expect = a; 7 | while (b < expect && 8 | !__atomic_compare_exchange_n(&a, &expect, b, true, __ATOMIC_RELAXED, __ATOMIC_RELAXED)) {} 9 | } 10 | -------------------------------------------------------------------------------- /Tools/Constants.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | 5 | // A special value representing infinity. 6 | constexpr int INFTY = std::numeric_limits::max() / 2; 7 | 8 | // Special values representing an invalid (vertex/edge) ID. 9 | constexpr int INVALID_ID = -1; 10 | constexpr int INVALID_INDEX = -1; 11 | constexpr int INVALID_VERTEX = -1; 12 | constexpr int INVALID_EDGE = -1; 13 | 14 | // This enum provides constants to specify the direction in which a road segment is open. 15 | enum class RoadDirection { OPEN_IN_BOTH, FORWARD, REVERSE, CLOSED }; 16 | 17 | // This enum provides constants to specify the direction of a search. 18 | enum class SearchDirection { FORWARD, REVERSE }; 19 | 20 | // The earth's mean radius in meters. 21 | constexpr int EARTH_RADIUS = 6371000; 22 | 23 | // The maximum number of shortest paths computed simultaneously during traffic assignment. 24 | #ifndef TA_LOG_K 25 | # define TA_LOG_K 5 26 | #endif 27 | 28 | // The maximum number of source vertices that are to be substituted into radiation model's formula. 29 | #ifndef DC_MAX_NUM_SOURCES 30 | # define DC_MAX_NUM_SOURCES std::numeric_limits::max() 31 | #endif 32 | -------------------------------------------------------------------------------- /Tools/ContainerHelpers.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | 5 | // Returns true if the specified sequence container contains the specified element. 6 | template 7 | inline bool contains(InputIteratorT first, InputIteratorT last, const T& val) { 8 | return std::find(first, last, val) != last; 9 | } 10 | -------------------------------------------------------------------------------- /Tools/DateHelpers.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | #include 5 | #include 6 | 7 | #include "Tools/LexicalCast.h" 8 | #include "Tools/StringHelpers.h" 9 | 10 | // A day-of-week, such as 'Tuesday'. 11 | enum class DayOfWeek { 12 | MONDAY = 1, 13 | TUESDAY = 2, 14 | WEDNESDAY = 3, 15 | THURSDAY = 4, 16 | FRIDAY = 5, 17 | SATURDAY = 6, 18 | SUNDAY = 7, 19 | }; 20 | 21 | // Obtains the seconds since midnight from a text string such as 10:15:30. 22 | template 23 | inline int parseTime(StringT& text) { 24 | const int len = str::length(text); 25 | if ((len == 5 || (len == 8 && text[5] == ':')) && text[2] == ':') { 26 | text[2] = '\0'; 27 | text[5] = '\0'; 28 | const int hrs = lexicalCast(str::cStr(text)); 29 | const int min = lexicalCast(str::cStr(text) + 3); 30 | const int sec = len == 8 ? lexicalCast(str::cStr(text) + 6) : 0; 31 | if (0 <= hrs && hrs < 24 && 0 <= min && min < 60 && 0 <= sec && sec < 60) { 32 | return hrs * 60 * 60 + min * 60 + sec; 33 | } else { 34 | text[2] = ':'; 35 | if (len == 8) 36 | text[5] = ':'; 37 | } 38 | } 39 | throw std::invalid_argument("text string not in format HH:mm:ss -- '" + std::string(text) + "'"); 40 | } 41 | 42 | // Obtains an instance of DayOfWeek from a text string such as 'Tue'. 43 | template 44 | inline DayOfWeek parseDayOfWeek(const StringT& text) { 45 | const char* const dayOfWeek = str::cStr(text); 46 | if (!std::strcmp(dayOfWeek, "Monday") || !std::strcmp(dayOfWeek, "Mon") || 47 | !std::strcmp(dayOfWeek, "Montag") || !std::strcmp(dayOfWeek, "Mo")) 48 | return DayOfWeek::MONDAY; 49 | else if (!std::strcmp(dayOfWeek, "Tuesday") || !std::strcmp(dayOfWeek, "Tue") || 50 | !std::strcmp(dayOfWeek, "Dienstag") || !std::strcmp(dayOfWeek, "Di")) 51 | return DayOfWeek::TUESDAY; 52 | else if (!std::strcmp(dayOfWeek, "Wednesday") || !std::strcmp(dayOfWeek, "Wed") || 53 | !std::strcmp(dayOfWeek, "Mittwoch") || !std::strcmp(dayOfWeek, "Mi")) 54 | return DayOfWeek::WEDNESDAY; 55 | else if (!std::strcmp(dayOfWeek, "Thursday") || !std::strcmp(dayOfWeek, "Thu") || 56 | !std::strcmp(dayOfWeek, "Donnerstag") || !std::strcmp(dayOfWeek, "Do")) 57 | return DayOfWeek::THURSDAY; 58 | else if (!std::strcmp(dayOfWeek, "Friday") || !std::strcmp(dayOfWeek, "Fri") || 59 | !std::strcmp(dayOfWeek, "Freitag") || !std::strcmp(dayOfWeek, "Fr")) 60 | return DayOfWeek::FRIDAY; 61 | else if (!std::strcmp(dayOfWeek, "Saturday") || !std::strcmp(dayOfWeek, "Sat") || 62 | !std::strcmp(dayOfWeek, "Samstag") || !std::strcmp(dayOfWeek, "Sa")) 63 | return DayOfWeek::SATURDAY; 64 | else if (!std::strcmp(dayOfWeek, "Sunday") || !std::strcmp(dayOfWeek, "Sun") || 65 | !std::strcmp(dayOfWeek, "Sonntag") || !std::strcmp(dayOfWeek, "So")) 66 | return DayOfWeek::SUNDAY; 67 | throw std::invalid_argument("invalid day of week -- '" + std::string(text) + "'"); 68 | } 69 | 70 | // Obtains the seconds since Monday midnight from two text strings such as 'Tue' and 10:15:30. 71 | template 72 | inline int secondsSinceMonMidnight(const StringT1& dayOfWeek, StringT2& time) { 73 | return (static_cast(parseDayOfWeek(dayOfWeek)) - 1) * 24 * 60 * 60 + parseTime(time); 74 | } 75 | -------------------------------------------------------------------------------- /Tools/EnumParser.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | #include 5 | #include 6 | #include 7 | 8 | // A facility for translating strings into enum values. Enums must specialize initNameToEnumMap. 9 | template 10 | class EnumParser { 11 | public: 12 | // Constructs and initializes an enum parser. 13 | EnumParser() { 14 | initNameToEnumMap(); 15 | } 16 | 17 | // Fills the map with name/value pairs. Enumerations must specialize this member function. 18 | void initNameToEnumMap() { 19 | assert(false); 20 | } 21 | 22 | // Returns the enum value with the specified name. 23 | T operator()(const std::string& name) const { 24 | const auto iter = nameToEnum.find(name); 25 | if (iter == nameToEnum.end()) 26 | throw std::invalid_argument("no enum value with the specified name -- '" + name + "'"); 27 | return iter->second; 28 | } 29 | 30 | private: 31 | std::unordered_map nameToEnum; // A map to translate strings into enum values. 32 | }; 33 | -------------------------------------------------------------------------------- /Tools/LexicalCast.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | #include 5 | #include 6 | 7 | #include 8 | 9 | #include "Tools/StringHelpers.h" 10 | 11 | // Converts the specified string to type T. 12 | template ::value>> 13 | inline T lexicalCast(const StringT& string) { 14 | try { 15 | T val; 16 | io::detail::parse(const_cast(str::cStr(string)), val); 17 | return val; 18 | } catch (io::error::invalid_single_character& e) { 19 | const auto what = "'" + std::string(string) + "' is not a single character"; 20 | throw std::invalid_argument(what); 21 | } catch (io::error::no_digit& e) { 22 | const auto what = "'" + std::string(string) + "' cannot be converted to an arithmetic type"; 23 | throw std::invalid_argument(what); 24 | } catch (io::error::integer_overflow& e) { 25 | const auto what = "'" + std::string(string) + "' is outside the range of representable values"; 26 | throw std::out_of_range(what); 27 | } catch (io::error::integer_underflow& e) { 28 | const auto what = "'" + std::string(string) + "' is outside the range of representable values"; 29 | throw std::out_of_range(what); 30 | } 31 | } 32 | 33 | // Converts the specified string to the specified enum type. 34 | template 35 | inline std::enable_if_t::value, EnumT> lexicalCast(const StringT& string) { 36 | return static_cast(lexicalCast>(string)); 37 | } 38 | -------------------------------------------------------------------------------- /Tools/Logging/LogManager.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | #include 5 | #include 6 | 7 | #include "Tools/Logging/NullLogger.h" 8 | 9 | // This class manages a set of named loggers. The logger type should be std::basic_ofstream or 10 | // NullLogger. In the former case, each logger writes to a file whose name is the concatenation of a 11 | // common base file name with the name of the logger. In the latter case, each logger discards the 12 | // data written to it, avoiding any overhead at runtime. When a logger is requested, we return a 13 | // reference to it if it already exists. Otherwise, the logger is newly constructed, an optional 14 | // header line is written to it, and a reference to it is returned. 15 | template 16 | class LogManager { 17 | public: 18 | LogManager() = delete; 19 | 20 | static LoggerT& getLogger(const std::string& name, const std::string& header = "") { 21 | auto iter = loggers.find(name); 22 | if (iter == loggers.end()) { 23 | iter = loggers.emplace(name, LoggerT(baseFileName + name)).first; 24 | assert(iter->second); 25 | iter->second << header; 26 | } 27 | return iter->second; 28 | } 29 | 30 | static void setBaseFileName(const std::string& fileName) { 31 | baseFileName = fileName; 32 | } 33 | 34 | private: 35 | inline static std::unordered_map loggers; 36 | inline static std::string baseFileName; 37 | }; 38 | -------------------------------------------------------------------------------- /Tools/Logging/NullLogger.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | // A logger that discards the data written to it, avoiding any overhead at runtime. 4 | class NullLogger { 5 | public: 6 | template 7 | explicit NullLogger(const T&) noexcept {} 8 | 9 | explicit operator bool() const noexcept { 10 | return true; 11 | } 12 | 13 | template 14 | NullLogger& operator<<(const T&) noexcept { 15 | return *this; 16 | } 17 | }; 18 | -------------------------------------------------------------------------------- /Tools/MachineSpecs.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | // The size of a cache line in bytes. 4 | static constexpr int CACHE_LINE_SIZE = 64; 5 | -------------------------------------------------------------------------------- /Tools/Math.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | #include 5 | 6 | #include "Tools/Bitwise.h" 7 | 8 | // The ratio of the circumference of a circle to its diameter. 9 | constexpr double PI = 3.14159265358979323846l; 10 | 11 | // Converts an angle measured in degrees to an approximately equivalent angle measured in radians. 12 | inline constexpr double toRadians(const double angdeg) { 13 | return PI / 180 * angdeg; 14 | } 15 | 16 | // Converts an angle measured in radians to an approximately equivalent angle measured in degrees. 17 | inline constexpr double toDegrees(const double angrad) { 18 | return 180 / PI * angrad; 19 | } 20 | 21 | // Returns the smallest power of two not less than x. 22 | template 23 | inline UIntT roundUpToPowerOfTwo(const UIntT x) { 24 | assert(x > 0); assert(x <= UIntT{1} << (std::numeric_limits::digits - 1)); 25 | return UIntT{1} << (highestOneBit(x - 1) + 1); 26 | } 27 | 28 | // Returns the largest power of two not greater than x. 29 | template 30 | inline UIntT roundDownToPowerOfTwo(const UIntT x) { 31 | assert(x > 0); 32 | return UIntT{1} << highestOneBit(x); 33 | } 34 | 35 | // Sets min to the smaller and max to the greater of a and b. 36 | template 37 | inline constexpr void minmax(const T a, const T b, T& min, T& max) { 38 | if (b < a) { 39 | min = b; 40 | max = a; 41 | } else { 42 | min = a; 43 | max = b; 44 | } 45 | } 46 | 47 | // Returns 0, 1, or -1 as the specified value is equal to, greater than, or less than zero. 48 | template 49 | inline int signum(const T val) { 50 | return (0 < val) - (val < 0); 51 | } 52 | -------------------------------------------------------------------------------- /Tools/OpenMP.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | // On platforms supporting OpenMP, this file includes the omp.h header file. On other platforms, 4 | // this file provides stubs for the runtime library routines defined in the OpenMP API. 5 | 6 | #ifdef _OPENMP 7 | 8 | #include 9 | 10 | #else 11 | 12 | int omp_get_num_threads(void) 13 | { 14 | return 1; 15 | } 16 | 17 | int omp_get_thread_num(void) 18 | { 19 | return 0; 20 | } 21 | 22 | #endif 23 | -------------------------------------------------------------------------------- /Tools/Simd/AlignedVector.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | 5 | #include 6 | 7 | #include "Tools/CompilerSpecific.h" 8 | #include "Tools/MachineSpecs.h" 9 | 10 | // A std::vector whose elements are properly aligned for use with SIMD instructions. 11 | template 12 | using AlignedVector = std::vector< 13 | T, boost::alignment::aligned_allocator>; 14 | -------------------------------------------------------------------------------- /Tools/TemplateProgramming.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | namespace templates { 4 | 5 | using PackExpansion = int[]; 6 | 7 | } 8 | 9 | // Let pattern be an expression naming one or more parameter packs. This macro executes the pattern 10 | // for each element in the pack. 11 | #define RUN_FORALL(pattern) templates::PackExpansion{0, ((pattern), void(), 0)...} 12 | 13 | // Let pattern be an expression naming one or more parameter packs. This macro executes the pattern 14 | // for each element in the pack for which cond holds. 15 | #define RUN_IF(cond, pattern) RUN_FORALL(((cond) ? (pattern), void() : void())) 16 | 17 | // An empty class, intended for implementing conditional inheritance. 18 | class EmptyClass {}; 19 | -------------------------------------------------------------------------------- /Tools/Timer.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | #include 5 | 6 | // A timer to measure how long some code takes to execute. 7 | class Timer { 8 | public: 9 | // Constructs a timer and starts it. 10 | Timer() : startTime(std::chrono::steady_clock::now()) {} 11 | 12 | // Returns the time elapsed since the timer was started. 13 | template 14 | int64_t elapsed() const { 15 | const auto now = std::chrono::steady_clock::now(); 16 | return std::chrono::duration_cast(now - startTime).count(); 17 | } 18 | 19 | // Restarts the timer. 20 | void restart() { 21 | startTime = std::chrono::steady_clock::now(); 22 | } 23 | 24 | private: 25 | std::chrono::steady_clock::time_point startTime; // Time point when the timer was started. 26 | }; 27 | -------------------------------------------------------------------------------- /Tools/Workarounds.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | // Returns its argument, doing nothing with it at all. This function helps to avoid odr-using 4 | // constant static data members. Constant static data members that are not odr-used in the program 5 | // aren't required to be defined in a namespace scope, which is a good thing. In C++17, the better 6 | // solution is to use inline variables. However, this is C++14 code. 7 | template 8 | T use(T arg) { return arg; } 9 | 10 | // Marks its arguments as possibly unused to suppress compiler warnings. 11 | template 12 | void unused(const Types&...) {} 13 | -------------------------------------------------------------------------------- /Visualization/GraphDrawer.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | 5 | #include "DataStructures/Geometry/Point.h" 6 | #include "DataStructures/Graph/Graph.h" 7 | #include "Visualization/Color.h" 8 | #include "Visualization/Graphic.h" 9 | #include "Visualization/PrimitiveDrawer.h" 10 | 11 | // A facility for drawing graphs. Each edge is drawn as a straight line segment. The color (width) 12 | // of an edge is determined by a user-provided callable object that takes an edge ID as argument 13 | // and returns the corresponding color (width). 14 | class GraphDrawer : public PrimitiveDrawer { 15 | public: 16 | // Constructs a drawer for graphs. 17 | explicit GraphDrawer( 18 | Graphic* const graphic = nullptr, 19 | const std::function& coordinate = {}, 20 | const std::function& color = [](const int /*e*/) { return KIT_BLACK; }, 21 | const std::function& width = [](const int /*e*/) { return LineWidth::THIN; }) 22 | : PrimitiveDrawer(graphic), getCoordinate(coordinate), getColor(color), getLineWidth(width) {} 23 | 24 | // Sets the callable object determining the coordinate of a vertex. 25 | void setCoordinate(const std::function& coordinate) { 26 | getCoordinate = coordinate; 27 | } 28 | 29 | // Sets the callable object determining the color of an edge. 30 | void setColor(const std::function& color) { 31 | getColor = color; 32 | } 33 | 34 | // Sets the callable object determining the width of an edge. 35 | void setLineWidth(const std::function& width) { 36 | getLineWidth = width; 37 | } 38 | 39 | // Draws the specified graph. 40 | template 41 | void drawGraph(const GraphT& graph) { 42 | FORALL_VALID_EDGES(graph, u, e) 43 | drawLine(getCoordinate(u), getCoordinate(graph.edgeHead(e)), getColor(e), getLineWidth(e)); 44 | } 45 | 46 | private: 47 | std::function getCoordinate; // The function determining the coordinate of a vertex. 48 | std::function getColor; // The function determining the color of an edge. 49 | std::function getLineWidth; // The function determining the width of an edge. 50 | }; 51 | -------------------------------------------------------------------------------- /Visualization/Graphic.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | 5 | #include 6 | 7 | #include "DataStructures/Geometry/Rectangle.h" 8 | 9 | // A graphic on which geometric objects can be drawn. To position objects on the graphic independent 10 | // of its type and size, each graphic maintains a user-space coordinate system. The Cartesian user 11 | // space is specified by its smallest and largest x- and y-coordinate. The point with the smallest 12 | // (largest) coordinates is transformed to the lower left (upper right) corner of the graphic. 13 | // However, the user space is not distorted, i.e., one user-space unit in x-direction is in device 14 | // space always as long as a user-space unit in y-direction. This is achieved by adding horizontal 15 | // or vertical padding if needed. This is an abstract base class. Derived classes provide graphics 16 | // of concrete types. 17 | class Graphic { 18 | public: 19 | // Constructs a graphic associated with no file. 20 | Graphic() : cairoContext(nullptr), deviceWidth(0), deviceHeight(0) {} 21 | 22 | // Outputs the current page (if any) and releases resources. 23 | virtual ~Graphic() { 24 | cairo_destroy(cairoContext); 25 | } 26 | 27 | // Returns true if this graphic is associated with a file and ready to be drawn on. 28 | bool isOpen() const { 29 | return cairoContext != nullptr; 30 | } 31 | 32 | // Outputs the current page (if any) and releases resources. 33 | virtual void close() { 34 | cairo_destroy(cairoContext); 35 | cairoContext = nullptr; 36 | } 37 | 38 | // Sets the user space according to the specified rectangle. 39 | void setUserSpace(const Rectangle& uspace) { 40 | assert(isOpen()); 41 | const double uspaceWidth = uspace.northEast().x() - uspace.southWest().x(); 42 | const double uspaceHeight = uspace.northEast().y() - uspace.southWest().y(); 43 | assert(uspaceWidth > 0); 44 | assert(uspaceHeight > 0); 45 | double scale, offsetX = 0, offsetY = 0; 46 | if (deviceWidth * uspaceHeight <= deviceHeight * uspaceWidth) { 47 | scale = deviceWidth / uspaceWidth; 48 | offsetY = (deviceHeight - scale * uspaceHeight) / 2.0; 49 | } else { 50 | scale = deviceHeight / uspaceHeight; 51 | offsetX = (deviceWidth - scale * uspaceWidth) / 2.0; 52 | } 53 | cairo_identity_matrix(cairoContext); 54 | cairo_translate(cairoContext, offsetX, offsetY); 55 | cairo_scale(cairoContext, scale, scale); 56 | cairo_translate(cairoContext, -uspace.southWest().x(), uspace.northEast().y()); 57 | cairo_scale(cairoContext, 1, -1); 58 | userSpace = uspace; 59 | } 60 | 61 | // Returns the user space. 62 | Rectangle getUserSpace() const { 63 | return userSpace; 64 | } 65 | 66 | // Returns the encapsulated cairo drawing context. 67 | cairo_t* getCairoContext() { 68 | return cairoContext; 69 | } 70 | 71 | // Converts a value measured in points to an equivalent value measured in device-space units. 72 | virtual double toDeviceSpaceUnits(const double pt) const = 0; 73 | 74 | // Converts a value measured in points to an equivalent value measured in user-space units. 75 | double toUserSpaceUnits(const double pt) { 76 | assert(isOpen()); 77 | double x = toDeviceSpaceUnits(pt), y = 0; 78 | cairo_device_to_user_distance(cairoContext, &x, &y); 79 | return x; 80 | } 81 | 82 | // Outputs the current page and inserts a new blank page. 83 | // Note: This member function may or may not create a new cairo drawing context. 84 | virtual void newPage() = 0; 85 | 86 | protected: 87 | cairo_t* cairoContext; // A cairo drawing context used to draw on the graphic. 88 | Rectangle userSpace; // The user space specified as a rectangle. 89 | double deviceWidth; // The width of the graphic in points or pixels, depending on the type. 90 | double deviceHeight; // The height of the graphic in points or pixels, depending on the type. 91 | }; 92 | -------------------------------------------------------------------------------- /Visualization/Graphics/PdfGraphic.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | #include 5 | 6 | #include 7 | #include 8 | 9 | #include "DataStructures/Geometry/Rectangle.h" 10 | #include "Visualization/Graphic.h" 11 | 12 | // A graphic in PDF format. See the description of its base class for further details. 13 | class PdfGraphic : public Graphic { 14 | public: 15 | // Constructs a PDF graphic associated with no file. 16 | PdfGraphic() = default; 17 | 18 | // Constructs a PDF graphic and calls open with the specified arguments. 19 | PdfGraphic(const std::string& filename, const double width, const double height, 20 | const Rectangle& userSpace = {{0, 0}, {1, 1}}) { 21 | open(filename, width, height, userSpace); 22 | } 23 | 24 | // PDF graphics can only be moved, not copied. 25 | PdfGraphic(PdfGraphic&& rhs) = default; 26 | PdfGraphic& operator=(PdfGraphic&& rhs) = default; 27 | 28 | // Opens a PDF graphic file of the specified size (in cm) with the given name. 29 | void open(const std::string& filename, const double width, const double height, 30 | const Rectangle& userSpace = {{0, 0}, {1, 1}}) { 31 | assert(!isOpen()); 32 | deviceWidth = width / 2.54 * 72; // cm to inches to pt 33 | deviceHeight = height / 2.54 * 72; // cm to inches to pt 34 | assert(deviceWidth > 0); 35 | assert(deviceHeight > 0); 36 | cairo_surface_t* surface; 37 | surface = cairo_pdf_surface_create((filename + ".pdf").c_str(), deviceWidth, deviceHeight); 38 | assert(cairo_surface_status(surface) == CAIRO_STATUS_SUCCESS); 39 | cairoContext = cairo_create(surface); 40 | assert(cairo_status(cairoContext) == CAIRO_STATUS_SUCCESS); 41 | cairo_surface_destroy(surface); 42 | setUserSpace(userSpace); 43 | } 44 | 45 | // Converts a value measured in points to an equivalent value measured in device-space units. 46 | virtual double toDeviceSpaceUnits(const double pt) const override { 47 | return pt; 48 | } 49 | 50 | // Outputs the current page and inserts a new blank page. 51 | // Note: This member function does not create a new cairo drawing context. 52 | virtual void newPage() override { 53 | assert(isOpen()); 54 | cairo_show_page(cairoContext); 55 | } 56 | }; 57 | -------------------------------------------------------------------------------- /Visualization/Graphics/PngGraphic.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | #include 5 | #include 6 | 7 | #include 8 | 9 | #include "DataStructures/Geometry/Rectangle.h" 10 | #include "Visualization/Graphic.h" 11 | 12 | // A graphic in PNG format with 381dpi. See the description of its base class for further details. 13 | class PngGraphic : public Graphic { 14 | public: 15 | // Constructs a PNG graphic associated with no file. 16 | PngGraphic() : page(0) {} 17 | 18 | // Constructs a PNG graphic and calls open with the specified arguments. 19 | PngGraphic(const std::string& filename, const double width, const double height, 20 | const Rectangle& userSpace = {{0, 0}, {1, 1}}) { 21 | open(filename, width, height, userSpace); 22 | } 23 | 24 | // PNG graphics can only be moved, not copied. 25 | PngGraphic(PngGraphic&& rhs) = default; 26 | PngGraphic& operator=(PngGraphic&& rhs) = default; 27 | 28 | // Outputs the current page (if any) and releases resources. 29 | virtual ~PngGraphic() override { 30 | if (isOpen()) { 31 | const std::string name = baseFilename + (page > 1 ? "_" + std::to_string(page) : ""); 32 | cairo_surface_write_to_png(cairo_get_target(cairoContext), (name + ".png").c_str()); 33 | } 34 | } 35 | 36 | // Opens a PNG graphic file of the specified size (in cm) with the given name. 37 | void open(const std::string& filename, const double width, const double height, 38 | const Rectangle& userSpace = {{0, 0}, {1, 1}}) { 39 | assert(!isOpen()); 40 | deviceWidth = std::round(width / 2.54 * 381); // cm to inches to pixels 41 | deviceHeight = std::round(height / 2.54 * 381); // cm to inches to pixels 42 | assert(deviceWidth > 0); 43 | assert(deviceHeight > 0); 44 | cairo_surface_t* surface; 45 | surface = cairo_image_surface_create(CAIRO_FORMAT_ARGB32, deviceWidth, deviceHeight); 46 | assert(cairo_surface_status(surface) == CAIRO_STATUS_SUCCESS); 47 | cairoContext = cairo_create(surface); 48 | assert(cairo_status(cairoContext) == CAIRO_STATUS_SUCCESS); 49 | cairo_surface_destroy(surface); 50 | setUserSpace(userSpace); 51 | baseFilename = filename; 52 | page = 1; 53 | } 54 | 55 | // Outputs the current page (if any) and releases resources. 56 | virtual void close() override { 57 | if (isOpen()) { 58 | const std::string name = baseFilename + (page > 1 ? "_" + std::to_string(page) : ""); 59 | cairo_surface_write_to_png(cairo_get_target(cairoContext), (name + ".png").c_str()); 60 | Graphic::close(); 61 | } 62 | } 63 | 64 | // Converts a value measured in points to an equivalent value measured in device-space units. 65 | virtual double toDeviceSpaceUnits(const double pt) const override { 66 | return pt / 72 * 381; // pt to inches to pixels 67 | } 68 | 69 | // Outputs the current page and inserts a new blank page. 70 | // Note: This member function creates a new cairo drawing context. 71 | virtual void newPage() override { 72 | assert(isOpen()); 73 | close(); 74 | cairo_surface_t* surface; 75 | surface = cairo_image_surface_create(CAIRO_FORMAT_ARGB32, deviceWidth, deviceHeight); 76 | assert(cairo_surface_status(surface) == CAIRO_STATUS_SUCCESS); 77 | cairoContext = cairo_create(surface); 78 | assert(cairo_status(cairoContext) == CAIRO_STATUS_SUCCESS); 79 | cairo_surface_destroy(surface); 80 | setUserSpace(userSpace); 81 | ++page; 82 | } 83 | 84 | private: 85 | std::string baseFilename; // The base name of the associated graphic file. 86 | int page; // The number of the current page. 87 | }; 88 | -------------------------------------------------------------------------------- /Visualization/Graphics/SvgGraphic.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | #include 5 | 6 | #include 7 | #include 8 | 9 | #include "DataStructures/Geometry/Rectangle.h" 10 | #include "Visualization/Graphic.h" 11 | 12 | // A graphic in SVG format. See the description of its base class for further details. 13 | class SvgGraphic : public Graphic { 14 | public: 15 | // Constructs a SVG graphic associated with no file. 16 | SvgGraphic() : page(0) {} 17 | 18 | // Constructs a SVG graphic and calls open with the specified arguments. 19 | SvgGraphic(const std::string& filename, const double width, const double height, 20 | const Rectangle& userSpace = {{0, 0}, {1, 1}}) { 21 | open(filename, width, height, userSpace); 22 | } 23 | 24 | // SVG graphics can only be moved, not copied. 25 | SvgGraphic(SvgGraphic&& rhs) = default; 26 | SvgGraphic& operator=(SvgGraphic&& rhs) = default; 27 | 28 | // Opens a SVG graphic file of the specified size (in cm) with the given name. 29 | void open(const std::string& filename, const double width, const double height, 30 | const Rectangle& userSpace = {{0, 0}, {1, 1}}) { 31 | assert(!isOpen()); 32 | deviceWidth = width / 2.54 * 72; // cm to inches to pt 33 | deviceHeight = height / 2.54 * 72; // cm to inches to pt 34 | assert(deviceWidth > 0); 35 | assert(deviceHeight > 0); 36 | cairo_surface_t* surface; 37 | surface = cairo_svg_surface_create((filename + ".svg").c_str(), deviceWidth, deviceHeight); 38 | assert(cairo_surface_status(surface) == CAIRO_STATUS_SUCCESS); 39 | cairoContext = cairo_create(surface); 40 | assert(cairo_status(cairoContext) == CAIRO_STATUS_SUCCESS); 41 | cairo_surface_destroy(surface); 42 | setUserSpace(userSpace); 43 | baseFilename = filename; 44 | page = 1; 45 | } 46 | 47 | // Converts a value measured in points to an equivalent value measured in device-space units. 48 | virtual double toDeviceSpaceUnits(const double pt) const override { 49 | return pt; 50 | } 51 | 52 | // Outputs the current page and inserts a new blank page. 53 | // Note: This member function creates a new cairo drawing context. 54 | virtual void newPage() override { 55 | assert(isOpen()); 56 | close(); 57 | const std::string name = baseFilename + "_" + std::to_string(++page) + ".svg"; 58 | cairo_surface_t* surface = cairo_svg_surface_create(name.c_str(), deviceWidth, deviceHeight); 59 | assert(cairo_surface_status(surface) == CAIRO_STATUS_SUCCESS); 60 | cairoContext = cairo_create(surface); 61 | assert(cairo_status(cairoContext) == CAIRO_STATUS_SUCCESS); 62 | cairo_surface_destroy(surface); 63 | setUserSpace(userSpace); 64 | } 65 | 66 | private: 67 | std::string baseFilename; // The base name of the associated graphic file. 68 | int page; // The number of the current page. 69 | }; 70 | --------------------------------------------------------------------------------