diff --git a/CMakeLists.txt b/CMakeLists.txt index 4930018d54e..76ec81072ee 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -41,7 +41,7 @@ file(GLOB ExtractorGlob Extractor/*.cpp) set(ExtractorSources extractor.cpp ${ExtractorGlob}) add_executable(osrm-extract ${ExtractorSources}) -file(GLOB PrepareGlob Contractor/*.cpp DataStructures/HilbertValue.cpp) +file(GLOB PrepareGlob Contractor/*.cpp DataStructures/HilbertValue.cpp DataStructures/RestrictionMap.cpp) set(PrepareSources prepare.cpp ${PrepareGlob}) add_executable(osrm-prepare ${PrepareSources}) diff --git a/Contractor/BFSComponentExplorer.h b/Contractor/BFSComponentExplorer.h new file mode 100644 index 00000000000..4e0788aadbd --- /dev/null +++ b/Contractor/BFSComponentExplorer.h @@ -0,0 +1,145 @@ +#ifndef __BFS_COMPONENT_EXPLORER_H__ +#define __BFS_COMPONENT_EXPLORER_H__ + +#include +#include + +#include "../typedefs.h" +#include "../DataStructures/DynamicGraph.h" +#include "../DataStructures/RestrictionMap.h" + +/** + * Explores the components of the given graph while respecting turn restrictions + * and barriers. + */ +template class BFSComponentExplorer +{ + public: + typedef typename GraphT::NodeIterator NodeIterator; + typedef typename GraphT::EdgeIterator EdgeIterator; + + BFSComponentExplorer(const GraphT &dynamicGraph, + const RestrictionMap &restrictions, + const boost::unordered_set &barrier_nodes) + : m_graph(dynamicGraph), m_restriction_map(restrictions), m_barrier_nodes(barrier_nodes) + { + BOOST_ASSERT(m_graph.GetNumberOfNodes() > 0); + } + + /*! + * Returns the size of the component that the node belongs to. + */ + inline unsigned int getComponentSize(NodeID node) + { + BOOST_ASSERT(node < m_component_index_list.size()); + + return m_component_index_size[m_component_index_list[node]]; + } + + inline unsigned int getNumberOfComponents() { return m_component_index_size.size(); } + + /*! + * Computes the component sizes. + */ + void run() + { + std::queue> bfs_queue; + unsigned current_component = 0; + + BOOST_ASSERT(m_component_index_list.empty()); + BOOST_ASSERT(m_component_index_size.empty()); + + unsigned num_nodes = m_graph.GetNumberOfNodes(); + + m_component_index_list.resize(num_nodes, std::numeric_limits::max()); + + BOOST_ASSERT(num_nodes > 0); + + // put unexplorered node with parent pointer into queue + for (NodeID node = 0; node < num_nodes; ++node) + { + if (std::numeric_limits::max() == m_component_index_list[node]) + { + unsigned size = exploreComponent(bfs_queue, node, current_component); + + // push size into vector + m_component_index_size.push_back(size); + ++current_component; + } + } + } + + private: + /*! + * Explores the current component that starts at node using BFS. + */ + inline unsigned exploreComponent(std::queue> &bfs_queue, + NodeID node, + unsigned current_component) + { + bfs_queue.push(std::make_pair(node, node)); + // mark node as read + m_component_index_list[node] = current_component; + + unsigned current_component_size = 1; + + while (!bfs_queue.empty()) + { + // fetch element from BFS queue + std::pair current_queue_item = bfs_queue.front(); + bfs_queue.pop(); + + const NodeID v = current_queue_item.first; // current node + const NodeID u = current_queue_item.second; // parent + // increment size counter of current component + ++current_component_size; + const bool is_barrier_node = (m_barrier_nodes.find(v) != m_barrier_nodes.end()); + if (!is_barrier_node) + { + const NodeID to_node_of_only_restriction = + m_restriction_map.CheckForEmanatingIsOnlyTurn(u, v); + + for (EdgeIterator e2 = m_graph.BeginEdges(v); e2 < m_graph.EndEdges(v); ++e2) + { + NodeIterator w = m_graph.GetTarget(e2); + + if (to_node_of_only_restriction != std::numeric_limits::max() && + w != to_node_of_only_restriction) + { + // At an only_-restriction but not at the right turn + continue; + } + + if (u != w) + { + // only add an edge if turn is not a U-turn except + // when it is at the end of a dead-end street. + if (!m_restriction_map.CheckIfTurnIsRestricted(u, v, w)) + { + // only add an edge if turn is not prohibited + if (std::numeric_limits::max() == m_component_index_list[w]) + { + // insert next (node, parent) only if w has + // not yet been explored + // mark node as read + m_component_index_list[w] = current_component; + bfs_queue.push(std::make_pair(w, v)); + } + } + } + } + } + } + + return current_component_size; + } + + std::vector m_component_index_list; + std::vector m_component_index_size; + + const GraphT &m_graph; + const RestrictionMap &m_restriction_map; + const boost::unordered_set &m_barrier_nodes; +}; + +#endif diff --git a/Contractor/Contractor.h b/Contractor/Contractor.h index 5d103f8a98e..46bf78be8a6 100644 --- a/Contractor/Contractor.h +++ b/Contractor/Contractor.h @@ -41,114 +41,144 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #include #include -#include -#include #include #include #include -class Contractor { +class Contractor +{ -private: - struct ContractorEdgeData { - ContractorEdgeData() : - distance(0), id(0), originalEdges(0), shortcut(0), forward(0), backward(0), originalViaNodeID(false) {} - ContractorEdgeData( unsigned _distance, unsigned _originalEdges, unsigned _id, bool _shortcut, bool _forward, bool _backward) : - distance(_distance), id(_id), originalEdges(std::min((unsigned)1<<28, _originalEdges) ), shortcut(_shortcut), forward(_forward), backward(_backward), originalViaNodeID(false) {} + private: + struct ContractorEdgeData + { + ContractorEdgeData() + : distance(0), id(0), originalEdges(0), shortcut(0), forward(0), backward(0), + originalViaNodeID(false) + { + } + ContractorEdgeData(unsigned _distance, + unsigned _originalEdges, + unsigned _id, + bool _shortcut, + bool _forward, + bool _backward) + : distance(_distance), id(_id), + originalEdges(std::min((unsigned)1 << 28, _originalEdges)), shortcut(_shortcut), + forward(_forward), backward(_backward), originalViaNodeID(false) + { + } unsigned distance; unsigned id; - unsigned originalEdges:28; - bool shortcut:1; - bool forward:1; - bool backward:1; - bool originalViaNodeID:1; + unsigned originalEdges : 28; + bool shortcut : 1; + bool forward : 1; + bool backward : 1; + bool originalViaNodeID : 1; } data; - struct _HeapData { + struct _HeapData + { short hop; bool target; _HeapData() : hop(0), target(false) {} - _HeapData( short h, bool t ) : hop(h), target(t) {} + _HeapData(short h, bool t) : hop(h), target(t) {} }; - typedef DynamicGraph< ContractorEdgeData > _DynamicGraph; + typedef DynamicGraph _DynamicGraph; // typedef BinaryHeap< NodeID, NodeID, int, _HeapData, ArrayStorage > _Heap; - typedef BinaryHeap< NodeID, NodeID, int, _HeapData, XORFastHashStorage > _Heap; + typedef BinaryHeap> _Heap; typedef _DynamicGraph::InputEdge _ContractorEdge; - struct _ThreadData { + struct _ThreadData + { _Heap heap; - std::vector< _ContractorEdge > insertedEdges; - std::vector< NodeID > neighbours; - _ThreadData( NodeID nodes ): heap( nodes ) { } + std::vector<_ContractorEdge> insertedEdges; + std::vector neighbours; + _ThreadData(NodeID nodes) : heap(nodes) {} }; - struct _PriorityData { + struct _PriorityData + { int depth; - _PriorityData() : depth(0) { } + _PriorityData() : depth(0) {} }; - struct _ContractionInformation { + struct _ContractionInformation + { int edgesDeleted; int edgesAdded; int originalEdgesDeleted; int originalEdgesAdded; - _ContractionInformation() : edgesDeleted(0), edgesAdded(0), originalEdgesDeleted(0), originalEdgesAdded(0) {} + _ContractionInformation() + : edgesDeleted(0), edgesAdded(0), originalEdgesDeleted(0), originalEdgesAdded(0) + { + } }; - struct _RemainingNodeData { - _RemainingNodeData() : id (0), isIndependent(false) {} - NodeID id:31; - bool isIndependent:1; + struct _RemainingNodeData + { + _RemainingNodeData() : id(0), isIndependent(false) {} + NodeID id : 31; + bool isIndependent : 1; }; - struct _NodePartitionor { - inline bool operator()(_RemainingNodeData & nodeData ) const { + struct _NodePartitionor + { + inline bool operator()(_RemainingNodeData &nodeData) const + { return !nodeData.isIndependent; } }; -public: - - template - Contractor( int nodes, ContainerT& inputEdges) { - std::vector< _ContractorEdge > edges; - edges.reserve(inputEdges.size()*2); + public: + template Contractor(int nodes, ContainerT &inputEdges) + { + std::vector<_ContractorEdge> edges; + edges.reserve(inputEdges.size() * 2); temp_edge_counter = 0; typename ContainerT::deallocation_iterator diter = inputEdges.dbegin(); - typename ContainerT::deallocation_iterator dend = inputEdges.dend(); + typename ContainerT::deallocation_iterator dend = inputEdges.dend(); _ContractorEdge newEdge; - while(diter!=dend) { + while (diter != dend) + { newEdge.source = diter->source(); newEdge.target = diter->target(); - newEdge.data = ContractorEdgeData( (std::max)((int)diter->weight(), 1 ), 1, diter->id(), false, diter->isForward(), diter->isBackward()); - BOOST_ASSERT_MSG( newEdge.data.distance > 0, "edge distance < 1" ); + newEdge.data = ContractorEdgeData((std::max)((int)diter->weight(), 1), + 1, + diter->id(), + false, + diter->isForward(), + diter->isBackward()); + BOOST_ASSERT_MSG(newEdge.data.distance > 0, "edge distance < 1"); #ifndef NDEBUG - if ( newEdge.data.distance > 24 * 60 * 60 * 10 ) { - SimpleLogger().Write(logWARNING) << - "Edge weight large -> " << newEdge.data.distance; + if (newEdge.data.distance > 24 * 60 * 60 * 10) + { + SimpleLogger().Write(logWARNING) << "Edge weight large -> " + << newEdge.data.distance; } #endif - edges.push_back( newEdge ); - std::swap( newEdge.source, newEdge.target ); + edges.push_back(newEdge); + std::swap(newEdge.source, newEdge.target); newEdge.data.forward = diter->isBackward(); newEdge.data.backward = diter->isForward(); - edges.push_back( newEdge ); + edges.push_back(newEdge); ++diter; } - //clear input vector and trim the current set of edges with the well-known swap trick + // clear input vector and trim the current set of edges with the well-known swap trick inputEdges.clear(); - sort( edges.begin(), edges.end() ); + sort(edges.begin(), edges.end()); NodeID edge = 0; - for ( NodeID i = 0; i < edges.size(); ) { + for (NodeID i = 0; i < edges.size();) + { const NodeID source = edges[i].source; const NodeID target = edges[i].target; const NodeID id = edges[i].data.id; - //remove eigenloops - if ( source == target ) { + // remove eigenloops + if (source == target) + { i++; continue; } @@ -161,38 +191,51 @@ class Contractor { forwardEdge.data.shortcut = backwardEdge.data.shortcut = false; forwardEdge.data.id = backwardEdge.data.id = id; forwardEdge.data.originalEdges = backwardEdge.data.originalEdges = 1; - forwardEdge.data.distance = backwardEdge.data.distance = std::numeric_limits< int >::max(); - //remove parallel edges - while ( i < edges.size() && edges[i].source == source && edges[i].target == target ) { - if ( edges[i].data.forward) { - forwardEdge.data.distance = std::min( edges[i].data.distance, forwardEdge.data.distance ); + forwardEdge.data.distance = backwardEdge.data.distance = + std::numeric_limits::max(); + // remove parallel edges + while (i < edges.size() && edges[i].source == source && edges[i].target == target) + { + if (edges[i].data.forward) + { + forwardEdge.data.distance = + std::min(edges[i].data.distance, forwardEdge.data.distance); } - if ( edges[i].data.backward) { - backwardEdge.data.distance = std::min( edges[i].data.distance, backwardEdge.data.distance ); + if (edges[i].data.backward) + { + backwardEdge.data.distance = + std::min(edges[i].data.distance, backwardEdge.data.distance); } ++i; } - //merge edges (s,t) and (t,s) into bidirectional edge - if ( forwardEdge.data.distance == backwardEdge.data.distance ) { - if ( (int)forwardEdge.data.distance != std::numeric_limits< int >::max() ) { + // merge edges (s,t) and (t,s) into bidirectional edge + if (forwardEdge.data.distance == backwardEdge.data.distance) + { + if ((int)forwardEdge.data.distance != std::numeric_limits::max()) + { forwardEdge.data.backward = true; edges[edge++] = forwardEdge; } - } else { //insert seperate edges - if ( ((int)forwardEdge.data.distance) != std::numeric_limits< int >::max() ) { + } + else + { // insert seperate edges + if (((int)forwardEdge.data.distance) != std::numeric_limits::max()) + { edges[edge++] = forwardEdge; } - if ( (int)backwardEdge.data.distance != std::numeric_limits< int >::max() ) { + if ((int)backwardEdge.data.distance != std::numeric_limits::max()) + { edges[edge++] = backwardEdge; } } } - std::cout << "merged " << edges.size() - edge << " edges out of " << edges.size() << std::endl; - edges.resize( edge ); - _graph = boost::make_shared<_DynamicGraph>( nodes, edges ); + std::cout << "merged " << edges.size() - edge << " edges out of " << edges.size() + << std::endl; + edges.resize(edge); + _graph = std::make_shared<_DynamicGraph>(nodes, edges); edges.clear(); std::vector<_ContractorEdge>().swap(edges); - BOOST_ASSERT( 0 == edges.capacity() ); + BOOST_ASSERT(0 == edges.capacity()); // unsigned maxdegree = 0; // NodeID highestNode = 0; // @@ -204,61 +247,74 @@ class Contractor { // } // } // - // SimpleLogger().Write() << "edges at node with id " << highestNode << " has degree " << maxdegree; - // for(unsigned i = _graph->BeginEdges(highestNode); i < _graph->EndEdges(highestNode); ++i) { - // SimpleLogger().Write() << " ->(" << highestNode << "," << _graph->GetTarget(i) << "); via: " << _graph->GetEdgeData(i).via; + // SimpleLogger().Write() << "edges at node with id " << highestNode << " has degree + // " << maxdegree; + // for(unsigned i = _graph->BeginEdges(highestNode); i < + // _graph->EndEdges(highestNode); ++i) { + // SimpleLogger().Write() << " ->(" << highestNode << "," << _graph->GetTarget(i) + // << "); via: " << _graph->GetEdgeData(i).via; // } - //Create temporary file + // Create temporary file // GetTemporaryFileName(temporaryEdgeStorageFilename); edge_storage_slot = TemporaryStorage::GetInstance().AllocateSlot(); std::cout << "contractor finished initalization" << std::endl; } - ~Contractor() { - //Delete temporary file + ~Contractor() + { + // Delete temporary file // remove(temporaryEdgeStorageFilename.c_str()); TemporaryStorage::GetInstance().DeallocateSlot(edge_storage_slot); } - void Run() { + void Run() + { const NodeID numberOfNodes = _graph->GetNumberOfNodes(); - Percent p (numberOfNodes); + Percent p(numberOfNodes); const unsigned maxThreads = omp_get_max_threads(); - std::vector < _ThreadData* > threadData; - for ( unsigned threadNum = 0; threadNum < maxThreads; ++threadNum ) { - threadData.push_back( new _ThreadData( numberOfNodes ) ); + std::vector<_ThreadData *> threadData; + for (unsigned threadNum = 0; threadNum < maxThreads; ++threadNum) + { + threadData.push_back(new _ThreadData(numberOfNodes)); } std::cout << "Contractor is using " << maxThreads << " threads" << std::endl; NodeID numberOfContractedNodes = 0; - std::vector< _RemainingNodeData > remainingNodes( numberOfNodes ); - std::vector< float > nodePriority( numberOfNodes ); - std::vector< _PriorityData > nodeData( numberOfNodes ); + std::vector<_RemainingNodeData> remainingNodes(numberOfNodes); + std::vector nodePriority(numberOfNodes); + std::vector<_PriorityData> nodeData(numberOfNodes); - //initialize the variables -#pragma omp parallel for schedule ( guided ) - for ( int x = 0; x < ( int ) numberOfNodes; ++x ) { +// initialize the variables +#pragma omp parallel for schedule(guided) + for (int x = 0; x < (int)numberOfNodes; ++x) + { remainingNodes[x].id = x; } std::cout << "initializing elimination PQ ..." << std::flush; #pragma omp parallel { - _ThreadData* data = threadData[omp_get_thread_num()]; -#pragma omp parallel for schedule ( guided ) - for ( int x = 0; x < ( int ) numberOfNodes; ++x ) { - nodePriority[x] = _Evaluate( data, &nodeData[x], x ); + _ThreadData *data = threadData[omp_get_thread_num()]; +#pragma omp parallel for schedule(guided) + for (int x = 0; x < (int)numberOfNodes; ++x) + { + nodePriority[x] = _Evaluate(data, &nodeData[x], x); } } - std::cout << "ok" << std::endl << "preprocessing " << numberOfNodes << " nodes ..." << std::flush; + std::cout << "ok" << std::endl << "preprocessing " << numberOfNodes << " nodes ..." + << std::flush; bool flushedContractor = false; - while ( numberOfNodes > 2 && numberOfContractedNodes < numberOfNodes ) { - if(!flushedContractor && (numberOfContractedNodes > (numberOfNodes*0.65) ) ){ - DeallocatingVector<_ContractorEdge> newSetOfEdges; //this one is not explicitely cleared since it goes out of scope anywa + while (numberOfNodes > 2 && numberOfContractedNodes < numberOfNodes) + { + if (!flushedContractor && (numberOfContractedNodes > (numberOfNodes * 0.65))) + { + DeallocatingVector<_ContractorEdge> newSetOfEdges; // this one is not explicitely + // cleared since it goes out of + // scope anywa std::cout << " [flush " << numberOfContractedNodes << " nodes] " << std::flush; //Delete old heap data to free memory that we need for the coming operations @@ -267,113 +323,129 @@ class Contractor { } threadData.clear(); - //Create new priority array + // Create new priority array std::vector newNodePriority(remainingNodes.size()); - //this map gives the old IDs from the new ones, necessary to get a consistent graph at the end of contraction + // this map gives the old IDs from the new ones, necessary to get a consistent graph + // at the end of contraction oldNodeIDFromNewNodeIDMap.resize(remainingNodes.size()); - //this map gives the new IDs from the old ones, necessary to remap targets from the remaining graph + // this map gives the new IDs from the old ones, necessary to remap targets from the + // remaining graph std::vector newNodeIDFromOldNodeIDMap(numberOfNodes, UINT_MAX); - //build forward and backward renumbering map and remap ids in remainingNodes and Priorities. - for(unsigned newNodeID = 0; newNodeID < remainingNodes.size(); ++newNodeID) { - //create renumbering maps in both directions + // build forward and backward renumbering map and remap ids in remainingNodes and + // Priorities. + for (unsigned newNodeID = 0; newNodeID < remainingNodes.size(); ++newNodeID) + { + // create renumbering maps in both directions oldNodeIDFromNewNodeIDMap[newNodeID] = remainingNodes[newNodeID].id; newNodeIDFromOldNodeIDMap[remainingNodes[newNodeID].id] = newNodeID; newNodePriority[newNodeID] = nodePriority[remainingNodes[newNodeID].id]; remainingNodes[newNodeID].id = newNodeID; } - TemporaryStorage & tempStorage = TemporaryStorage::GetInstance(); - //walk over all nodes - for(unsigned i = 0; i < _graph->GetNumberOfNodes(); ++i) { + TemporaryStorage &tempStorage = TemporaryStorage::GetInstance(); + // walk over all nodes + for (unsigned i = 0; i < _graph->GetNumberOfNodes(); ++i) + { const NodeID start = i; - for(_DynamicGraph::EdgeIterator currentEdge = _graph->BeginEdges(start); currentEdge < _graph->EndEdges(start); ++currentEdge) { - _DynamicGraph::EdgeData & data = _graph->GetEdgeData(currentEdge); + for (_DynamicGraph::EdgeIterator currentEdge = _graph->BeginEdges(start); + currentEdge < _graph->EndEdges(start); + ++currentEdge) + { + _DynamicGraph::EdgeData &data = _graph->GetEdgeData(currentEdge); const NodeID target = _graph->GetTarget(currentEdge); - if(UINT_MAX == newNodeIDFromOldNodeIDMap[i] ){ - //Save edges of this node w/o renumbering. - tempStorage.WriteToSlot(edge_storage_slot, (char*)&start, sizeof(NodeID)); - tempStorage.WriteToSlot(edge_storage_slot, (char*)&target, sizeof(NodeID)); - tempStorage.WriteToSlot(edge_storage_slot, (char*)&data, sizeof(_DynamicGraph::EdgeData)); + if (UINT_MAX == newNodeIDFromOldNodeIDMap[i]) + { + // Save edges of this node w/o renumbering. + tempStorage.WriteToSlot( + edge_storage_slot, (char *)&start, sizeof(NodeID)); + tempStorage.WriteToSlot( + edge_storage_slot, (char *)&target, sizeof(NodeID)); + tempStorage.WriteToSlot( + edge_storage_slot, (char *)&data, sizeof(_DynamicGraph::EdgeData)); ++temp_edge_counter; - } else { - //node is not yet contracted. - //add (renumbered) outgoing edges to new DynamicGraph. + } + else + { + // node is not yet contracted. + // add (renumbered) outgoing edges to new DynamicGraph. _ContractorEdge newEdge; newEdge.source = newNodeIDFromOldNodeIDMap[start]; newEdge.target = newNodeIDFromOldNodeIDMap[target]; newEdge.data = data; newEdge.data.originalViaNodeID = true; - BOOST_ASSERT_MSG( - UINT_MAX != newNodeIDFromOldNodeIDMap[start], - "new start id not resolveable" - ); - BOOST_ASSERT_MSG( - UINT_MAX != newNodeIDFromOldNodeIDMap[target], - "new target id not resolveable" - ); + BOOST_ASSERT_MSG(UINT_MAX != newNodeIDFromOldNodeIDMap[start], + "new start id not resolveable"); + BOOST_ASSERT_MSG(UINT_MAX != newNodeIDFromOldNodeIDMap[target], + "new target id not resolveable"); newSetOfEdges.push_back(newEdge); } } } - //Delete map from old NodeIDs to new ones. + // Delete map from old NodeIDs to new ones. std::vector().swap(newNodeIDFromOldNodeIDMap); - //Replace old priorities array by new one + // Replace old priorities array by new one nodePriority.swap(newNodePriority); - //Delete old nodePriority vector + // Delete old nodePriority vector std::vector().swap(newNodePriority); - //old Graph is removed + // old Graph is removed _graph.reset(); - //create new graph + // create new graph std::sort(newSetOfEdges.begin(), newSetOfEdges.end()); - _graph = boost::make_shared<_DynamicGraph>(remainingNodes.size(), newSetOfEdges); + _graph = std::make_shared<_DynamicGraph>(remainingNodes.size(), newSetOfEdges); newSetOfEdges.clear(); flushedContractor = true; - //INFO: MAKE SURE THIS IS THE LAST OPERATION OF THE FLUSH! - //reinitialize heaps and ThreadData objects with appropriate size - for ( unsigned threadNum = 0; threadNum < maxThreads; ++threadNum ) { - threadData.push_back( new _ThreadData( _graph->GetNumberOfNodes() ) ); + // INFO: MAKE SURE THIS IS THE LAST OPERATION OF THE FLUSH! + // reinitialize heaps and ThreadData objects with appropriate size + for (unsigned threadNum = 0; threadNum < maxThreads; ++threadNum) + { + threadData.push_back(new _ThreadData(_graph->GetNumberOfNodes())); } } - const int last = ( int ) remainingNodes.size(); + const int last = (int)remainingNodes.size(); #pragma omp parallel { - //determine independent node set - _ThreadData* const data = threadData[omp_get_thread_num()]; -#pragma omp for schedule ( guided ) - for ( int i = 0; i < last; ++i ) { + // determine independent node set + _ThreadData *const data = threadData[omp_get_thread_num()]; +#pragma omp for schedule(guided) + for (int i = 0; i < last; ++i) + { const NodeID node = remainingNodes[i].id; - remainingNodes[i].isIndependent = _IsIndependent( nodePriority/*, nodeData*/, data, node ); + remainingNodes[i].isIndependent = + _IsIndependent(nodePriority /*, nodeData*/, data, node); } } _NodePartitionor functor; - const std::vector < _RemainingNodeData >::const_iterator first = stable_partition( remainingNodes.begin(), remainingNodes.end(), functor ); + const std::vector<_RemainingNodeData>::const_iterator first = + stable_partition(remainingNodes.begin(), remainingNodes.end(), functor); const int firstIndependent = first - remainingNodes.begin(); - //contract independent nodes +// contract independent nodes #pragma omp parallel { - _ThreadData* data = threadData[omp_get_thread_num()]; -#pragma omp for schedule ( guided ) nowait - for ( int position = firstIndependent ; position < last; ++position ) { + _ThreadData *data = threadData[omp_get_thread_num()]; +#pragma omp for schedule(guided) nowait + for (int position = firstIndependent; position < last; ++position) + { NodeID x = remainingNodes[position].id; - _Contract< false > ( data, x ); - //nodePriority[x] = -1; + _Contract(data, x); + // nodePriority[x] = -1; } - std::sort( data->insertedEdges.begin(), data->insertedEdges.end() ); + std::sort(data->insertedEdges.begin(), data->insertedEdges.end()); } #pragma omp parallel { - _ThreadData* data = threadData[omp_get_thread_num()]; -#pragma omp for schedule ( guided ) nowait - for ( int position = firstIndependent ; position < last; ++position ) { + _ThreadData *data = threadData[omp_get_thread_num()]; +#pragma omp for schedule(guided) nowait + for (int position = firstIndependent; position < last; ++position) + { NodeID x = remainingNodes[position].id; - _DeleteIncomingEdges( data, x ); + _DeleteIncomingEdges(data, x); } } //insert new edges @@ -383,42 +455,45 @@ class Contractor { _DynamicGraph::EdgeIterator currentEdgeID = _graph->FindEdge(edge.source, edge.target); if(currentEdgeID < _graph->EndEdges(edge.source) ) { _DynamicGraph::EdgeData & currentEdgeData = _graph->GetEdgeData(currentEdgeID); - if( currentEdgeData.shortcut && - edge.data.forward == currentEdgeData.forward && - edge.data.backward == currentEdgeData.backward && - edge.data.distance < currentEdgeData.distance - ) { + if(currentEdgeData.shortcut && + edge.data.forward == currentEdgeData.forward && + edge.data.backward == currentEdgeData.backward && + edge.data.distance < currentEdgeData.distance) + { // found a duplicate edge with smaller weight, update it. currentEdgeData = edge.data; - // currentEdgeData.distance = std::min(currentEdgeData.distance, edge.data.distance); + // currentEdgeData.distance = std::min(currentEdgeData.distance, + // edge.data.distance); continue; } } - _graph->InsertEdge( edge.source, edge.target, edge.data ); + _graph->InsertEdge(edge.source, edge.target, edge.data); } data.insertedEdges.clear(); } - //update priorities +// update priorities #pragma omp parallel { - _ThreadData* data = threadData[omp_get_thread_num()]; -#pragma omp for schedule ( guided ) nowait - for ( int position = firstIndependent ; position < last; ++position ) { + _ThreadData *data = threadData[omp_get_thread_num()]; +#pragma omp for schedule(guided) nowait + for (int position = firstIndependent; position < last; ++position) + { NodeID x = remainingNodes[position].id; - _UpdateNeighbours( nodePriority, nodeData, data, x ); + _UpdateNeighbours(nodePriority, nodeData, data, x); } } - //remove contracted nodes from the pool + // remove contracted nodes from the pool numberOfContractedNodes += last - firstIndependent; - remainingNodes.resize( firstIndependent ); - std::vector< _RemainingNodeData>( remainingNodes ).swap( remainingNodes ); + remainingNodes.resize(firstIndependent); + std::vector<_RemainingNodeData>(remainingNodes).swap(remainingNodes); // unsigned maxdegree = 0; // unsigned avgdegree = 0; // unsigned mindegree = UINT_MAX; // unsigned quaddegree = 0; // // for(unsigned i = 0; i < remainingNodes.size(); ++i) { - // unsigned degree = _graph->EndEdges(remainingNodes[i].first) - _graph->BeginEdges(remainingNodes[i].first); + // unsigned degree = _graph->EndEdges(remainingNodes[i].first) - + // _graph->BeginEdges(remainingNodes[i].first); // if(degree > maxdegree) // maxdegree = degree; // if(degree < mindegree) @@ -431,7 +506,9 @@ class Contractor { // avgdegree /= std::max((unsigned)1,(unsigned)remainingNodes.size() ); // quaddegree /= std::max((unsigned)1,(unsigned)remainingNodes.size() ); // - // SimpleLogger().Write() << "rest: " << remainingNodes.size() << ", max: " << maxdegree << ", min: " << mindegree << ", avg: " << avgdegree << ", quad: " << quaddegree; + // SimpleLogger().Write() << "rest: " << remainingNodes.size() << ", max: " + // << maxdegree << ", min: " << mindegree << ", avg: " << avgdegree << ", + // quad: " << quaddegree; p.printStatus(numberOfContractedNodes); } @@ -441,225 +518,283 @@ class Contractor { threadData.clear(); } - template< class Edge > - inline void GetEdges( DeallocatingVector< Edge >& edges ) { - Percent p (_graph->GetNumberOfNodes()); + template inline void GetEdges(DeallocatingVector &edges) + { + Percent p(_graph->GetNumberOfNodes()); SimpleLogger().Write() << "Getting edges of minimized graph"; NodeID numberOfNodes = _graph->GetNumberOfNodes(); - if(_graph->GetNumberOfNodes()) { + if (_graph->GetNumberOfNodes()) + { Edge newEdge; - for ( NodeID node = 0; node < numberOfNodes; ++node ) { + for (NodeID node = 0; node < numberOfNodes; ++node) + { p.printStatus(node); - for ( _DynamicGraph::EdgeIterator edge = _graph->BeginEdges( node ), endEdges = _graph->EndEdges( node ); edge < endEdges; ++edge ) { - const NodeID target = _graph->GetTarget( edge ); - const _DynamicGraph::EdgeData& data = _graph->GetEdgeData( edge ); - if( !oldNodeIDFromNewNodeIDMap.empty() ) { + for (_DynamicGraph::EdgeIterator edge = _graph->BeginEdges(node), + endEdges = _graph->EndEdges(node); + edge < endEdges; + ++edge) + { + const NodeID target = _graph->GetTarget(edge); + const _DynamicGraph::EdgeData &data = _graph->GetEdgeData(edge); + if (!oldNodeIDFromNewNodeIDMap.empty()) + { newEdge.source = oldNodeIDFromNewNodeIDMap[node]; newEdge.target = oldNodeIDFromNewNodeIDMap[target]; - } else { + } + else + { newEdge.source = node; newEdge.target = target; } - BOOST_ASSERT_MSG( - UINT_MAX != newEdge.source, - "Source id invalid" - ); - BOOST_ASSERT_MSG( - UINT_MAX != newEdge.target, - "Target id invalid" - ); + BOOST_ASSERT_MSG(UINT_MAX != newEdge.source, "Source id invalid"); + BOOST_ASSERT_MSG(UINT_MAX != newEdge.target, "Target id invalid"); newEdge.data.distance = data.distance; newEdge.data.shortcut = data.shortcut; - if( - !data.originalViaNodeID && - !oldNodeIDFromNewNodeIDMap.empty() - ) { + if (!data.originalViaNodeID && !oldNodeIDFromNewNodeIDMap.empty()) + { newEdge.data.id = oldNodeIDFromNewNodeIDMap[data.id]; - } else { + } + else + { newEdge.data.id = data.id; } - BOOST_ASSERT_MSG( - newEdge.data.id != INT_MAX, //2^31 - "edge id invalid" - ); + BOOST_ASSERT_MSG(newEdge.data.id != INT_MAX, // 2^31 + "edge id invalid"); newEdge.data.forward = data.forward; newEdge.data.backward = data.backward; - edges.push_back( newEdge ); + edges.push_back(newEdge); } } } _graph.reset(); std::vector().swap(oldNodeIDFromNewNodeIDMap); - BOOST_ASSERT( 0 == oldNodeIDFromNewNodeIDMap.capacity() ); + BOOST_ASSERT(0 == oldNodeIDFromNewNodeIDMap.capacity()); - TemporaryStorage & tempStorage = TemporaryStorage::GetInstance(); - //loads edges of graph before renumbering, no need for further numbering action. + TemporaryStorage &tempStorage = TemporaryStorage::GetInstance(); + // loads edges of graph before renumbering, no need for further numbering action. NodeID start; NodeID target; _DynamicGraph::EdgeData data; Edge restored_edge; - for(unsigned i = 0; i < temp_edge_counter; ++i) { - tempStorage.ReadFromSlot(edge_storage_slot, (char*)&start, sizeof(NodeID)); - tempStorage.ReadFromSlot(edge_storage_slot, (char*)&target, sizeof(NodeID)); - tempStorage.ReadFromSlot(edge_storage_slot, (char*)&data, sizeof(_DynamicGraph::EdgeData)); - restored_edge.source = start; + for (unsigned i = 0; i < temp_edge_counter; ++i) + { + tempStorage.ReadFromSlot(edge_storage_slot, (char *)&start, sizeof(NodeID)); + tempStorage.ReadFromSlot(edge_storage_slot, (char *)&target, sizeof(NodeID)); + tempStorage.ReadFromSlot( + edge_storage_slot, (char *)&data, sizeof(_DynamicGraph::EdgeData)); + restored_edge.source = start; restored_edge.target = target; restored_edge.data.distance = data.distance; restored_edge.data.shortcut = data.shortcut; restored_edge.data.id = data.id; restored_edge.data.forward = data.forward; restored_edge.data.backward = data.backward; - edges.push_back( restored_edge ); + edges.push_back(restored_edge); } tempStorage.DeallocateSlot(edge_storage_slot); } -private: - inline void _Dijkstra( const int maxDistance, const unsigned numTargets, const int maxNodes, _ThreadData* const data, const NodeID middleNode ){ + private: + inline void _Dijkstra(const int maxDistance, + const unsigned numTargets, + const int maxNodes, + _ThreadData *const data, + const NodeID middleNode) + { - _Heap& heap = data->heap; + _Heap &heap = data->heap; int nodes = 0; unsigned targetsFound = 0; - while ( heap.Size() > 0 ) { + while (heap.Size() > 0) + { const NodeID node = heap.DeleteMin(); - const int distance = heap.GetKey( node ); - const short currentHop = heap.GetData( node ).hop+1; + const int distance = heap.GetKey(node); + const short currentHop = heap.GetData(node).hop + 1; - if ( ++nodes > maxNodes ) + if (++nodes > maxNodes) return; - //Destination settled? - if ( distance > maxDistance ) + // Destination settled? + if (distance > maxDistance) return; - if ( heap.GetData( node ).target ) { + if (heap.GetData(node).target) + { ++targetsFound; - if ( targetsFound >= numTargets ) { + if (targetsFound >= numTargets) + { return; } } - //iterate over all edges of node - for ( _DynamicGraph::EdgeIterator edge = _graph->BeginEdges( node ), endEdges = _graph->EndEdges( node ); edge != endEdges; ++edge ) { - const ContractorEdgeData& data = _graph->GetEdgeData( edge ); - if ( !data.forward ){ + // iterate over all edges of node + for (_DynamicGraph::EdgeIterator edge = _graph->BeginEdges(node), + endEdges = _graph->EndEdges(node); + edge != endEdges; + ++edge) + { + const ContractorEdgeData &data = _graph->GetEdgeData(edge); + if (!data.forward) + { continue; } - const NodeID to = _graph->GetTarget( edge ); - if(middleNode == to) { + const NodeID to = _graph->GetTarget(edge); + if (middleNode == to) + { continue; } const int toDistance = distance + data.distance; - //New Node discovered -> Add to Heap + Node Info Storage - if ( !heap.WasInserted( to ) ) { - heap.Insert( to, toDistance, _HeapData(currentHop, false) ); + // New Node discovered -> Add to Heap + Node Info Storage + if (!heap.WasInserted(to)) + { + heap.Insert(to, toDistance, _HeapData(currentHop, false)); } - //Found a shorter Path -> Update distance - else if ( toDistance < heap.GetKey( to ) ) { - heap.DecreaseKey( to, toDistance ); - heap.GetData( to ).hop = currentHop; + // Found a shorter Path -> Update distance + else if (toDistance < heap.GetKey(to)) + { + heap.DecreaseKey(to, toDistance); + heap.GetData(to).hop = currentHop; } } } } - inline float _Evaluate( _ThreadData* const data, _PriorityData* const nodeData, const NodeID node){ + inline float + _Evaluate(_ThreadData *const data, _PriorityData *const nodeData, const NodeID node) + { _ContractionInformation stats; - //perform simulated contraction - _Contract< true> ( data, node, &stats ); + // perform simulated contraction + _Contract(data, node, &stats); // Result will contain the priority float result; - if ( 0 == (stats.edgesDeleted*stats.originalEdgesDeleted) ) + if (0 == (stats.edgesDeleted * stats.originalEdgesDeleted)) result = 1 * nodeData->depth; else - result = 2 * ((( float ) stats.edgesAdded ) / stats.edgesDeleted ) + 4 * ((( float ) stats.originalEdgesAdded ) / stats.originalEdgesDeleted ) + 1 * nodeData->depth; - assert( result >= 0 ); + result = 2 * (((float)stats.edgesAdded) / stats.edgesDeleted) + + 4 * (((float)stats.originalEdgesAdded) / stats.originalEdgesDeleted) + + 1 * nodeData->depth; + assert(result >= 0); return result; } - template< bool Simulate > - inline bool _Contract( _ThreadData* data, NodeID node, _ContractionInformation* stats = NULL ) { - _Heap& heap = data->heap; + template + inline bool _Contract(_ThreadData *data, NodeID node, _ContractionInformation *stats = NULL) + { + _Heap &heap = data->heap; int insertedEdgesSize = data->insertedEdges.size(); - std::vector< _ContractorEdge >& insertedEdges = data->insertedEdges; + std::vector<_ContractorEdge> &insertedEdges = data->insertedEdges; - for ( _DynamicGraph::EdgeIterator inEdge = _graph->BeginEdges( node ), endInEdges = _graph->EndEdges( node ); inEdge != endInEdges; ++inEdge ) { - const ContractorEdgeData& inData = _graph->GetEdgeData( inEdge ); - const NodeID source = _graph->GetTarget( inEdge ); - if ( Simulate ) { - assert( stats != NULL ); + for (_DynamicGraph::EdgeIterator inEdge = _graph->BeginEdges(node), + endInEdges = _graph->EndEdges(node); + inEdge != endInEdges; + ++inEdge) + { + const ContractorEdgeData &inData = _graph->GetEdgeData(inEdge); + const NodeID source = _graph->GetTarget(inEdge); + if (Simulate) + { + assert(stats != NULL); ++stats->edgesDeleted; stats->originalEdgesDeleted += inData.originalEdges; } - if ( !inData.backward ) + if (!inData.backward) continue; heap.Clear(); - heap.Insert( source, 0, _HeapData() ); + heap.Insert(source, 0, _HeapData()); int maxDistance = 0; unsigned numTargets = 0; - for ( _DynamicGraph::EdgeIterator outEdge = _graph->BeginEdges( node ), endOutEdges = _graph->EndEdges( node ); outEdge != endOutEdges; ++outEdge ) { - const ContractorEdgeData& outData = _graph->GetEdgeData( outEdge ); - if ( !outData.forward ) { + for (_DynamicGraph::EdgeIterator outEdge = _graph->BeginEdges(node), + endOutEdges = _graph->EndEdges(node); + outEdge != endOutEdges; + ++outEdge) + { + const ContractorEdgeData &outData = _graph->GetEdgeData(outEdge); + if (!outData.forward) + { continue; } - const NodeID target = _graph->GetTarget( outEdge ); + const NodeID target = _graph->GetTarget(outEdge); const int pathDistance = inData.distance + outData.distance; - maxDistance = std::max( maxDistance, pathDistance ); - if ( !heap.WasInserted( target ) ) { - heap.Insert( target, INT_MAX, _HeapData( 0, true ) ); + maxDistance = std::max(maxDistance, pathDistance); + if (!heap.WasInserted(target)) + { + heap.Insert(target, INT_MAX, _HeapData(0, true)); ++numTargets; } } - if( Simulate ) { - _Dijkstra( maxDistance, numTargets, 1000, data, node ); - } else { - _Dijkstra( maxDistance, numTargets, 2000, data, node ); + if (Simulate) + { + _Dijkstra(maxDistance, numTargets, 1000, data, node); + } + else + { + _Dijkstra(maxDistance, numTargets, 2000, data, node); } - for ( _DynamicGraph::EdgeIterator outEdge = _graph->BeginEdges( node ), endOutEdges = _graph->EndEdges( node ); outEdge != endOutEdges; ++outEdge ) { - const ContractorEdgeData& outData = _graph->GetEdgeData( outEdge ); - if ( !outData.forward ) { + for (_DynamicGraph::EdgeIterator outEdge = _graph->BeginEdges(node), + endOutEdges = _graph->EndEdges(node); + outEdge != endOutEdges; + ++outEdge) + { + const ContractorEdgeData &outData = _graph->GetEdgeData(outEdge); + if (!outData.forward) + { continue; } - const NodeID target = _graph->GetTarget( outEdge ); + const NodeID target = _graph->GetTarget(outEdge); const int pathDistance = inData.distance + outData.distance; - const int distance = heap.GetKey( target ); - if ( pathDistance < distance ) { - if ( Simulate ) { - assert( stats != NULL ); - stats->edgesAdded+=2; - stats->originalEdgesAdded += 2* ( outData.originalEdges + inData.originalEdges ); - } else { + const int distance = heap.GetKey(target); + if (pathDistance < distance) + { + if (Simulate) + { + assert(stats != NULL); + stats->edgesAdded += 2; + stats->originalEdgesAdded += + 2 * (outData.originalEdges + inData.originalEdges); + } + else + { _ContractorEdge newEdge; newEdge.source = source; newEdge.target = target; - newEdge.data = ContractorEdgeData( pathDistance, outData.originalEdges + inData.originalEdges, node/*, 0, inData.turnInstruction*/, true, true, false);; - insertedEdges.push_back( newEdge ); - std::swap( newEdge.source, newEdge.target ); + newEdge.data = + ContractorEdgeData(pathDistance, + outData.originalEdges + inData.originalEdges, + node /*, 0, inData.turnInstruction*/, + true, + true, + false); + ; + insertedEdges.push_back(newEdge); + std::swap(newEdge.source, newEdge.target); newEdge.data.forward = false; newEdge.data.backward = true; - insertedEdges.push_back( newEdge ); + insertedEdges.push_back(newEdge); } } } } - if ( !Simulate ) { - for ( int i = insertedEdgesSize, iend = insertedEdges.size(); i < iend; ++i ) { + if (!Simulate) + { + for (int i = insertedEdgesSize, iend = insertedEdges.size(); i < iend; ++i) + { bool found = false; - for ( int other = i + 1 ; other < iend ; ++other ) { - if ( insertedEdges[other].source != insertedEdges[i].source ) + for (int other = i + 1; other < iend; ++other) + { + if (insertedEdges[other].source != insertedEdges[i].source) continue; - if ( insertedEdges[other].target != insertedEdges[i].target ) + if (insertedEdges[other].target != insertedEdges[i].target) continue; - if ( insertedEdges[other].data.distance != insertedEdges[i].data.distance ) + if (insertedEdges[other].data.distance != insertedEdges[i].data.distance) continue; - if ( insertedEdges[other].data.shortcut != insertedEdges[i].data.shortcut ) + if (insertedEdges[other].data.shortcut != insertedEdges[i].data.shortcut) continue; insertedEdges[other].data.forward |= insertedEdges[i].data.forward; insertedEdges[other].data.backward |= insertedEdges[i].data.backward; @@ -670,45 +805,57 @@ class Contractor { insertedEdges[insertedEdgesSize++] = insertedEdges[i]; } } - insertedEdges.resize( insertedEdgesSize ); + insertedEdges.resize(insertedEdgesSize); } return true; } - inline void _DeleteIncomingEdges( _ThreadData* data, const NodeID node ) { - std::vector< NodeID >& neighbours = data->neighbours; + inline void _DeleteIncomingEdges(_ThreadData *data, const NodeID node) + { + std::vector &neighbours = data->neighbours; neighbours.clear(); - //find all neighbours - for ( _DynamicGraph::EdgeIterator e = _graph->BeginEdges( node ) ; e < _graph->EndEdges( node ) ; ++e ) { - const NodeID u = _graph->GetTarget( e ); - if ( u != node ) - neighbours.push_back( u ); + // find all neighbours + for (_DynamicGraph::EdgeIterator e = _graph->BeginEdges(node); e < _graph->EndEdges(node); + ++e) + { + const NodeID u = _graph->GetTarget(e); + if (u != node) + neighbours.push_back(u); } - //eliminate duplicate entries ( forward + backward edges ) - std::sort( neighbours.begin(), neighbours.end() ); - neighbours.resize( std::unique( neighbours.begin(), neighbours.end() ) - neighbours.begin() ); + // eliminate duplicate entries ( forward + backward edges ) + std::sort(neighbours.begin(), neighbours.end()); + neighbours.resize(std::unique(neighbours.begin(), neighbours.end()) - neighbours.begin()); - for ( int i = 0, e = ( int ) neighbours.size(); i < e; ++i ) { - _graph->DeleteEdgesTo( neighbours[i], node ); + for (int i = 0, e = (int)neighbours.size(); i < e; ++i) + { + _graph->DeleteEdgesTo(neighbours[i], node); } } - inline bool _UpdateNeighbours( std::vector< float > & priorities, std::vector< _PriorityData > & nodeData, _ThreadData* const data, const NodeID node) { - std::vector< NodeID >& neighbours = data->neighbours; + inline bool _UpdateNeighbours(std::vector &priorities, + std::vector<_PriorityData> &nodeData, + _ThreadData *const data, + const NodeID node) + { + std::vector &neighbours = data->neighbours; neighbours.clear(); - //find all neighbours - for ( _DynamicGraph::EdgeIterator e = _graph->BeginEdges( node ), endEdges = _graph->EndEdges( node ) ; e < endEdges ; ++e ) { - const NodeID u = _graph->GetTarget( e ); - if ( u == node ) + // find all neighbours + for (_DynamicGraph::EdgeIterator e = _graph->BeginEdges(node), + endEdges = _graph->EndEdges(node); + e < endEdges; + ++e) + { + const NodeID u = _graph->GetTarget(e); + if (u == node) continue; - neighbours.push_back( u ); - nodeData[u].depth = (std::max)(nodeData[node].depth + 1, nodeData[u].depth ); + neighbours.push_back(u); + nodeData[u].depth = (std::max)(nodeData[node].depth + 1, nodeData[u].depth); } - //eliminate duplicate entries ( forward + backward edges ) - std::sort( neighbours.begin(), neighbours.end() ); - neighbours.resize( std::unique( neighbours.begin(), neighbours.end() ) - neighbours.begin() ); + // eliminate duplicate entries ( forward + backward edges ) + std::sort(neighbours.begin(), neighbours.end()); + neighbours.resize(std::unique(neighbours.begin(), neighbours.end()) - neighbours.begin()); for(const NodeID u : neighbours) { priorities[u] = _Evaluate( data, &( nodeData )[u], u ); @@ -716,40 +863,49 @@ class Contractor { return true; } - inline bool _IsIndependent( const std::vector< float >& priorities/*, const std::vector< _PriorityData >& nodeData*/, _ThreadData* const data, NodeID node ) const { + inline bool _IsIndependent( + const std::vector &priorities /*, const std::vector< _PriorityData >& nodeData*/, + _ThreadData *const data, + NodeID node) const + { const double priority = priorities[node]; - std::vector< NodeID >& neighbours = data->neighbours; + std::vector &neighbours = data->neighbours; neighbours.clear(); - for ( _DynamicGraph::EdgeIterator e = _graph->BeginEdges( node ) ; e < _graph->EndEdges( node ) ; ++e ) { - const NodeID target = _graph->GetTarget( e ); - if(node==target) + for (_DynamicGraph::EdgeIterator e = _graph->BeginEdges(node); e < _graph->EndEdges(node); + ++e) + { + const NodeID target = _graph->GetTarget(e); + if (node == target) continue; const double targetPriority = priorities[target]; - assert( targetPriority >= 0 ); - //found a neighbour with lower priority? - if ( priority > targetPriority ) + assert(targetPriority >= 0); + // found a neighbour with lower priority? + if (priority > targetPriority) return false; - //tie breaking - if ( std::abs(priority - targetPriority) < std::numeric_limits::epsilon() && bias(node, target) ) { + // tie breaking + if (std::abs(priority - targetPriority) < std::numeric_limits::epsilon() && + bias(node, target)) + { return false; } // TODO: C++11 copy_if with lambda - neighbours.push_back( target ); + neighbours.push_back(target); } - std::sort( neighbours.begin(), neighbours.end() ); - neighbours.resize( std::unique( neighbours.begin(), neighbours.end() ) - neighbours.begin() ); + std::sort(neighbours.begin(), neighbours.end()); + neighbours.resize(std::unique(neighbours.begin(), neighbours.end()) - neighbours.begin()); - //examine all neighbours that are at most 2 hops away - for(const NodeID u : neighbours) { - for ( _DynamicGraph::EdgeIterator e = _graph->BeginEdges( u ) ; e < _graph->EndEdges( u ) ; ++e ) { - const NodeID target = _graph->GetTarget( e ); - if(node==target) - { + // examine all neighbours that are at most 2 hops away + for(const NodeID u : neighbours) + { + for (_DynamicGraph::EdgeIterator e = _graph->BeginEdges(u); e < _graph->EndEdges(u); + ++e) + { + const NodeID target = _graph->GetTarget(e); + if (node == target) continue; - } const double targetPriority = priorities[target]; assert( targetPriority >= 0 ); @@ -769,17 +925,19 @@ class Contractor { /** * This bias function takes up 22 assembly instructions in total on X86 */ - inline bool bias(const NodeID a, const NodeID b) const { + inline bool bias(const NodeID a, const NodeID b) const + { unsigned short hasha = fastHash(a); unsigned short hashb = fastHash(b); - //The compiler optimizes that to conditional register flags but without branching statements! - if(hasha != hashb) + // The compiler optimizes that to conditional register flags but without branching + // statements! + if (hasha != hashb) return hasha < hashb; return a < b; } - boost::shared_ptr<_DynamicGraph> _graph; + std::shared_ptr<_DynamicGraph> _graph; std::vector<_DynamicGraph::InputEdge> contractedEdges; unsigned edge_storage_slot; uint64_t temp_edge_counter; diff --git a/Contractor/EdgeBasedGraphFactory.cpp b/Contractor/EdgeBasedGraphFactory.cpp index 7629660f95a..b138a9c8a4a 100644 --- a/Contractor/EdgeBasedGraphFactory.cpp +++ b/Contractor/EdgeBasedGraphFactory.cpp @@ -25,309 +25,110 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ - #include "EdgeBasedGraphFactory.h" #include "../Util/ComputeAngle.h" +#include "../Util/TimingUtil.h" +#include "BFSComponentExplorer.h" #include #include -#include #include #include #include EdgeBasedGraphFactory::EdgeBasedGraphFactory( - int number_of_nodes, - std::vector & input_edge_list, - std::vector & barrier_node_list, - std::vector & traffic_light_node_list, - std::vector & input_restrictions_list, - std::vector & m_node_info_list, - SpeedProfileProperties & speed_profile -) : speed_profile(speed_profile), - m_turn_restrictions_count(0), - m_number_of_edge_based_nodes(std::numeric_limits::max()), - m_node_info_list(m_node_info_list), - max_id(0) + const std::shared_ptr &node_based_graph, + std::unique_ptr restriction_map, + std::vector &barrier_node_list, + std::vector &traffic_light_node_list, + std::vector &m_node_info_list, + SpeedProfileProperties &speed_profile) + : speed_profile(speed_profile), + m_number_of_edge_based_nodes(std::numeric_limits::max()), + m_node_info_list(m_node_info_list), m_node_based_graph(node_based_graph), + m_restriction_map(std::move(restriction_map)), max_id(0) { - BOOST_FOREACH(const TurnRestriction & restriction, input_restrictions_list) { - std::pair restriction_source = - std::make_pair(restriction.fromNode, restriction.viaNode); - unsigned index; - RestrictionMap::iterator restriction_iter; - restriction_iter = m_restriction_map.find(restriction_source); - if(restriction_iter == m_restriction_map.end()) { - index = m_restriction_bucket_list.size(); - m_restriction_bucket_list.resize(index+1); - m_restriction_map.emplace(restriction_source, index); - } else { - index = restriction_iter->second; - //Map already contains an is_only_*-restriction - if(m_restriction_bucket_list.at(index).begin()->second) { - continue; - } else if(restriction.flags.isOnly) { - //We are going to insert an is_only_*-restriction. There can be only one. - m_turn_restrictions_count -= m_restriction_bucket_list.at(index).size(); - m_restriction_bucket_list.at(index).clear(); - } - } - ++m_turn_restrictions_count; - m_restriction_bucket_list.at(index).push_back( - std::make_pair( restriction.toNode, restriction.flags.isOnly) - ); - } - m_barrier_nodes.insert( - barrier_node_list.begin(), - barrier_node_list.end() - ); - - m_traffic_lights.insert( - traffic_light_node_list.begin(), - traffic_light_node_list.end() - ); - - std::sort( input_edge_list.begin(), input_edge_list.end() ); - - //TODO: remove duplicate edges - - DeallocatingVector edges_list; - NodeBasedEdge edge; - BOOST_FOREACH(const ImportEdge & import_edge, input_edge_list) { - - if( !import_edge.isForward() ) { - edge.source = import_edge.target(); - edge.target = import_edge.source(); - edge.data.backward = import_edge.isForward(); - edge.data.forward = import_edge.isBackward(); - } else { - edge.source = import_edge.source(); - edge.target = import_edge.target(); - edge.data.forward = import_edge.isForward(); - edge.data.backward = import_edge.isBackward(); - } - - if( edge.source == edge.target ) { - continue; - } + // insert into unordered sets for fast lookup + m_barrier_nodes.insert(barrier_node_list.begin(), barrier_node_list.end()); - edge.data.distance = (std::max)((int)import_edge.weight(), 1 ); - BOOST_ASSERT( edge.data.distance > 0 ); - edge.data.shortcut = false; - edge.data.roundabout = import_edge.isRoundabout(); - edge.data.ignore_in_grid = import_edge.ignoreInGrid(); - edge.data.nameID = import_edge.name(); - edge.data.type = import_edge.type(); - edge.data.isAccessRestricted = import_edge.isAccessRestricted(); - edge.data.contraFlow = import_edge.isContraFlow(); - edges_list.push_back( edge ); - - if( !import_edge.IsSplit() ) { - using std::swap; //enable ADL - swap( edge.source, edge.target ); - edge.data.SwapDirectionFlags(); - edges_list.push_back( edge ); - } - } - - std::vector().swap(input_edge_list); - std::sort( edges_list.begin(), edges_list.end() ); - - m_node_based_graph = boost::make_shared( - number_of_nodes, - edges_list - ); - DeallocatingVector().swap(edges_list); - BOOST_ASSERT(0 == edges_list.size() ); + m_traffic_lights.insert(traffic_light_node_list.begin(), traffic_light_node_list.end()); } -void EdgeBasedGraphFactory::FixupArrivingTurnRestriction( - const NodeID u, - const NodeID v, - const NodeID w -) { - BOOST_ASSERT( u != std::numeric_limits::max() ); - BOOST_ASSERT( v != std::numeric_limits::max() ); - BOOST_ASSERT( w != std::numeric_limits::max() ); - - std::vector predecessors; - for( - EdgeID current_edge_id = m_node_based_graph->BeginEdges(u); - current_edge_id < m_node_based_graph->EndEdges(u); - ++current_edge_id - ) { - const EdgeData & edge_data = m_node_based_graph->GetEdgeData(current_edge_id); - const NodeID target = m_node_based_graph->GetTarget(current_edge_id); - if( edge_data.backward && ( v != target) ) { - predecessors.push_back(target); - } - } - BOOST_FOREACH( const NodeID x, predecessors ) { - const std::pair restr_start = std::make_pair(x,u); - RestrictionMap::const_iterator restriction_iterator; - restriction_iterator = m_restriction_map.find( restr_start ); - if( restriction_iterator != m_restriction_map.end() ) { - const unsigned index = restriction_iterator->second; - BOOST_FOREACH( - RestrictionTarget & restriction_target, - m_restriction_bucket_list.at(index) - ) { - if( v == restriction_target.first ) { - restriction_target.first = w; - } - } - } - } -} - -void EdgeBasedGraphFactory::FixupStartingTurnRestriction( - const NodeID u, - const NodeID v, - const NodeID w -) { - BOOST_ASSERT( u != std::numeric_limits::max() ); - BOOST_ASSERT( v != std::numeric_limits::max() ); - BOOST_ASSERT( w != std::numeric_limits::max() ); - - const std::pair old_start = std::make_pair(v,w); - RestrictionMap::const_iterator restriction_iterator; - restriction_iterator = m_restriction_map.find( old_start ); - if( restriction_iterator != m_restriction_map.end() ) { - const unsigned index = restriction_iterator->second; - // remove old restriction start (v,w) - m_restriction_map.erase( restriction_iterator ); - - // insert new restriction start (u,w) (point to index) - const std::pair new_start = std::make_pair(u,w); - m_restriction_map.insert( std::make_pair(new_start, index) ); - } -} - -void EdgeBasedGraphFactory::GetEdgeBasedEdges( - DeallocatingVector< EdgeBasedEdge >& output_edge_list -) { - BOOST_ASSERT_MSG( - 0 == output_edge_list.size(), - "Vector is not empty" - ); +void EdgeBasedGraphFactory::GetEdgeBasedEdges(DeallocatingVector &output_edge_list) +{ + BOOST_ASSERT_MSG(0 == output_edge_list.size(), "Vector is not empty"); m_edge_based_edge_list.swap(output_edge_list); } -void EdgeBasedGraphFactory::GetEdgeBasedNodes( std::vector & nodes) { +void EdgeBasedGraphFactory::GetEdgeBasedNodes(std::vector &nodes) +{ #ifndef NDEBUG - BOOST_FOREACH(const EdgeBasedNode & node, m_edge_based_node_list){ + BOOST_FOREACH (const EdgeBasedNode &node, m_edge_based_node_list) + { - BOOST_ASSERT( m_node_info_list.at(node.u).lat != INT_MAX ); - BOOST_ASSERT( m_node_info_list.at(node.u).lon != INT_MAX ); - BOOST_ASSERT( m_node_info_list.at(node.v).lon != INT_MAX ); - BOOST_ASSERT( m_node_info_list.at(node.v).lat != INT_MAX ); + BOOST_ASSERT(m_node_info_list.at(node.u).lat != INT_MAX); + BOOST_ASSERT(m_node_info_list.at(node.u).lon != INT_MAX); + BOOST_ASSERT(m_node_info_list.at(node.v).lon != INT_MAX); + BOOST_ASSERT(m_node_info_list.at(node.v).lat != INT_MAX); } #endif nodes.swap(m_edge_based_node_list); } -NodeID EdgeBasedGraphFactory::CheckForEmanatingIsOnlyTurn( - const NodeID u, - const NodeID v -) const { - BOOST_ASSERT( u != std::numeric_limits::max() ); - BOOST_ASSERT( v != std::numeric_limits::max() ); - const std::pair restriction_source = std::make_pair(u, v); - RestrictionMap::const_iterator restriction_iter; - restriction_iter = m_restriction_map.find(restriction_source); - if (restriction_iter != m_restriction_map.end()) { - const unsigned index = restriction_iter->second; - BOOST_FOREACH( - const RestrictionSource & restriction_target, - m_restriction_bucket_list.at(index) - ) { - if(restriction_target.second) { - return restriction_target.first; - } - } - } - return std::numeric_limits::max(); -} - -bool EdgeBasedGraphFactory::CheckIfTurnIsRestricted( - const NodeID u, - const NodeID v, - const NodeID w -) const { - BOOST_ASSERT( u != std::numeric_limits::max() ); - BOOST_ASSERT( v != std::numeric_limits::max() ); - BOOST_ASSERT( w != std::numeric_limits::max() ); - - const std::pair restriction_source = std::make_pair(u, v); - RestrictionMap::const_iterator restriction_iter; - restriction_iter = m_restriction_map.find(restriction_source); - if (restriction_iter != m_restriction_map.end()) { - const unsigned index = restriction_iter->second; - BOOST_FOREACH( - const RestrictionTarget & restriction_target, - m_restriction_bucket_list.at(index) - ) { - if( - ( w == restriction_target.first ) && // target found - ( !restriction_target.second ) // and not an only_-restr. - ) { - return true; - } - } - } - return false; -} - -void EdgeBasedGraphFactory::InsertEdgeBasedNode( - NodeIterator u, - NodeIterator v, - EdgeIterator e1, - bool belongs_to_tiny_cc -) { +void EdgeBasedGraphFactory::InsertEdgeBasedNode(NodeIterator u, + NodeIterator v, + EdgeIterator e1, + bool belongs_to_tiny_cc) +{ // merge edges together into one EdgeBasedNode - BOOST_ASSERT( u != SPECIAL_NODEID ); - BOOST_ASSERT( v != SPECIAL_NODEID ); - BOOST_ASSERT( e1 != SPECIAL_EDGEID ); + BOOST_ASSERT(u != SPECIAL_NODEID); + BOOST_ASSERT(v != SPECIAL_NODEID); + BOOST_ASSERT(e1 != SPECIAL_EDGEID); #ifndef NDEBUG // find forward edge id and const EdgeID e1b = m_node_based_graph->FindEdge(u, v); - BOOST_ASSERT( e1 == e1b ); + BOOST_ASSERT(e1 == e1b); #endif - BOOST_ASSERT( e1 != SPECIAL_EDGEID ); - const EdgeData & forward_data = m_node_based_graph->GetEdgeData(e1); + BOOST_ASSERT(e1 != SPECIAL_EDGEID); + const EdgeData &forward_data = m_node_based_graph->GetEdgeData(e1); // find reverse edge id and const EdgeID e2 = m_node_based_graph->FindEdge(v, u); #ifndef NDEBUG - if ( e2 == m_node_based_graph->EndEdges(v) ) { + if (e2 == m_node_based_graph->EndEdges(v)) + { SimpleLogger().Write(logWARNING) << "Did not find edge (" << v << "," << u << ")"; } #endif - BOOST_ASSERT( e2 != SPECIAL_EDGEID ); - BOOST_ASSERT( e2 < m_node_based_graph->EndEdges(v) ); - const EdgeData & reverse_data = m_node_based_graph->GetEdgeData(e2); - - if( - forward_data.edgeBasedNodeID == SPECIAL_NODEID && - reverse_data.edgeBasedNodeID == SPECIAL_NODEID - ) { + BOOST_ASSERT(e2 != SPECIAL_EDGEID); + BOOST_ASSERT(e2 < m_node_based_graph->EndEdges(v)); + const EdgeData &reverse_data = m_node_based_graph->GetEdgeData(e2); + + if (forward_data.edgeBasedNodeID == SPECIAL_NODEID && + reverse_data.edgeBasedNodeID == SPECIAL_NODEID) + { return; } - BOOST_ASSERT( m_geometry_compressor.HasEntryForID(e1) == m_geometry_compressor.HasEntryForID(e2) ); - if( m_geometry_compressor.HasEntryForID(e1) ) { + BOOST_ASSERT(m_geometry_compressor.HasEntryForID(e1) == + m_geometry_compressor.HasEntryForID(e2)); + if (m_geometry_compressor.HasEntryForID(e1)) + { - BOOST_ASSERT( m_geometry_compressor.HasEntryForID(e2) ); + BOOST_ASSERT(m_geometry_compressor.HasEntryForID(e2)); // reconstruct geometry and put in each individual edge with its offset - const std::vector & forward_geometry = m_geometry_compressor.GetBucketReference(e1); - const std::vector & reverse_geometry = m_geometry_compressor.GetBucketReference(e2); - BOOST_ASSERT( forward_geometry.size() == reverse_geometry.size() ); - BOOST_ASSERT( 0 != forward_geometry.size() ); + const std::vector &forward_geometry = + m_geometry_compressor.GetBucketReference(e1); + const std::vector &reverse_geometry = + m_geometry_compressor.GetBucketReference(e2); + BOOST_ASSERT(forward_geometry.size() == reverse_geometry.size()); + BOOST_ASSERT(0 != forward_geometry.size()); // reconstruct bidirectional edge with individual weights and put each into the NN index @@ -343,20 +144,21 @@ void EdgeBasedGraphFactory::InsertEdgeBasedNode( forward_dist_prefix_sum[i] = temp_sum; temp_sum += forward_geometry[i].second; - BOOST_ASSERT( forward_data.distance >= temp_sum ); + BOOST_ASSERT(forward_data.distance >= temp_sum); } temp_sum = 0; - for( unsigned i = 0; i < reverse_geometry.size(); ++i ) { - temp_sum += reverse_geometry[reverse_geometry.size()-1-i].second; + for (unsigned i = 0; i < reverse_geometry.size(); ++i) + { + temp_sum += reverse_geometry[reverse_geometry.size() - 1 - i].second; reverse_dist_prefix_sum[i] = reverse_data.distance - temp_sum; - BOOST_ASSERT( reverse_data.distance >= temp_sum ); + BOOST_ASSERT(reverse_data.distance >= temp_sum); } - BOOST_ASSERT( forward_geometry.size() == reverse_geometry.size() ); + BOOST_ASSERT(forward_geometry.size() == reverse_geometry.size()); const unsigned geometry_size = forward_geometry.size(); - BOOST_ASSERT( geometry_size > 1 ); + BOOST_ASSERT(geometry_size > 1); NodeID current_edge_start_coordinate_id = u; if (forward_data.edgeBasedNodeID != SPECIAL_NODEID) @@ -369,105 +171,121 @@ void EdgeBasedGraphFactory::InsertEdgeBasedNode( } // traverse arrays from start and end respectively - for( unsigned i = 0; i < geometry_size; ++i ) { - BOOST_ASSERT( current_edge_start_coordinate_id == reverse_geometry[geometry_size-1-i].first ); + for (unsigned i = 0; i < geometry_size; ++i) + { + BOOST_ASSERT(current_edge_start_coordinate_id == + reverse_geometry[geometry_size - 1 - i].first); const NodeID current_edge_target_coordinate_id = forward_geometry[i].first; - BOOST_ASSERT( current_edge_target_coordinate_id != current_edge_start_coordinate_id); + BOOST_ASSERT(current_edge_target_coordinate_id != current_edge_start_coordinate_id); // build edges - m_edge_based_node_list.push_back( - EdgeBasedNode( - forward_data.edgeBasedNodeID, - reverse_data.edgeBasedNodeID, - current_edge_start_coordinate_id, - current_edge_target_coordinate_id, - forward_data.nameID, - forward_geometry[i].second, - reverse_geometry[i].second, - forward_dist_prefix_sum[i], - reverse_dist_prefix_sum[i], - m_geometry_compressor.GetPositionForID(e1), - i, - belongs_to_tiny_cc - ) - ); + m_edge_based_node_list.emplace_back( + EdgeBasedNode(forward_data.edgeBasedNodeID, + reverse_data.edgeBasedNodeID, + current_edge_start_coordinate_id, + current_edge_target_coordinate_id, + forward_data.nameID, + forward_geometry[i].second, + reverse_geometry[i].second, + forward_dist_prefix_sum[i], + reverse_dist_prefix_sum[i], + m_geometry_compressor.GetPositionForID(e1), + i, + belongs_to_tiny_cc)); current_edge_start_coordinate_id = current_edge_target_coordinate_id; - BOOST_ASSERT( m_edge_based_node_list.back().IsCompressed() ); + BOOST_ASSERT(m_edge_based_node_list.back().IsCompressed()); - BOOST_ASSERT( - u != m_edge_based_node_list.back().u || - v != m_edge_based_node_list.back().v - ); + BOOST_ASSERT(u != m_edge_based_node_list.back().u || + v != m_edge_based_node_list.back().v); - BOOST_ASSERT( - u != m_edge_based_node_list.back().v || - v != m_edge_based_node_list.back().u - ); + BOOST_ASSERT(u != m_edge_based_node_list.back().v || + v != m_edge_based_node_list.back().u); } - BOOST_ASSERT( current_edge_start_coordinate_id == v ); - BOOST_ASSERT( m_edge_based_node_list.back().IsCompressed() ); - - } else { - BOOST_ASSERT( !m_geometry_compressor.HasEntryForID(e2) ); + BOOST_ASSERT(current_edge_start_coordinate_id == v); + BOOST_ASSERT(m_edge_based_node_list.back().IsCompressed()); + } + else + { + BOOST_ASSERT(!m_geometry_compressor.HasEntryForID(e2)); - if( forward_data.edgeBasedNodeID != std::numeric_limits::max() ) { - BOOST_ASSERT( forward_data.forward ); + if (forward_data.edgeBasedNodeID != SPECIAL_NODEID) + { + BOOST_ASSERT(forward_data.forward); } - if( reverse_data.edgeBasedNodeID != std::numeric_limits::max() ) { - BOOST_ASSERT( reverse_data.forward ); + if (reverse_data.edgeBasedNodeID != SPECIAL_NODEID) + { + BOOST_ASSERT(reverse_data.forward); } - if( forward_data.edgeBasedNodeID == std::numeric_limits::max() ) { - BOOST_ASSERT( !forward_data.forward ); + if (forward_data.edgeBasedNodeID == SPECIAL_NODEID) + { + BOOST_ASSERT(!forward_data.forward); } - if( reverse_data.edgeBasedNodeID == std::numeric_limits::max() ) { - BOOST_ASSERT( !reverse_data.forward ); + if (reverse_data.edgeBasedNodeID == SPECIAL_NODEID) + { + BOOST_ASSERT(!reverse_data.forward); } - BOOST_ASSERT( - forward_data.edgeBasedNodeID != SPECIAL_NODEID || - reverse_data.edgeBasedNodeID != SPECIAL_NODEID - ); - - //TODO C++11: emplace_back with - m_edge_based_node_list.push_back( - EdgeBasedNode( - forward_data.edgeBasedNodeID, - reverse_data.edgeBasedNodeID, - u, - v, - forward_data.nameID, - forward_data.distance, - reverse_data.distance, - 0, - 0, - SPECIAL_EDGEID, - 0, - belongs_to_tiny_cc - ) - ); - BOOST_ASSERT( !m_edge_based_node_list.back().IsCompressed() ); + BOOST_ASSERT(forward_data.edgeBasedNodeID != SPECIAL_NODEID || + reverse_data.edgeBasedNodeID != SPECIAL_NODEID); + + m_edge_based_node_list.emplace_back(EdgeBasedNode(forward_data.edgeBasedNodeID, + reverse_data.edgeBasedNodeID, + u, + v, + forward_data.nameID, + forward_data.distance, + reverse_data.distance, + 0, + 0, + SPECIAL_EDGEID, + 0, + belongs_to_tiny_cc)); + BOOST_ASSERT(!m_edge_based_node_list.back().IsCompressed()); } } - void EdgeBasedGraphFactory::FlushVectorToStream( - std::ofstream & edge_data_file, - std::vector & original_edge_data_vector -) const { - edge_data_file.write( - (char*)&(original_edge_data_vector[0]), - original_edge_data_vector.size()*sizeof(OriginalEdgeData) - ); + std::ofstream &edge_data_file, std::vector &original_edge_data_vector) const +{ + edge_data_file.write((char *)&(original_edge_data_vector[0]), + original_edge_data_vector.size() * sizeof(OriginalEdgeData)); original_edge_data_vector.clear(); } -void EdgeBasedGraphFactory::Run( - const std::string & original_edge_data_filename, - const std::string & geometry_filename, - lua_State *lua_state -) { +void EdgeBasedGraphFactory::Run(const std::string &original_edge_data_filename, + const std::string &geometry_filename, + lua_State *lua_state) +{ + + TIMER_START(geometry); + CompressGeometry(); + TIMER_STOP(geometry); + + TIMER_START(renumber); + RenumberEdges(); + TIMER_STOP(renumber); + + TIMER_START(generate_nodes); + GenerateEdgeExpandedNodes(); + TIMER_STOP(generate_nodes); + + TIMER_START(generate_edges); + GenerateEdgeExpandedEdges(original_edge_data_filename, lua_state); + TIMER_STOP(generate_edges); + + m_geometry_compressor.SerializeInternalVector(geometry_filename); + + SimpleLogger().Write() << "Timing statistics for edge-expanded graph:"; + SimpleLogger().Write() << "Geometry compression: " << TIMER_SEC(geometry) << "s"; + SimpleLogger().Write() << "Renumbering edges: " << TIMER_SEC(renumber) << "s"; + SimpleLogger().Write() << "Generating nodes: " << TIMER_SEC(generate_nodes) << "s"; + SimpleLogger().Write() << "Generating edges: " << TIMER_SEC(generate_edges) << "s"; +} + +void EdgeBasedGraphFactory::CompressGeometry() +{ SimpleLogger().Write() << "Removing graph geometry while preserving topology"; const unsigned original_number_of_nodes = m_node_based_graph->GetNumberOfNodes(); @@ -476,79 +294,84 @@ void EdgeBasedGraphFactory::Run( Percent p(original_number_of_nodes); unsigned removed_node_count = 0; - for( NodeID v = 0; v < original_number_of_nodes; ++v ) { + for (NodeID v = 0; v < original_number_of_nodes; ++v) + { p.printStatus(v); // only contract degree 2 vertices - if( 2 != m_node_based_graph->GetOutDegree(v) ) { + if (2 != m_node_based_graph->GetOutDegree(v)) + { continue; } // don't contract barrier node - if( m_barrier_nodes.end() != m_barrier_nodes.find(v) ) { + if (m_barrier_nodes.end() != m_barrier_nodes.find(v)) + { continue; } - const bool reverse_edge_order = !(m_node_based_graph->GetEdgeData(m_node_based_graph->BeginEdges(v)).forward); + const bool reverse_edge_order = + !(m_node_based_graph->GetEdgeData(m_node_based_graph->BeginEdges(v)).forward); const EdgeIterator forward_e2 = m_node_based_graph->BeginEdges(v) + reverse_edge_order; - BOOST_ASSERT( std::numeric_limits::max() != forward_e2 ); + BOOST_ASSERT(SPECIAL_EDGEID != forward_e2); const EdgeIterator reverse_e2 = m_node_based_graph->BeginEdges(v) + 1 - reverse_edge_order; - BOOST_ASSERT( std::numeric_limits::max() != reverse_e2 ); + BOOST_ASSERT(SPECIAL_EDGEID != reverse_e2); - const EdgeData & fwd_edge_data2 = m_node_based_graph->GetEdgeData(forward_e2); - const EdgeData & rev_edge_data2 = m_node_based_graph->GetEdgeData(reverse_e2); + const EdgeData &fwd_edge_data2 = m_node_based_graph->GetEdgeData(forward_e2); + const EdgeData &rev_edge_data2 = m_node_based_graph->GetEdgeData(reverse_e2); const NodeIterator w = m_node_based_graph->GetTarget(forward_e2); - BOOST_ASSERT( std::numeric_limits::max() != w ); - BOOST_ASSERT( v != w ); + BOOST_ASSERT(SPECIAL_NODEID != w); + BOOST_ASSERT(v != w); const NodeIterator u = m_node_based_graph->GetTarget(reverse_e2); - BOOST_ASSERT( std::numeric_limits::max() != u ); - BOOST_ASSERT( u != v ); + BOOST_ASSERT(SPECIAL_NODEID != u); + BOOST_ASSERT(u != v); const EdgeIterator forward_e1 = m_node_based_graph->FindEdge(u, v); - BOOST_ASSERT( m_node_based_graph->EndEdges(u) != forward_e1 ); - BOOST_ASSERT( std::numeric_limits::max() != forward_e1 ); - BOOST_ASSERT( v == m_node_based_graph->GetTarget(forward_e1)); + BOOST_ASSERT(m_node_based_graph->EndEdges(u) != forward_e1); + BOOST_ASSERT(SPECIAL_EDGEID != forward_e1); + BOOST_ASSERT(v == m_node_based_graph->GetTarget(forward_e1)); const EdgeIterator reverse_e1 = m_node_based_graph->FindEdge(w, v); - BOOST_ASSERT( std::numeric_limits::max() != reverse_e1 ); - BOOST_ASSERT( v == m_node_based_graph->GetTarget(reverse_e1)); + BOOST_ASSERT(SPECIAL_EDGEID != reverse_e1); + BOOST_ASSERT(v == m_node_based_graph->GetTarget(reverse_e1)); - const EdgeData & fwd_edge_data1 = m_node_based_graph->GetEdgeData(forward_e1); - const EdgeData & rev_edge_data1 = m_node_based_graph->GetEdgeData(reverse_e1); + const EdgeData &fwd_edge_data1 = m_node_based_graph->GetEdgeData(forward_e1); + const EdgeData &rev_edge_data1 = m_node_based_graph->GetEdgeData(reverse_e1); - if( - ( m_node_based_graph->FindEdge(u, w) != m_node_based_graph->EndEdges(u) ) || - ( m_node_based_graph->FindEdge(w, u) != m_node_based_graph->EndEdges(w) ) - ) { + if ((m_node_based_graph->FindEdge(u, w) != m_node_based_graph->EndEdges(u)) || + (m_node_based_graph->FindEdge(w, u) != m_node_based_graph->EndEdges(w))) + { continue; } - if ( //TODO: rename to IsCompatibleTo - fwd_edge_data1.IsEqualTo(fwd_edge_data2) && - rev_edge_data1.IsEqualTo(rev_edge_data2) - ) { - //Get distances before graph is modified + if ( // TODO: rename to IsCompatibleTo + fwd_edge_data1.IsEqualTo(fwd_edge_data2) && rev_edge_data1.IsEqualTo(rev_edge_data2)) + { + // Get distances before graph is modified const int forward_weight1 = m_node_based_graph->GetEdgeData(forward_e1).distance; const int forward_weight2 = m_node_based_graph->GetEdgeData(forward_e2).distance; - BOOST_ASSERT( 0 != forward_weight1 ); - BOOST_ASSERT( 0 != forward_weight2 ); + BOOST_ASSERT(0 != forward_weight1); + BOOST_ASSERT(0 != forward_weight2); const int reverse_weight1 = m_node_based_graph->GetEdgeData(reverse_e1).distance; const int reverse_weight2 = m_node_based_graph->GetEdgeData(reverse_e2).distance; - BOOST_ASSERT( 0 != reverse_weight1 ); - BOOST_ASSERT( 0 != forward_weight2 ); + BOOST_ASSERT(0 != reverse_weight1); + BOOST_ASSERT(0 != forward_weight2); - const bool add_traffic_signal_penalty = (m_traffic_lights.find(v) != m_traffic_lights.end()); + const bool add_traffic_signal_penalty = + (m_traffic_lights.find(v) != m_traffic_lights.end()); // add weight of e2's to e1 m_node_based_graph->GetEdgeData(forward_e1).distance += fwd_edge_data2.distance; m_node_based_graph->GetEdgeData(reverse_e1).distance += rev_edge_data2.distance; if (add_traffic_signal_penalty) { - m_node_based_graph->GetEdgeData(forward_e1).distance += speed_profile.trafficSignalPenalty; - m_node_based_graph->GetEdgeData(reverse_e1).distance += speed_profile.trafficSignalPenalty; + m_node_based_graph->GetEdgeData(forward_e1).distance += + speed_profile.trafficSignalPenalty; + m_node_based_graph->GetEdgeData(reverse_e1).distance += + speed_profile.trafficSignalPenalty; } // extend e1's to targets of e2's @@ -560,11 +383,11 @@ void EdgeBasedGraphFactory::Run( m_node_based_graph->DeleteEdge(v, reverse_e2); // update any involved turn restrictions - FixupStartingTurnRestriction( u, v, w ); - FixupArrivingTurnRestriction( u, v, w ); + m_restriction_map->FixupStartingTurnRestriction(u, v, w); + m_restriction_map->FixupArrivingTurnRestriction(u, v, w); - FixupStartingTurnRestriction( w, v, u ); - FixupArrivingTurnRestriction( w, v, u ); + m_restriction_map->FixupStartingTurnRestriction(w, v, u); + m_restriction_map->FixupArrivingTurnRestriction(w, v, u); // store compressed geometry in container m_geometry_compressor.CompressEdge( @@ -572,24 +395,21 @@ void EdgeBasedGraphFactory::Run( forward_e2, v, w, - forward_weight1 + (add_traffic_signal_penalty ? speed_profile.trafficSignalPenalty :0), - forward_weight2 - ); + forward_weight1 + + (add_traffic_signal_penalty ? speed_profile.trafficSignalPenalty : 0), + forward_weight2); m_geometry_compressor.CompressEdge( reverse_e1, reverse_e2, v, u, - reverse_weight1 , - reverse_weight2 + (add_traffic_signal_penalty ? speed_profile.trafficSignalPenalty :0) - ); + reverse_weight1, + reverse_weight2 + + (add_traffic_signal_penalty ? speed_profile.trafficSignalPenalty : 0)); ++removed_node_count; - BOOST_ASSERT - ( - m_node_based_graph->GetEdgeData(forward_e1).nameID == - m_node_based_graph->GetEdgeData(reverse_e1).nameID - ); + BOOST_ASSERT(m_node_based_graph->GetEdgeData(forward_e1).nameID == + m_node_based_graph->GetEdgeData(reverse_e1).nameID); } } SimpleLogger().Write() << "removed " << removed_node_count << " nodes"; @@ -597,158 +417,177 @@ void EdgeBasedGraphFactory::Run( unsigned new_node_count = 0; unsigned new_edge_count = 0; - for( unsigned i = 0; i < m_node_based_graph->GetNumberOfNodes(); ++i ) { - if( m_node_based_graph->GetOutDegree(i) > 0 ) { + for (unsigned i = 0; i < m_node_based_graph->GetNumberOfNodes(); ++i) + { + if (m_node_based_graph->GetOutDegree(i) > 0) + { ++new_node_count; new_edge_count += (m_node_based_graph->EndEdges(i) - m_node_based_graph->BeginEdges(i)); } } SimpleLogger().Write() << "new nodes: " << new_node_count << ", edges " << new_edge_count; - SimpleLogger().Write() << "Node compression ratio: " << new_node_count/(double)original_number_of_nodes; - SimpleLogger().Write() << "Edge compression ratio: " << new_edge_count/(double)original_number_of_edges; + SimpleLogger().Write() << "Node compression ratio: " + << new_node_count / (double)original_number_of_nodes; + SimpleLogger().Write() << "Edge compression ratio: " + << new_edge_count / (double)original_number_of_edges; +} +/** + * Writes the id of the edge in the edge expanded graph (into the egde in the node based graph) + */ +void EdgeBasedGraphFactory::RenumberEdges() +{ // renumber edge based node IDs unsigned numbered_edges_count = 0; - for(NodeID current_node = 0; current_node < m_node_based_graph->GetNumberOfNodes(); ++current_node) { - for(EdgeIterator current_edge = m_node_based_graph->BeginEdges(current_node); current_edge < m_node_based_graph->EndEdges(current_node); ++current_edge) { - EdgeData & edge_data = m_node_based_graph->GetEdgeData(current_edge); - if( !edge_data.forward ) { + for (NodeID current_node = 0; current_node < m_node_based_graph->GetNumberOfNodes(); + ++current_node) + { + for (EdgeIterator current_edge = m_node_based_graph->BeginEdges(current_node); + current_edge < m_node_based_graph->EndEdges(current_node); + ++current_edge) + { + EdgeData &edge_data = m_node_based_graph->GetEdgeData(current_edge); + if (!edge_data.forward) + { continue; } - BOOST_ASSERT( numbered_edges_count < m_node_based_graph->GetNumberOfEdges() ); + BOOST_ASSERT(numbered_edges_count < m_node_based_graph->GetNumberOfEdges()); edge_data.edgeBasedNodeID = numbered_edges_count; ++numbered_edges_count; - BOOST_ASSERT( std::numeric_limits::max() != edge_data.edgeBasedNodeID); + BOOST_ASSERT(SPECIAL_NODEID != edge_data.edgeBasedNodeID); } } + m_number_of_edge_based_nodes = numbered_edges_count; +} + +/** + * Creates the nodes in the edge expanded graph from edges in the node-based graph. + */ +void EdgeBasedGraphFactory::GenerateEdgeExpandedNodes() +{ SimpleLogger().Write() << "Identifying components of the road network"; - unsigned node_based_edge_counter = 0; - unsigned original_edges_counter = 0; - - std::ofstream edge_data_file( - original_edge_data_filename.c_str(), - std::ios::binary - ); - - //writes a dummy value that is updated later - edge_data_file.write( - (char*)&original_edges_counter, - sizeof(unsigned) - ); - - //Run a BFS on the undirected graph and identify small components - std::vector component_index_list; - std::vector component_index_size; - BFSCompentExplorer( component_index_list, component_index_size ); - - SimpleLogger().Write() << - "identified: " << component_index_size.size() << " many components"; + // Run a BFS on the undirected graph and identify small components + BFSComponentExplorer component_explorer( + *m_node_based_graph, *m_restriction_map, m_barrier_nodes); + + component_explorer.run(); + + SimpleLogger().Write() << "identified: " << component_explorer.getNumberOfComponents() + << " many components"; SimpleLogger().Write() << "generating edge-expanded nodes"; - p.reinit(m_node_based_graph->GetNumberOfNodes()); + Percent p(m_node_based_graph->GetNumberOfNodes()); - //loop over all edges and generate new set of nodes - for( - NodeIterator u = 0, end = m_node_based_graph->GetNumberOfNodes(); - u < end; - ++u - ) { - BOOST_ASSERT( u != std::numeric_limits::max() ); - BOOST_ASSERT( u < m_node_based_graph->GetNumberOfNodes() ); + // loop over all edges and generate new set of nodes + for (NodeIterator u = 0, end = m_node_based_graph->GetNumberOfNodes(); u < end; ++u) + { + BOOST_ASSERT(u != SPECIAL_NODEID); + BOOST_ASSERT(u < m_node_based_graph->GetNumberOfNodes()); p.printIncrement(); - for( - EdgeID e1 = m_node_based_graph->BeginEdges(u), - last_edge = m_node_based_graph->EndEdges(u); - e1 < last_edge; - ++e1 - ) { - const EdgeData & edge_data = m_node_based_graph->GetEdgeData(e1); - if( edge_data.edgeBasedNodeID == SPECIAL_NODEID ) { + for (EdgeID e1 = m_node_based_graph->BeginEdges(u), + last_edge = m_node_based_graph->EndEdges(u); + e1 < last_edge; + ++e1) + { + const EdgeData &edge_data = m_node_based_graph->GetEdgeData(e1); + if (edge_data.edgeBasedNodeID == SPECIAL_NODEID) + { // continue; } - BOOST_ASSERT( e1 != SPECIAL_EDGEID ); + BOOST_ASSERT(e1 != SPECIAL_EDGEID); const NodeID v = m_node_based_graph->GetTarget(e1); - BOOST_ASSERT( SPECIAL_NODEID != v ); + BOOST_ASSERT(SPECIAL_NODEID != v); // pick only every other edge - if( u > v ) { + if (u > v) + { continue; } - BOOST_ASSERT( u < v ); - BOOST_ASSERT( edge_data.type != SHRT_MAX ); + BOOST_ASSERT(u < v); + BOOST_ASSERT(edge_data.type != SHRT_MAX); - //Note: edges that end on barrier nodes or on a turn restriction - //may actually be in two distinct components. We choose the smallest - const unsigned size_of_component = std::min( - component_index_size[component_index_list[u]], - component_index_size[component_index_list[v]] - ); + // Note: edges that end on barrier nodes or on a turn restriction + // may actually be in two distinct components. We choose the smallest + const unsigned size_of_component = std::min(component_explorer.getComponentSize(u), + component_explorer.getComponentSize(v)); - const bool component_is_tiny = ( size_of_component < 1000 ); - InsertEdgeBasedNode( u, v, e1, component_is_tiny ); + const bool component_is_tiny = (size_of_component < 1000); + InsertEdgeBasedNode(u, v, e1, component_is_tiny); } } - m_number_of_edge_based_nodes = numbered_edges_count; + SimpleLogger().Write() << "Generated " << m_edge_based_node_list.size() + << " nodes in edge-expanded graph"; +} - SimpleLogger().Write() << "Generated " << m_edge_based_node_list.size() << - " nodes in edge-expanded graph"; +/** + * Actually it also generates OriginalEdgeData and serializes them... + */ +void +EdgeBasedGraphFactory::GenerateEdgeExpandedEdges(const std::string &original_edge_data_filename, + lua_State *lua_state) +{ SimpleLogger().Write() << "generating edge-expanded edges"; - std::vector().swap(component_index_size); - BOOST_ASSERT_MSG( - 0 == component_index_size.capacity(), - "component size vector not deallocated" - ); - std::vector().swap(component_index_list); - BOOST_ASSERT_MSG( - 0 == component_index_list.capacity(), - "component index vector not deallocated" - ); + unsigned node_based_edge_counter = 0; + unsigned original_edges_counter = 0; + + std::ofstream edge_data_file(original_edge_data_filename.c_str(), std::ios::binary); + + // writes a dummy value that is updated later + edge_data_file.write((char *)&original_edges_counter, sizeof(unsigned)); + std::vector original_edge_data_vector; - original_edge_data_vector.reserve(1024*1024); + original_edge_data_vector.reserve(1024 * 1024); - //Loop over all turns and generate new set of edges. - //Three nested loop look super-linear, but we are dealing with a (kind of) - //linear number of turns only. + // Loop over all turns and generate new set of edges. + // Three nested loop look super-linear, but we are dealing with a (kind of) + // linear number of turns only. unsigned restricted_turns_counter = 0; unsigned skipped_uturns_counter = 0; unsigned skipped_barrier_turns_counter = 0; unsigned compressed = 0; - p.reinit(m_node_based_graph->GetNumberOfNodes()); + + Percent p(m_node_based_graph->GetNumberOfNodes()); + for (NodeIterator u = 0, end = m_node_based_graph->GetNumberOfNodes(); u < end; ++u) { - for (EdgeIterator e1 = m_node_based_graph->BeginEdges(u), last_edge_u = m_node_based_graph->EndEdges(u); e1 < last_edge_u; ++e1) + for (EdgeIterator e1 = m_node_based_graph->BeginEdges(u), + last_edge_u = m_node_based_graph->EndEdges(u); + e1 < last_edge_u; + ++e1) { - if( !m_node_based_graph->GetEdgeData(e1).forward ) { + if (!m_node_based_graph->GetEdgeData(e1).forward) + { continue; } ++node_based_edge_counter; const NodeIterator v = m_node_based_graph->GetTarget(e1); - const NodeID to_node_of_only_restriction = CheckForEmanatingIsOnlyTurn(u, v); - const bool is_barrier_node = ( m_barrier_nodes.find(v) != m_barrier_nodes.end() ); - - for( - EdgeIterator e2 = m_node_based_graph->BeginEdges(v), - last_edge_v = m_node_based_graph->EndEdges(v); - e2 < last_edge_v; - ++e2 - ) { + const NodeID to_node_of_only_restriction = + m_restriction_map->CheckForEmanatingIsOnlyTurn(u, v); + const bool is_barrier_node = (m_barrier_nodes.find(v) != m_barrier_nodes.end()); + + for (EdgeIterator e2 = m_node_based_graph->BeginEdges(v), + last_edge_v = m_node_based_graph->EndEdges(v); + e2 < last_edge_v; + ++e2) + { if (!m_node_based_graph->GetEdgeData(e2).forward) { continue; } const NodeIterator w = m_node_based_graph->GetTarget(e2); - if ((to_node_of_only_restriction != SPECIAL_NODEID) && (w != to_node_of_only_restriction)) + if ((to_node_of_only_restriction != SPECIAL_NODEID) && + (w != to_node_of_only_restriction)) { - //We are at an only_-restriction but not at the right turn. + // We are at an only_-restriction but not at the right turn. ++restricted_turns_counter; continue; } @@ -770,17 +609,19 @@ void EdgeBasedGraphFactory::Run( } } - //only add an edge if turn is not a U-turn except when it is - //at the end of a dead-end street - if (CheckIfTurnIsRestricted(u, v, w) && (to_node_of_only_restriction == SPECIAL_NODEID) && (w != to_node_of_only_restriction)) + // only add an edge if turn is not a U-turn except when it is + // at the end of a dead-end street + if (m_restriction_map->CheckIfTurnIsRestricted(u, v, w) && + (to_node_of_only_restriction == SPECIAL_NODEID) && + (w != to_node_of_only_restriction)) { ++restricted_turns_counter; continue; } - //only add an edge if turn is not prohibited - const EdgeData & edge_data1 = m_node_based_graph->GetEdgeData(e1); - const EdgeData & edge_data2 = m_node_based_graph->GetEdgeData(e2); + // only add an edge if turn is not prohibited + const EdgeData &edge_data1 = m_node_based_graph->GetEdgeData(e1); + const EdgeData &edge_data2 = m_node_based_graph->GetEdgeData(e2); BOOST_ASSERT(edge_data1.edgeBasedNodeID != edge_data2.edgeBasedNodeID); BOOST_ASSERT(edge_data1.forward); @@ -807,225 +648,143 @@ void EdgeBasedGraphFactory::Run( ++compressed; } - original_edge_data_vector.push_back( - OriginalEdgeData( - (edge_is_compressed ? m_geometry_compressor.GetPositionForID(e1) : v), - edge_data1.nameID, - turn_instruction, - edge_is_compressed - ) - ); + original_edge_data_vector.push_back(OriginalEdgeData( + (edge_is_compressed ? m_geometry_compressor.GetPositionForID(e1) : v), + edge_data1.nameID, + turn_instruction, + edge_is_compressed)); ++original_edges_counter; - if (original_edge_data_vector.size() > 1024*1024*10) + if (original_edge_data_vector.size() > 1024 * 1024 * 10) { FlushVectorToStream(edge_data_file, original_edge_data_vector); } - BOOST_ASSERT( SPECIAL_NODEID != edge_data1.edgeBasedNodeID ); - BOOST_ASSERT( SPECIAL_NODEID != edge_data2.edgeBasedNodeID ); - - m_edge_based_edge_list.push_back( - EdgeBasedEdge( - edge_data1.edgeBasedNodeID, - edge_data2.edgeBasedNodeID, - m_edge_based_edge_list.size(), - distance, - true, - false - ) - ); + BOOST_ASSERT(SPECIAL_NODEID != edge_data1.edgeBasedNodeID); + BOOST_ASSERT(SPECIAL_NODEID != edge_data2.edgeBasedNodeID); + + m_edge_based_edge_list.emplace_back(EdgeBasedEdge(edge_data1.edgeBasedNodeID, + edge_data2.edgeBasedNodeID, + m_edge_based_edge_list.size(), + distance, + true, + false)); } } p.printIncrement(); } - FlushVectorToStream( edge_data_file, original_edge_data_vector ); + FlushVectorToStream(edge_data_file, original_edge_data_vector); - edge_data_file.seekp( std::ios::beg ); - edge_data_file.write( (char*)&original_edges_counter, sizeof(unsigned) ); + edge_data_file.seekp(std::ios::beg); + edge_data_file.write((char *)&original_edges_counter, sizeof(unsigned)); edge_data_file.close(); - m_geometry_compressor.SerializeInternalVector( geometry_filename ); - SimpleLogger().Write() << "Generated " << m_edge_based_node_list.size() << " edge based nodes"; SimpleLogger().Write() << "Node-based graph contains " << node_based_edge_counter << " edges"; SimpleLogger().Write() << "Edge-expanded graph ..."; SimpleLogger().Write() << " contains " << m_edge_based_edge_list.size() << " edges"; - SimpleLogger().Write() << " skips " << restricted_turns_counter << " turns, " - "defined by " << m_turn_restrictions_count << " restrictions"; - SimpleLogger().Write() << " skips " << skipped_uturns_counter << " U turns"; - SimpleLogger().Write() << " skips " << skipped_barrier_turns_counter << " turns over barriers"; + SimpleLogger().Write() << " skips " << restricted_turns_counter << " turns, " + "defined by " + << m_restriction_map->size() << " restrictions"; + SimpleLogger().Write() << " skips " << skipped_uturns_counter << " U turns"; + SimpleLogger().Write() << " skips " << skipped_barrier_turns_counter << " turns over barriers"; } -int EdgeBasedGraphFactory::GetTurnPenalty( - const NodeID u, - const NodeID v, - const NodeID w, - lua_State *lua_state -) const { - const double angle = GetAngleBetweenThreeFixedPointCoordinates ( - m_node_info_list[u], - m_node_info_list[v], - m_node_info_list[w] - ); - - if( speed_profile.has_turn_penalty_function ) { - try { - //call lua profile to compute turn penalty - return luabind::call_function( - lua_state, - "turn_function", - 180.-angle - ); - } catch (const luabind::error &er) { +int EdgeBasedGraphFactory::GetTurnPenalty(const NodeID u, + const NodeID v, + const NodeID w, + lua_State *lua_state) const +{ + const double angle = GetAngleBetweenThreeFixedPointCoordinates( + m_node_info_list[u], m_node_info_list[v], m_node_info_list[w]); + + if (speed_profile.has_turn_penalty_function) + { + try + { + // call lua profile to compute turn penalty + return luabind::call_function(lua_state, "turn_function", 180. - angle); + } + catch (const luabind::error &er) + { SimpleLogger().Write(logWARNING) << er.what(); } } return 0; } -TurnInstruction EdgeBasedGraphFactory::AnalyzeTurn( - const NodeID u, - const NodeID v, - const NodeID w -) const { - if(u == w) { +TurnInstruction EdgeBasedGraphFactory::AnalyzeTurn(const NodeID u, const NodeID v, const NodeID w) + const +{ + if (u == w) + { return TurnInstruction::UTurn; } const EdgeIterator edge1 = m_node_based_graph->FindEdge(u, v); const EdgeIterator edge2 = m_node_based_graph->FindEdge(v, w); - const EdgeData & data1 = m_node_based_graph->GetEdgeData(edge1); - const EdgeData & data2 = m_node_based_graph->GetEdgeData(edge2); + const EdgeData &data1 = m_node_based_graph->GetEdgeData(edge1); + const EdgeData &data2 = m_node_based_graph->GetEdgeData(edge2); - if(!data1.contraFlow && data2.contraFlow) { + if (!data1.contraFlow && data2.contraFlow) + { return TurnInstruction::EnterAgainstAllowedDirection; } - if(data1.contraFlow && !data2.contraFlow) { + if (data1.contraFlow && !data2.contraFlow) + { return TurnInstruction::LeaveAgainstAllowedDirection; } - //roundabouts need to be handled explicitely - if(data1.roundabout && data2.roundabout) { - //Is a turn possible? If yes, we stay on the roundabout! - if( 1 == m_node_based_graph->GetOutDegree(v) ) { - //No turn possible. + // roundabouts need to be handled explicitely + if (data1.roundabout && data2.roundabout) + { + // Is a turn possible? If yes, we stay on the roundabout! + if (1 == m_node_based_graph->GetOutDegree(v)) + { + // No turn possible. return TurnInstruction::NoTurn; } return TurnInstruction::StayOnRoundAbout; } - //Does turn start or end on roundabout? - if(data1.roundabout || data2.roundabout) { - //We are entering the roundabout - if( (!data1.roundabout) && data2.roundabout) { + // Does turn start or end on roundabout? + if (data1.roundabout || data2.roundabout) + { + // We are entering the roundabout + if ((!data1.roundabout) && data2.roundabout) + { return TurnInstruction::EnterRoundAbout; } - //We are leaving the roundabout - if(data1.roundabout && (!data2.roundabout) ) { + // We are leaving the roundabout + if (data1.roundabout && (!data2.roundabout)) + { return TurnInstruction::LeaveRoundAbout; } } - //If street names stay the same and if we are certain that it is not a - //a segment of a roundabout, we skip it. - if( data1.nameID == data2.nameID ) { - //TODO: Here we should also do a small graph exploration to check for + // If street names stay the same and if we are certain that it is not a + // a segment of a roundabout, we skip it. + if (data1.nameID == data2.nameID) + { + // TODO: Here we should also do a small graph exploration to check for // more complex situations - if( 0 != data1.nameID ) { + if (0 != data1.nameID) + { return TurnInstruction::NoTurn; - } else if (m_node_based_graph->GetOutDegree(v) <= 2) { + } + else if (m_node_based_graph->GetOutDegree(v) <= 2) + { return TurnInstruction::NoTurn; } } - const double angle = GetAngleBetweenThreeFixedPointCoordinates ( - m_node_info_list[u], - m_node_info_list[v], - m_node_info_list[w] - ); + const double angle = GetAngleBetweenThreeFixedPointCoordinates( + m_node_info_list[u], m_node_info_list[v], m_node_info_list[w]); return TurnInstructionsClass::GetTurnDirectionOfInstruction(angle); } -unsigned EdgeBasedGraphFactory::GetNumberOfEdgeBasedNodes() const { +unsigned EdgeBasedGraphFactory::GetNumberOfEdgeBasedNodes() const +{ return m_number_of_edge_based_nodes; } - -void EdgeBasedGraphFactory::BFSCompentExplorer( - std::vector & component_index_list, - std::vector & component_index_size -) const { - std::queue > bfs_queue; - Percent p( m_node_based_graph->GetNumberOfNodes() ); - unsigned current_component, current_component_size; - current_component = current_component_size = 0; - - BOOST_ASSERT( component_index_list.empty() ); - BOOST_ASSERT( component_index_size.empty() ); - - component_index_list.resize( - m_node_based_graph->GetNumberOfNodes(), - std::numeric_limits::max() - ); - - //put unexplorered node with parent pointer into queue - for( NodeID node = 0, end = m_node_based_graph->GetNumberOfNodes(); node < end; ++node) { - if(std::numeric_limits::max() == component_index_list[node]) { - bfs_queue.push(std::make_pair(node, node)); - //mark node as read - component_index_list[node] = current_component; - p.printIncrement(); - while(!bfs_queue.empty()) { - //fetch element from BFS queue - std::pair current_queue_item = bfs_queue.front(); - bfs_queue.pop(); - - const NodeID v = current_queue_item.first; //current node - const NodeID u = current_queue_item.second; //parent - //increment size counter of current component - ++current_component_size; - const bool is_barrier_node = (m_barrier_nodes.find(v) != m_barrier_nodes.end()); - if(!is_barrier_node) { - const NodeID to_node_of_only_restriction = CheckForEmanatingIsOnlyTurn(u, v); - - for( - EdgeIterator e2 = m_node_based_graph->BeginEdges(v); - e2 < m_node_based_graph->EndEdges(v); - ++e2 - ) { - NodeIterator w = m_node_based_graph->GetTarget(e2); - - if( - to_node_of_only_restriction != std::numeric_limits::max() && - w != to_node_of_only_restriction - ) { - // At an only_-restriction but not at the right turn - continue; - } - if( u != w ) { - //only add an edge if turn is not a U-turn except - //when it is at the end of a dead-end street. - if (!CheckIfTurnIsRestricted(u, v, w) ) { - //only add an edge if turn is not prohibited - if(std::numeric_limits::max() == component_index_list[w]) { - //insert next (node, parent) only if w has - //not yet been explored - //mark node as read - component_index_list[w] = current_component; - bfs_queue.push(std::make_pair(w,v)); - p.printIncrement(); - } - } - } - } - } - } - //push size into vector - component_index_size.push_back(current_component_size); - //reset counters; - current_component_size = 0; - ++current_component; - } - } -} diff --git a/Contractor/EdgeBasedGraphFactory.h b/Contractor/EdgeBasedGraphFactory.h index 2a777dd3a75..7fdb21e845b 100644 --- a/Contractor/EdgeBasedGraphFactory.h +++ b/Contractor/EdgeBasedGraphFactory.h @@ -35,20 +35,20 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #include "../DataStructures/DynamicGraph.h" #include "../DataStructures/EdgeBasedNode.h" #include "../DataStructures/HashTable.h" -#include "../DataStructures/ImportEdge.h" #include "../DataStructures/OriginalEdgeData.h" #include "../DataStructures/Percent.h" #include "../DataStructures/QueryEdge.h" #include "../DataStructures/QueryNode.h" #include "../DataStructures/TurnInstructions.h" #include "../DataStructures/Restriction.h" +#include "../DataStructures/NodeBasedGraph.h" +#include "../DataStructures/RestrictionMap.h" #include "../Util/LuaUtil.h" #include "../Util/SimpleLogger.h" #include "GeometryCompressor.h" #include -#include #include #include @@ -57,155 +57,76 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #include #include -class EdgeBasedGraphFactory : boost::noncopyable { -public: +class EdgeBasedGraphFactory : boost::noncopyable +{ + public: struct SpeedProfileProperties; - explicit EdgeBasedGraphFactory( - int number_of_nodes, - std::vector & input_edge_list, - std::vector & barrier_node_list, - std::vector & traffic_light_node_list, - std::vector & input_restrictions_list, - std::vector & m_node_info_list, - SpeedProfileProperties & speed_profile - ); - - void Run( - const std::string & original_edge_data_filename, - const std::string & geometry_filename, - lua_State *myLuaState - ); - - void GetEdgeBasedEdges( DeallocatingVector< EdgeBasedEdge >& edges ); - - void GetEdgeBasedNodes( std::vector< EdgeBasedNode> & nodes); - - TurnInstruction AnalyzeTurn( - const NodeID u, - const NodeID v, - const NodeID w - ) const; - - int GetTurnPenalty( - const NodeID u, - const NodeID v, - const NodeID w, - lua_State *myLuaState - ) const; + explicit EdgeBasedGraphFactory(const std::shared_ptr &node_based_graph, + std::unique_ptr restricion_map, + std::vector &barrier_node_list, + std::vector &traffic_light_node_list, + std::vector &m_node_info_list, + SpeedProfileProperties &speed_profile); + + void Run(const std::string &original_edge_data_filename, + const std::string &geometry_filename, + lua_State *myLuaState); + + void GetEdgeBasedEdges(DeallocatingVector &edges); + + void GetEdgeBasedNodes(std::vector &nodes); + + TurnInstruction AnalyzeTurn(const NodeID u, const NodeID v, const NodeID w) const; + + int GetTurnPenalty(const NodeID u, const NodeID v, const NodeID w, lua_State *myLuaState) const; unsigned GetNumberOfEdgeBasedNodes() const; - struct SpeedProfileProperties{ - SpeedProfileProperties() : - trafficSignalPenalty(0), - uTurnPenalty(0), - has_turn_penalty_function(false) - { } + struct SpeedProfileProperties + { + SpeedProfileProperties() + : trafficSignalPenalty(0), uTurnPenalty(0), has_turn_penalty_function(false) + { + } int trafficSignalPenalty; int uTurnPenalty; bool has_turn_penalty_function; } speed_profile; -private: - struct NodeBasedEdgeData { - NodeBasedEdgeData() : distance(INVALID_EDGE_WEIGHT), edgeBasedNodeID(SPECIAL_NODEID), nameID(std::numeric_limits::max()), - type(std::numeric_limits::max()), isAccessRestricted(false), shortcut(false), forward(false), backward(false), - roundabout(false), ignore_in_grid(false), contraFlow(false) - { } - - int distance; - unsigned edgeBasedNodeID; - unsigned nameID; - short type; - bool isAccessRestricted:1; - bool shortcut:1; - bool forward:1; - bool backward:1; - bool roundabout:1; - bool ignore_in_grid:1; - bool contraFlow:1; - - void SwapDirectionFlags() { - bool temp_flag = forward; - forward = backward; - backward = temp_flag; - } - - bool IsEqualTo( const NodeBasedEdgeData & other ) const { - return (forward == other.forward) && - (backward == other.backward) && - (nameID == other.nameID) && - (ignore_in_grid == other.ignore_in_grid) && - (contraFlow == other.contraFlow); - } - }; + private: + typedef NodeBasedDynamicGraph::NodeIterator NodeIterator; + typedef NodeBasedDynamicGraph::EdgeIterator EdgeIterator; + typedef NodeBasedDynamicGraph::EdgeData EdgeData; - unsigned m_turn_restrictions_count; unsigned m_number_of_edge_based_nodes; - typedef DynamicGraph NodeBasedDynamicGraph; - typedef NodeBasedDynamicGraph::InputEdge NodeBasedEdge; - typedef NodeBasedDynamicGraph::NodeIterator NodeIterator; - typedef NodeBasedDynamicGraph::EdgeIterator EdgeIterator; - typedef NodeBasedDynamicGraph::EdgeData EdgeData; - typedef std::pair RestrictionSource; - typedef std::pair RestrictionTarget; - typedef std::vector EmanatingRestrictionsVector; - typedef boost::unordered_map RestrictionMap; - - std::vector m_node_info_list; - std::vector m_restriction_bucket_list; - std::vector m_edge_based_node_list; - DeallocatingVector m_edge_based_edge_list; - - boost::shared_ptr m_node_based_graph; - boost::unordered_set m_barrier_nodes; - boost::unordered_set m_traffic_lights; - - RestrictionMap m_restriction_map; - GeometryCompressor m_geometry_compressor; - - NodeID CheckForEmanatingIsOnlyTurn( - const NodeID u, - const NodeID v - ) const; - - bool CheckIfTurnIsRestricted( - const NodeID u, - const NodeID v, - const NodeID w - ) const; - - void InsertEdgeBasedNode( - NodeBasedDynamicGraph::NodeIterator u, - NodeBasedDynamicGraph::NodeIterator v, - NodeBasedDynamicGraph::EdgeIterator e1, - bool belongsToTinyComponent - ); - - void BFSCompentExplorer( - std::vector & component_index_list, - std::vector & component_index_size - ) const; - - void FlushVectorToStream( - std::ofstream & edge_data_file, - std::vector & original_edge_data_vector - ) const; - - void FixupArrivingTurnRestriction( - const NodeID u, - const NodeID v, - const NodeID w - ); - - void FixupStartingTurnRestriction( - const NodeID u, - const NodeID v, - const NodeID w - ); + std::vector m_node_info_list; + std::vector m_edge_based_node_list; + DeallocatingVector m_edge_based_edge_list; + + std::shared_ptr m_node_based_graph; + boost::unordered_set m_barrier_nodes; + boost::unordered_set m_traffic_lights; + + std::unique_ptr m_restriction_map; + + GeometryCompressor m_geometry_compressor; + + void CompressGeometry(); + void RenumberEdges(); + void GenerateEdgeExpandedNodes(); + void GenerateEdgeExpandedEdges(const std::string &original_edge_data_filename, + lua_State *lua_state); + + void InsertEdgeBasedNode(NodeBasedDynamicGraph::NodeIterator u, + NodeBasedDynamicGraph::NodeIterator v, + NodeBasedDynamicGraph::EdgeIterator e1, + bool belongsToTinyComponent); + + void FlushVectorToStream(std::ofstream &edge_data_file, + std::vector &original_edge_data_vector) const; unsigned max_id; }; diff --git a/Contractor/GeometryCompressor.cpp b/Contractor/GeometryCompressor.cpp index 4d85e01ff45..8a9ba6f5d0e 100644 --- a/Contractor/GeometryCompressor.cpp +++ b/Contractor/GeometryCompressor.cpp @@ -70,18 +70,18 @@ unsigned GeometryCompressor::GetPositionForID(const EdgeID edge_id) const void GeometryCompressor::SerializeInternalVector(const std::string &path) const { - boost::filesystem::fstream geometry_out_stream(path, std::ios::binary|std::ios::out); + boost::filesystem::fstream geometry_out_stream(path, std::ios::binary | std::ios::out); const unsigned number_of_compressed_geometries = m_compressed_geometries.size() + 1; BOOST_ASSERT(UINT_MAX != number_of_compressed_geometries); geometry_out_stream.write((char *)&number_of_compressed_geometries, sizeof(unsigned)); // write indices array unsigned prefix_sum_of_list_indices = 0; - for (unsigned i = 0; i < m_compressed_geometries.size(); ++i) + for (auto &elem : m_compressed_geometries) { geometry_out_stream.write((char *)&prefix_sum_of_list_indices, sizeof(unsigned)); - const std::vector ¤t_vector = m_compressed_geometries.at(i); + const std::vector ¤t_vector = elem; const unsigned unpacked_size = current_vector.size(); BOOST_ASSERT(UINT_MAX != unpacked_size); prefix_sum_of_list_indices += unpacked_size; @@ -94,9 +94,9 @@ void GeometryCompressor::SerializeInternalVector(const std::string &path) const unsigned control_sum = 0; // write compressed geometries - for (unsigned i = 0; i < m_compressed_geometries.size(); ++i) + for (auto &elem : m_compressed_geometries) { - const std::vector ¤t_vector = m_compressed_geometries[i]; + const std::vector ¤t_vector = elem; const unsigned unpacked_size = current_vector.size(); control_sum += unpacked_size; BOOST_ASSERT(UINT_MAX != unpacked_size); @@ -122,8 +122,8 @@ void GeometryCompressor::CompressEdge(const EdgeID edge_id_1, BOOST_ASSERT(SPECIAL_EDGEID != edge_id_2); BOOST_ASSERT(SPECIAL_NODEID != via_node_id); BOOST_ASSERT(SPECIAL_NODEID != target_node_id); - BOOST_ASSERT(std::numeric_limits::max() != weight1); - BOOST_ASSERT(std::numeric_limits::max() != weight2); + BOOST_ASSERT(INVALID_EDGE_WEIGHT != weight1); + BOOST_ASSERT(INVALID_EDGE_WEIGHT != weight2); // append list of removed edge_id plus via node to surviving edge id: // ::const_iterator iter = m_edge_id_to_list_index_map.find(edge_id_1); + const boost::unordered_map::const_iterator iter = + m_edge_id_to_list_index_map.find(edge_id_1); BOOST_ASSERT(iter != m_edge_id_to_list_index_map.end()); const unsigned edge_bucket_id1 = iter->second; BOOST_ASSERT(edge_bucket_id1 == GetPositionForID(edge_id_1)); diff --git a/Contractor/GeometryCompressor.h b/Contractor/GeometryCompressor.h index 39c92d45d0d..5cd9dcbeeb1 100644 --- a/Contractor/GeometryCompressor.h +++ b/Contractor/GeometryCompressor.h @@ -56,7 +56,7 @@ class GeometryCompressor private: void IncreaseFreeList(); - std::vector > m_compressed_geometries; + std::vector> m_compressed_geometries; std::vector m_free_list; boost::unordered_map m_edge_id_to_list_index_map; }; diff --git a/Contractor/TemporaryStorage.cpp b/Contractor/TemporaryStorage.cpp index d0e160b6f4e..582d7e66f5a 100644 --- a/Contractor/TemporaryStorage.cpp +++ b/Contractor/TemporaryStorage.cpp @@ -27,136 +27,154 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #include "TemporaryStorage.h" -TemporaryStorage::TemporaryStorage() { - temp_directory = boost::filesystem::temp_directory_path(); -} +TemporaryStorage::TemporaryStorage() { temp_directory = boost::filesystem::temp_directory_path(); } -TemporaryStorage & TemporaryStorage::GetInstance(){ +TemporaryStorage &TemporaryStorage::GetInstance() +{ static TemporaryStorage static_instance; return static_instance; } -TemporaryStorage::~TemporaryStorage() { - RemoveAll(); -} +TemporaryStorage::~TemporaryStorage() { RemoveAll(); } -void TemporaryStorage::RemoveAll() { +void TemporaryStorage::RemoveAll() +{ boost::mutex::scoped_lock lock(mutex); - for(unsigned slot_id = 0; slot_id < stream_data_list.size(); ++slot_id) { + for (unsigned slot_id = 0; slot_id < stream_data_list.size(); ++slot_id) + { DeallocateSlot(slot_id); } stream_data_list.clear(); } -int TemporaryStorage::AllocateSlot() { +int TemporaryStorage::AllocateSlot() +{ boost::mutex::scoped_lock lock(mutex); - try { + try + { stream_data_list.push_back(StreamData()); - } catch(boost::filesystem::filesystem_error & e) { + } + catch (boost::filesystem::filesystem_error &e) + { Abort(e); } CheckIfTemporaryDeviceFull(); return stream_data_list.size() - 1; } -void TemporaryStorage::DeallocateSlot(const int slot_id) { - try { - StreamData & data = stream_data_list[slot_id]; +void TemporaryStorage::DeallocateSlot(const int slot_id) +{ + try + { + StreamData &data = stream_data_list[slot_id]; boost::mutex::scoped_lock lock(*data.readWriteMutex); - if(!boost::filesystem::exists(data.temp_path)) { + if (!boost::filesystem::exists(data.temp_path)) + { return; } - if(data.temp_file->is_open()) { + if (data.temp_file->is_open()) + { data.temp_file->close(); } boost::filesystem::remove(data.temp_path); - } catch(boost::filesystem::filesystem_error & e) { + } + catch (boost::filesystem::filesystem_error &e) + { Abort(e); } } -void TemporaryStorage::WriteToSlot( - const int slot_id, - char * pointer, - const std::size_t size -) { - try { - StreamData & data = stream_data_list[slot_id]; +void TemporaryStorage::WriteToSlot(const int slot_id, char *pointer, const std::size_t size) +{ + try + { + StreamData &data = stream_data_list[slot_id]; BOOST_ASSERT(data.write_mode); boost::mutex::scoped_lock lock(*data.readWriteMutex); - BOOST_ASSERT_MSG( - data.write_mode, - "Writing after first read is not allowed" - ); - if( 1073741824 < data.buffer.size() ) { + BOOST_ASSERT_MSG(data.write_mode, "Writing after first read is not allowed"); + if (1073741824 < data.buffer.size()) + { data.temp_file->write(&data.buffer[0], data.buffer.size()); // data.temp_file->write(pointer, size); data.buffer.clear(); CheckIfTemporaryDeviceFull(); } - data.buffer.insert(data.buffer.end(), pointer, pointer+size); - - } catch(boost::filesystem::filesystem_error & e) { + data.buffer.insert(data.buffer.end(), pointer, pointer + size); + } + catch (boost::filesystem::filesystem_error &e) + { Abort(e); } } -void TemporaryStorage::ReadFromSlot( - const int slot_id, - char * pointer, - const std::size_t size -) { - try { - StreamData & data = stream_data_list[slot_id]; +void TemporaryStorage::ReadFromSlot(const int slot_id, char *pointer, const std::size_t size) +{ + try + { + StreamData &data = stream_data_list[slot_id]; boost::mutex::scoped_lock lock(*data.readWriteMutex); - if( data.write_mode ) { + if (data.write_mode) + { data.write_mode = false; data.temp_file->write(&data.buffer[0], data.buffer.size()); data.buffer.clear(); - data.temp_file->seekg( data.temp_file->beg ); - BOOST_ASSERT( data.temp_file->beg == data.temp_file->tellg() ); + data.temp_file->seekg(data.temp_file->beg); + BOOST_ASSERT(data.temp_file->beg == data.temp_file->tellg()); } - BOOST_ASSERT( !data.write_mode ); + BOOST_ASSERT(!data.write_mode); data.temp_file->read(pointer, size); - } catch(boost::filesystem::filesystem_error & e) { + } + catch (boost::filesystem::filesystem_error &e) + { Abort(e); } } -uint64_t TemporaryStorage::GetFreeBytesOnTemporaryDevice() { +uint64_t TemporaryStorage::GetFreeBytesOnTemporaryDevice() +{ uint64_t value = -1; - try { - boost::filesystem::path p = boost::filesystem::temp_directory_path(); - boost::filesystem::space_info s = boost::filesystem::space( p ); + try + { + boost::filesystem::path p = boost::filesystem::temp_directory_path(); + boost::filesystem::space_info s = boost::filesystem::space(p); value = s.free; - } catch(boost::filesystem::filesystem_error & e) { + } + catch (boost::filesystem::filesystem_error &e) + { Abort(e); } return value; } -void TemporaryStorage::CheckIfTemporaryDeviceFull() { +void TemporaryStorage::CheckIfTemporaryDeviceFull() +{ boost::filesystem::path p = boost::filesystem::temp_directory_path(); - boost::filesystem::space_info s = boost::filesystem::space( p ); - if( (1024*1024) > s.free ) { + boost::filesystem::space_info s = boost::filesystem::space(p); + if ((1024 * 1024) > s.free) + { throw OSRMException("temporary device is full"); } } -boost::filesystem::fstream::pos_type TemporaryStorage::Tell(const int slot_id) { +boost::filesystem::fstream::pos_type TemporaryStorage::Tell(const int slot_id) +{ boost::filesystem::fstream::pos_type position; - try { - StreamData & data = stream_data_list[slot_id]; + try + { + StreamData &data = stream_data_list[slot_id]; boost::mutex::scoped_lock lock(*data.readWriteMutex); position = data.temp_file->tellp(); - } catch(boost::filesystem::filesystem_error & e) { + } + catch (boost::filesystem::filesystem_error &e) + { Abort(e); } return position; } -void TemporaryStorage::Abort(const boost::filesystem::filesystem_error& e) { +void TemporaryStorage::Abort(const boost::filesystem::filesystem_error &e) +{ RemoveAll(); throw OSRMException(e.what()); } diff --git a/Contractor/TemporaryStorage.h b/Contractor/TemporaryStorage.h index 5704e7dd865..5864cc68457 100644 --- a/Contractor/TemporaryStorage.h +++ b/Contractor/TemporaryStorage.h @@ -36,8 +36,6 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #include #include #include -#include -#include #include #include @@ -56,61 +54,52 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. static boost::filesystem::path temp_directory; static std::string TemporaryFilePattern("OSRM-%%%%-%%%%-%%%%"); -class TemporaryStorage { -public: - static TemporaryStorage & GetInstance(); +class TemporaryStorage +{ + public: + static TemporaryStorage &GetInstance(); virtual ~TemporaryStorage(); int AllocateSlot(); void DeallocateSlot(const int slot_id); - void WriteToSlot(const int slot_id, char * pointer, const std::size_t size); - void ReadFromSlot(const int slot_id, char * pointer, const std::size_t size); - //returns the number of free bytes + void WriteToSlot(const int slot_id, char *pointer, const std::size_t size); + void ReadFromSlot(const int slot_id, char *pointer, const std::size_t size); + // returns the number of free bytes uint64_t GetFreeBytesOnTemporaryDevice(); boost::filesystem::fstream::pos_type Tell(const int slot_id); void RemoveAll(); -private: + + private: TemporaryStorage(); - TemporaryStorage(TemporaryStorage const &){}; + TemporaryStorage(TemporaryStorage const &) {}; - TemporaryStorage & operator=(TemporaryStorage const &) { - return *this; - } + TemporaryStorage &operator=(TemporaryStorage const &) { return *this; } - void Abort(const boost::filesystem::filesystem_error& e); + void Abort(const boost::filesystem::filesystem_error &e); void CheckIfTemporaryDeviceFull(); - struct StreamData { + struct StreamData + { bool write_mode; boost::filesystem::path temp_path; - boost::shared_ptr temp_file; - boost::shared_ptr readWriteMutex; + std::shared_ptr temp_file; + std::shared_ptr readWriteMutex; std::vector buffer; - StreamData() : - write_mode(true), - temp_path( - boost::filesystem::unique_path( - temp_directory.append( - TemporaryFilePattern.begin(), - TemporaryFilePattern.end() - ) - ) - ), - temp_file( - new boost::filesystem::fstream( - temp_path, - std::ios::in|std::ios::out|std::ios::trunc|std::ios::binary - ) - ), - readWriteMutex(boost::make_shared()) + StreamData() + : write_mode(true), temp_path(boost::filesystem::unique_path(temp_directory.append( + TemporaryFilePattern.begin(), TemporaryFilePattern.end()))), + temp_file(new boost::filesystem::fstream( + temp_path, std::ios::in | std::ios::out | std::ios::trunc | std::ios::binary)), + readWriteMutex(std::make_shared()) { - if( temp_file->fail() ) { + if (temp_file->fail()) + { throw OSRMException("temporary file could not be created"); } } }; - //vector of file streams that is used to store temporary data + // vector of file streams that is used to store temporary data boost::mutex mutex; std::vector stream_data_list; }; diff --git a/DataStructures/NodeBasedGraph.h b/DataStructures/NodeBasedGraph.h new file mode 100644 index 00000000000..393add55b51 --- /dev/null +++ b/DataStructures/NodeBasedGraph.h @@ -0,0 +1,110 @@ +#ifndef __NODE_BASED_GRAPH_H__ +#define __NODE_BASED_GRAPH_H__ + +#include "DynamicGraph.h" +#include "ImportEdge.h" + +struct NodeBasedEdgeData +{ + NodeBasedEdgeData() + : distance(INVALID_EDGE_WEIGHT), edgeBasedNodeID(SPECIAL_NODEID), + nameID(std::numeric_limits::max()), type(std::numeric_limits::max()), + isAccessRestricted(false), shortcut(false), forward(false), backward(false), + roundabout(false), ignore_in_grid(false), contraFlow(false) + { + } + + int distance; + unsigned edgeBasedNodeID; + unsigned nameID; + short type; + bool isAccessRestricted : 1; + bool shortcut : 1; + bool forward : 1; + bool backward : 1; + bool roundabout : 1; + bool ignore_in_grid : 1; + bool contraFlow : 1; + + void SwapDirectionFlags() + { + bool temp_flag = forward; + forward = backward; + backward = temp_flag; + } + + bool IsEqualTo(const NodeBasedEdgeData &other) const + { + return (forward == other.forward) && (backward == other.backward) && + (nameID == other.nameID) && (ignore_in_grid == other.ignore_in_grid) && + (contraFlow == other.contraFlow); + } +}; + +typedef DynamicGraph NodeBasedDynamicGraph; + +// Factory method to create NodeBasedDynamicGraph from ImportEdges +inline std::shared_ptr +NodeBasedDynamicGraphFromImportEdges(int number_of_nodes, std::vector &input_edge_list) +{ + typedef NodeBasedDynamicGraph::InputEdge DynInputEdge; + + std::sort(input_edge_list.begin(), input_edge_list.end()); + + // TODO: remove duplicate edges + DeallocatingVector edges_list; + DynInputEdge edge; + for (const ImportEdge &import_edge : input_edge_list) + { + + if (!import_edge.isForward()) + { + edge.source = import_edge.target(); + edge.target = import_edge.source(); + edge.data.backward = import_edge.isForward(); + edge.data.forward = import_edge.isBackward(); + } + else + { + edge.source = import_edge.source(); + edge.target = import_edge.target(); + edge.data.forward = import_edge.isForward(); + edge.data.backward = import_edge.isBackward(); + } + + if (edge.source == edge.target) + { + continue; + } + + edge.data.distance = (std::max)((int)import_edge.weight(), 1); + BOOST_ASSERT(edge.data.distance > 0); + edge.data.shortcut = false; + edge.data.roundabout = import_edge.isRoundabout(); + edge.data.ignore_in_grid = import_edge.ignoreInGrid(); + edge.data.nameID = import_edge.name(); + edge.data.type = import_edge.type(); + edge.data.isAccessRestricted = import_edge.isAccessRestricted(); + edge.data.contraFlow = import_edge.isContraFlow(); + edges_list.push_back(edge); + + if (!import_edge.IsSplit()) + { + using std::swap; // enable ADL + swap(edge.source, edge.target); + edge.data.SwapDirectionFlags(); + edges_list.push_back(edge); + } + } + + std::sort(edges_list.begin(), edges_list.end()); + auto graph = std::make_shared(number_of_nodes, edges_list); + + // FIXME probably unneeded since this is the end of scope + DeallocatingVector().swap(edges_list); + BOOST_ASSERT(0 == edges_list.size()); + + return graph; +} + +#endif diff --git a/DataStructures/RestrictionMap.cpp b/DataStructures/RestrictionMap.cpp new file mode 100644 index 00000000000..69641f1224e --- /dev/null +++ b/DataStructures/RestrictionMap.cpp @@ -0,0 +1,168 @@ +#include "RestrictionMap.h" +#include "NodeBasedGraph.h" + +RestrictionMap::RestrictionMap(const std::shared_ptr &graph, + const std::vector &input_restrictions_list) + : m_count(0), m_graph(graph) +{ + // decompose restirction consisting of a start, via and end note into a start-edge + // and all end-nodes + for (auto &restriction : input_restrictions_list) + { + std::pair restriction_source = + std::make_pair(restriction.fromNode, restriction.viaNode); + unsigned index; + auto restriction_iter = m_restriction_map.find(restriction_source); + if (restriction_iter == m_restriction_map.end()) + { + index = m_restriction_bucket_list.size(); + m_restriction_bucket_list.resize(index + 1); + m_restriction_map.emplace(restriction_source, index); + } + else + { + index = restriction_iter->second; + // Map already contains an is_only_*-restriction + if (m_restriction_bucket_list.at(index).begin()->second) + { + continue; + } + else if (restriction.flags.isOnly) + { + // We are going to insert an is_only_*-restriction. There can be only one. + m_count -= m_restriction_bucket_list.at(index).size(); + m_restriction_bucket_list.at(index).clear(); + } + } + ++m_count; + m_restriction_bucket_list.at(index) + .push_back(std::make_pair(restriction.toNode, restriction.flags.isOnly)); + } +} + +/** + * Replace end v with w in each turn restriction containing u as via node + * + * Note: We need access to node based graph. + */ +void RestrictionMap::FixupArrivingTurnRestriction(const NodeID u, const NodeID v, const NodeID w) +{ + BOOST_ASSERT(u != std::numeric_limits::max()); + BOOST_ASSERT(v != std::numeric_limits::max()); + BOOST_ASSERT(w != std::numeric_limits::max()); + + // find all possible start edges + // it is more efficent to get a (small) list of potential start edges + // than iterating over all buckets + std::vector predecessors; + for (EdgeID current_edge_id = m_graph->BeginEdges(u); current_edge_id < m_graph->EndEdges(u); + ++current_edge_id) + { + const EdgeData &edge_data = m_graph->GetEdgeData(current_edge_id); + const NodeID target = m_graph->GetTarget(current_edge_id); + if (edge_data.backward && (v != target)) + { + predecessors.push_back(target); + } + } + + for (const NodeID x : predecessors) + { + const std::pair restr_start = std::make_pair(x, u); + auto restriction_iterator = m_restriction_map.find(restr_start); + if (restriction_iterator == m_restriction_map.end()) + continue; + + const unsigned index = restriction_iterator->second; + auto &bucket = m_restriction_bucket_list.at(index); + for (RestrictionTarget &restriction_target : bucket) + { + if (v == restriction_target.first) + { + restriction_target.first = w; + } + } + } +} + +/** + * Replaces the start edge (v, w) with (u, w), only start node changes. + */ +void RestrictionMap::FixupStartingTurnRestriction(const NodeID u, const NodeID v, const NodeID w) +{ + BOOST_ASSERT(u != std::numeric_limits::max()); + BOOST_ASSERT(v != std::numeric_limits::max()); + BOOST_ASSERT(w != std::numeric_limits::max()); + + const std::pair old_start = std::make_pair(v, w); + + auto restriction_iterator = m_restriction_map.find(old_start); + if (restriction_iterator != m_restriction_map.end()) + { + const unsigned index = restriction_iterator->second; + // remove old restriction start (v,w) + m_restriction_map.erase(restriction_iterator); + + // insert new restriction start (u,w) (point to index) + const std::pair new_start = std::make_pair(u, w); + m_restriction_map.insert(std::make_pair(new_start, index)); + } +} + +/* + * Check if the edge (u, v) is contained in any turn restriction. + * If so returns id of first target node. + */ +NodeID RestrictionMap::CheckForEmanatingIsOnlyTurn(const NodeID u, const NodeID v) const +{ + BOOST_ASSERT(u != std::numeric_limits::max()); + BOOST_ASSERT(v != std::numeric_limits::max()); + + const std::pair restriction_source = std::make_pair(u, v); + auto restriction_iter = m_restriction_map.find(restriction_source); + + if (restriction_iter != m_restriction_map.end()) + { + const unsigned index = restriction_iter->second; + auto &bucket = m_restriction_bucket_list.at(index); + for (const RestrictionSource &restriction_target : bucket) + { + if (restriction_target.second) + { + return restriction_target.first; + } + } + } + + return std::numeric_limits::max(); +} + +/** + * Checks if the turn described by start u, via v and targed w is covert by any turn restriction. + */ +bool RestrictionMap::CheckIfTurnIsRestricted(const NodeID u, const NodeID v, const NodeID w) const +{ + BOOST_ASSERT(u != std::numeric_limits::max()); + BOOST_ASSERT(v != std::numeric_limits::max()); + BOOST_ASSERT(w != std::numeric_limits::max()); + + const std::pair restriction_source = std::make_pair(u, v); + auto restriction_iter = m_restriction_map.find(restriction_source); + + if (restriction_iter != m_restriction_map.end()) + { + const unsigned index = restriction_iter->second; + auto &bucket = m_restriction_bucket_list.at(index); + for (const RestrictionTarget &restriction_target : bucket) + { + if ((w == restriction_target.first) && // target found + (!restriction_target.second) // and not an only_-restr. + ) + { + return true; + } + } + } + + return false; +} diff --git a/DataStructures/RestrictionMap.h b/DataStructures/RestrictionMap.h new file mode 100644 index 00000000000..099397037eb --- /dev/null +++ b/DataStructures/RestrictionMap.h @@ -0,0 +1,71 @@ +/* + +Copyright (c) 2013, Project OSRM, Dennis Luxen, others +All rights reserved. + +Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + +Redistributions of source code must retain the above copyright notice, this list +of conditions and the following disclaimer. +Redistributions in binary form must reproduce the above copyright notice, this +list of conditions and the following disclaimer in the documentation and/or +other materials provided with the distribution. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND +ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR +ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON +ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +*/ + +#ifndef __RESTRICTION_MAP_H__ +#define __RESTRICTION_MAP_H__ + +#include + +#include "../typedefs.h" +#include "DynamicGraph.h" +#include "Restriction.h" +#include "NodeBasedGraph.h" + +#include + +/*! + * Makee it efficent to look up if an edge is the start + via node of a TurnRestriction. + * Is needed by EdgeBasedGraphFactory. + */ +class RestrictionMap +{ + public: + RestrictionMap(const std::shared_ptr &graph, + const std::vector &input_restrictions_list); + + void FixupArrivingTurnRestriction(const NodeID u, const NodeID v, const NodeID w); + void FixupStartingTurnRestriction(const NodeID u, const NodeID v, const NodeID w); + NodeID CheckForEmanatingIsOnlyTurn(const NodeID u, const NodeID v) const; + bool CheckIfTurnIsRestricted(const NodeID u, const NodeID v, const NodeID w) const; + + unsigned size() { return m_count; } + + private: + typedef std::pair RestrictionSource; + typedef std::pair RestrictionTarget; + typedef std::vector EmanatingRestrictionsVector; + typedef NodeBasedDynamicGraph::EdgeData EdgeData; + + unsigned m_count; + std::shared_ptr m_graph; + //! index -> list of (target, isOnly) + std::vector m_restriction_bucket_list; + //! maps (start, via) -> bucket index + boost::unordered_map m_restriction_map; +}; + +#endif diff --git a/Util/TimingUtil.h b/Util/TimingUtil.h new file mode 100644 index 00000000000..7e55321879e --- /dev/null +++ b/Util/TimingUtil.h @@ -0,0 +1,58 @@ +/* + +Copyright (c) 2013, Project OSRM, Dennis Luxen, others +All rights reserved. + +Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + +Redistributions of source code must retain the above copyright notice, this list +of conditions and the following disclaimer. +Redistributions in binary form must reproduce the above copyright notice, this +list of conditions and the following disclaimer in the documentation and/or +other materials provided with the distribution. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND +ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR +ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON +ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +*/ + +#ifndef TIMINGUTIL_H_ +#define TIMINGUTIL_H_ + +#ifdef _WIN32 +#include +#include +#include +void gettimeofday(struct timeval* t,void* timezone) { + struct _timeb timebuffer; + _ftime( &timebuffer ); + t->tv_sec=timebuffer.time; + t->tv_usec=1000*timebuffer.millitm; +} +#else +#include +#endif + +/** Returns a timestamp (now) in seconds (incl. a fractional part). */ +static inline double get_timestamp() { + struct timeval tp; + gettimeofday(&tp, NULL); + return double(tp.tv_sec) + tp.tv_usec / 1000000.; +} + +#define TIMER_START(_X) timeval _X##_start, _X##_stop; gettimeofday(&_X##_start, NULL) +#define TIMER_STOP(_X) gettimeofday(&_X##_stop, NULL); +#define TIMER_MSEC(_X) ((_X##_stop.tv_sec - _X##_start.tv_sec) * 1000.0 + (_X##_stop.tv_usec - _X##_start.tv_usec) / 1000.0) +#define TIMER_SEC(_X) ((_X##_stop.tv_sec - _X##_start.tv_sec) + (_X##_stop.tv_usec - _X##_start.tv_usec) / 1000.0 / 1000.0) +#define TIMER_MIN(_X) ((_X##_stop.tv_sec - _X##_start.tv_sec) / 60.0) + +#endif /* TIMINGUTIL_H_ */ diff --git a/prepare.cpp b/prepare.cpp index 48dd3b5ed95..1b664fdaac7 100644 --- a/prepare.cpp +++ b/prepare.cpp @@ -33,6 +33,7 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #include "DataStructures/QueryEdge.h" #include "DataStructures/StaticGraph.h" #include "DataStructures/StaticRTree.h" +#include "DataStructures/RestrictionMap.h" #include "Util/GitDescription.h" #include "Util/GraphLoader.h" #include "Util/LuaUtil.h" @@ -48,7 +49,6 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #include -#include #include #include @@ -274,12 +274,13 @@ int main(int argc, char *argv[]) */ SimpleLogger().Write() << "Generating edge-expanded graph representation"; - EdgeBasedGraphFactory *edge_based_graph_factor = - new EdgeBasedGraphFactory(number_of_node_based_nodes, - edge_list, + std::shared_ptr node_based_graph = NodeBasedDynamicGraphFromImportEdges(number_of_node_based_nodes, edge_list); + std::unique_ptr restriction_map = std::unique_ptr(new RestrictionMap(node_based_graph, restriction_list)); + EdgeBasedGraphFactory * edge_based_graph_factor = + new EdgeBasedGraphFactory(node_based_graph, + std::move(restriction_map), barrier_node_list, traffic_light_list, - restriction_list, internal_to_external_node_map, speed_profile); edge_list.clear(); @@ -302,6 +303,9 @@ int main(int argc, char *argv[]) edge_based_graph_factor->GetEdgeBasedNodes(node_based_edge_list); delete edge_based_graph_factor; + // TODO actually use scoping: Split this up in subfunctions + node_based_graph.reset(); + std::chrono::duration end_of_expansion_time = std::chrono::steady_clock::now() - startup_time;