Refactoring StronglyConnectedComponents.h

This commit is contained in:
Dennis Luxen 2013-08-19 16:04:00 +02:00
parent dabc9589e9
commit e1620b8fa2

View File

@ -35,11 +35,13 @@ Strongly connected components using Tarjan's Algorithm
#include "../Util/SimpleLogger.h" #include "../Util/SimpleLogger.h"
#include <boost/assert.hpp>
#include <boost/filesystem.hpp> #include <boost/filesystem.hpp>
#include <boost/foreach.hpp> #include <boost/foreach.hpp>
#include <boost/integer.hpp> #include <boost/integer.hpp>
#include <boost/make_shared.hpp> #include <boost/make_shared.hpp>
#include <boost/unordered_map.hpp> #include <boost/unordered_map.hpp>
#include <boost/unordered_set.hpp>
#ifdef __APPLE__ #ifdef __APPLE__
#include <gdal.h> #include <gdal.h>
@ -48,7 +50,7 @@ Strongly connected components using Tarjan's Algorithm
#include <gdal/gdal.h> #include <gdal/gdal.h>
#include <gdal/ogrsf_frmts.h> #include <gdal/ogrsf_frmts.h>
#endif #endif
#include <cassert>
#include <stack> #include <stack>
#include <vector> #include <vector>
@ -64,7 +66,6 @@ private:
struct TarjanEdgeData { struct TarjanEdgeData {
int distance; int distance;
unsigned edgeBasedNodeID;
unsigned nameID:31; unsigned nameID:31;
bool shortcut:1; bool shortcut:1;
short type; short type;
@ -77,26 +78,28 @@ private:
}; };
struct TarjanStackFrame { struct TarjanStackFrame {
explicit TarjanStackFrame(NodeID _v, NodeID p) : v(_v), parent(p) {} explicit TarjanStackFrame(
NodeID v,
NodeID parent
) : v(v), parent(parent) { }
NodeID v; NodeID v;
NodeID parent; NodeID parent;
}; };
typedef DynamicGraph<TarjanEdgeData> TarjanDynamicGraph; typedef DynamicGraph<TarjanEdgeData> TarjanDynamicGraph;
typedef TarjanDynamicGraph::InputEdge TarjanEdge; typedef TarjanDynamicGraph::InputEdge TarjanEdge;
typedef std::pair<NodeID, NodeID> RestrictionSource; typedef std::pair<NodeID, NodeID> RestrictionSource;
typedef std::pair<NodeID, bool> RestrictionTarget; typedef std::pair<NodeID, bool> restriction_target;
typedef std::vector<RestrictionTarget> EmanatingRestrictionsVector; typedef std::vector<restriction_target> EmanatingRestrictionsVector;
typedef boost::unordered_map<RestrictionSource, unsigned > RestrictionMap; typedef boost::unordered_map<RestrictionSource, unsigned > RestrictionMap;
std::vector<NodeInfo> inputNodeInfoList; std::vector<NodeInfo> m_coordinate_list;
unsigned numberOfTurnRestrictions; std::vector<EmanatingRestrictionsVector> m_restriction_bucket_list;
boost::shared_ptr<TarjanDynamicGraph> _nodeBasedGraph; boost::shared_ptr<TarjanDynamicGraph> m_node_based_graph;
boost::unordered_map<NodeID, bool> _barrierNodes; boost::unordered_set<NodeID> m_barrier_node_list;
boost::unordered_map<NodeID, bool> _trafficLights; boost::unordered_set<NodeID> m_traffic_light_list;
unsigned m_restriction_counter;
std::vector<EmanatingRestrictionsVector> _restrictionBucketVector; RestrictionMap m_restriction_map;
RestrictionMap _restrictionMap;
struct EdgeBasedNode { struct EdgeBasedNode {
bool operator<(const EdgeBasedNode & other) const { bool operator<(const EdgeBasedNode & other) const {
@ -116,93 +119,99 @@ private:
bool ignoreInGrid:1; bool ignoreInGrid:1;
}; };
DeallocatingVector<EdgeBasedNode> edgeBasedNodes;
public: public:
TarjanSCC( TarjanSCC(
int nodes, int number_of_nodes,
std::vector<NodeBasedEdge> & inputEdges, std::vector<NodeBasedEdge> & input_edges,
std::vector<NodeID> & bn, std::vector<NodeID> & bn,
std::vector<NodeID> & tl, std::vector<NodeID> & tl,
std::vector<TurnRestriction> & irs, std::vector<TurnRestriction> & irs,
std::vector<NodeInfo> & nI std::vector<NodeInfo> & nI
) : ) :
inputNodeInfoList(nI), m_coordinate_list(nI),
numberOfTurnRestrictions(irs.size()) m_restriction_counter(irs.size())
{ {
BOOST_FOREACH(const TurnRestriction & restriction, irs) { BOOST_FOREACH(const TurnRestriction & restriction, irs) {
std::pair<NodeID, NodeID> restrictionSource = std::make_pair( std::pair<NodeID, NodeID> restrictionSource = std::make_pair(
restriction.fromNode, restriction.viaNode restriction.fromNode, restriction.viaNode
); );
unsigned index; unsigned index;
RestrictionMap::iterator restrIter = _restrictionMap.find(restrictionSource); RestrictionMap::iterator restriction_iterator = m_restriction_map.find(restrictionSource);
if(restrIter == _restrictionMap.end()) { if(restriction_iterator == m_restriction_map.end()) {
index = _restrictionBucketVector.size(); index = m_restriction_bucket_list.size();
_restrictionBucketVector.resize(index+1); m_restriction_bucket_list.resize(index+1);
_restrictionMap[restrictionSource] = index; m_restriction_map[restrictionSource] = index;
} else { } else {
index = restrIter->second; index = restriction_iterator->second;
//Map already contains an is_only_*-restriction //Map already contains an is_only_*-restriction
if(_restrictionBucketVector.at(index).begin()->second) if(m_restriction_bucket_list.at(index).begin()->second) {
continue; continue;
else if(restriction.flags.isOnly){ } else if(restriction.flags.isOnly) {
//We are going to insert an is_only_*-restriction. There can be only one. //We are going to insert an is_only_*-restriction. There can be only one.
_restrictionBucketVector.at(index).clear(); m_restriction_bucket_list.at(index).clear();
} }
} }
_restrictionBucketVector.at(index).push_back( m_restriction_bucket_list.at(index).push_back(
std::make_pair(restriction.toNode, restriction.flags.isOnly) std::make_pair(restriction.toNode, restriction.flags.isOnly)
); );
} }
BOOST_FOREACH(NodeID id, bn) { m_barrier_node_list.insert(bn.begin(), bn.end());
_barrierNodes[id] = true; m_traffic_light_list.insert(tl.begin(), tl.end());
}
BOOST_FOREACH(NodeID id, tl) {
_trafficLights[id] = true;
}
DeallocatingVector< TarjanEdge > edges;
for ( std::vector< NodeBasedEdge >::const_iterator i = inputEdges.begin(); i != inputEdges.end(); ++i ) {
DeallocatingVector< TarjanEdge > edge_list;
BOOST_FOREACH(const NodeBasedEdge & input_edge, input_edges) {
TarjanEdge edge; TarjanEdge edge;
if(!i->isForward()) { if(!input_edge.isForward()) {
edge.source = i->target(); edge.source = input_edge.target();
edge.target = i->source(); edge.target = input_edge.source();
edge.data.backward = i->isForward(); edge.data.backward = input_edge.isForward();
edge.data.forward = i->isBackward(); edge.data.forward = input_edge.isBackward();
} else { } else {
edge.source = i->source(); edge.source = input_edge.source();
edge.target = i->target(); edge.target = input_edge.target();
edge.data.forward = i->isForward(); edge.data.forward = input_edge.isForward();
edge.data.backward = i->isBackward(); edge.data.backward = input_edge.isBackward();
} }
if(edge.source == edge.target) if(edge.source == edge.target) {
continue; continue;
}
edge.data.distance = (std::max)((int)i->weight(), 1 ); edge.data.distance = (std::max)((int)input_edge.weight(), 1 );
assert( edge.data.distance > 0 ); BOOST_ASSERT( edge.data.distance > 0 );
edge.data.shortcut = false; edge.data.shortcut = false;
edge.data.roundabout = i->isRoundabout(); edge.data.roundabout = input_edge.isRoundabout();
edge.data.ignoreInGrid = i->ignoreInGrid(); edge.data.ignoreInGrid = input_edge.ignoreInGrid();
edge.data.nameID = i->name(); edge.data.nameID = input_edge.name();
edge.data.type = i->type(); edge.data.type = input_edge.type();
edge.data.isAccessRestricted = i->isAccessRestricted(); edge.data.isAccessRestricted = input_edge.isAccessRestricted();
edge.data.edgeBasedNodeID = edges.size();
edge.data.reversedEdge = false; edge.data.reversedEdge = false;
edges.push_back( edge ); edge_list.push_back( edge );
if( edge.data.backward ) { if( edge.data.backward ) {
std::swap( edge.source, edge.target ); std::swap( edge.source, edge.target );
edge.data.forward = i->isBackward(); edge.data.forward = input_edge.isBackward();
edge.data.backward = i->isForward(); edge.data.backward = input_edge.isForward();
edge.data.edgeBasedNodeID = edges.size();
edge.data.reversedEdge = true; edge.data.reversedEdge = true;
edges.push_back( edge ); edge_list.push_back( edge );
} }
} }
std::vector<NodeBasedEdge>().swap(inputEdges); std::vector<NodeBasedEdge>().swap(input_edges);
std::sort( edges.begin(), edges.end() ); BOOST_ASSERT_MSG(
_nodeBasedGraph = boost::make_shared<TarjanDynamicGraph>( nodes, edges ); 0 == input_edges.size() && 0 == input_edges.capacity(),
"input edge vector not properly deallocated"
);
std::sort( edge_list.begin(), edge_list.end() );
m_node_based_graph = boost::make_shared<TarjanDynamicGraph>(
number_of_nodes,
edge_list
);
}
~TarjanSCC() {
m_node_based_graph.reset();
} }
void Run() { void Run() {
@ -211,162 +220,203 @@ public:
DeleteFileIfExists("component.shx"); DeleteFileIfExists("component.shx");
DeleteFileIfExists("component.shp"); DeleteFileIfExists("component.shp");
Percent p(_nodeBasedGraph->GetNumberOfNodes()); Percent p(m_node_based_graph->GetNumberOfNodes());
const char *pszDriverName = "ESRI Shapefile";
OGRSFDriver *poDriver;
OGRRegisterAll(); OGRRegisterAll();
poDriver = OGRSFDriverRegistrar::GetRegistrar()->GetDriverByName( const char *pszDriverName = "ESRI Shapefile";
pszDriverName ); OGRSFDriver * poDriver = OGRSFDriverRegistrar::GetRegistrar()->
if( poDriver == NULL ) GetDriverByName( pszDriverName );
{ if( NULL == poDriver ) {
printf( "%s driver not available.\n", pszDriverName ); throw OSRMException("ESRI Shapefile driver not available");
exit( 1 );
} }
OGRDataSource *poDS; OGRDataSource * poDS = poDriver->CreateDataSource(
"component.shp",
NULL
);
poDS = poDriver->CreateDataSource( "component.shp", NULL ); if( NULL == poDS ) {
if( poDS == NULL ) { throw OSRMException("Creation of output file failed");
printf( "Creation of output file failed.\n" );
exit( 1 );
} }
OGRLayer *poLayer; OGRLayer * poLayer = poDS->CreateLayer(
"component",
NULL,
wkbLineString,
NULL
);
poLayer = poDS->CreateLayer( "component", NULL, wkbLineString, NULL ); if( NULL == poLayer ) {
if( poLayer == NULL ) { throw OSRMException("Layer creation failed.");
printf( "Layer creation failed.\n" );
exit( 1 );
} }
//The following is a hack to distinguish between stuff that happens
//The following is a hack to distinguish between stuff that happens before the recursive call and stuff that happens after //before the recursive call and stuff that happens after
std::stack<std::pair<bool, TarjanStackFrame> > recursionStack; //true = stuff before, false = stuff after call std::stack<std::pair<bool, TarjanStackFrame> > recursion_stack;
std::stack<NodeID> tarjanStack; //true = stuff before, false = stuff after call
std::vector<unsigned> componentsIndex(_nodeBasedGraph->GetNumberOfNodes(), UINT_MAX); std::stack<NodeID> tarjan_stack;
std::vector<NodeID> vectorOfComponentSizes; std::vector<unsigned> components_index(
std::vector<TarjanNode> tarjanNodes(_nodeBasedGraph->GetNumberOfNodes()); m_node_based_graph->GetNumberOfNodes(),
unsigned currentComponent = 0, sizeOfCurrentComponent = 0; UINT_MAX
);
std::vector<NodeID> component_size_vector;
std::vector<TarjanNode> tarjan_node_list(
m_node_based_graph->GetNumberOfNodes()
);
unsigned component_index = 0, size_of_current_component = 0;
int index = 0; int index = 0;
for(NodeID node = 0, endNodes = _nodeBasedGraph->GetNumberOfNodes(); node < endNodes; ++node) { for(
if(UINT_MAX == componentsIndex[node]) { NodeID node = 0, last_node = m_node_based_graph->GetNumberOfNodes();
recursionStack.push(std::make_pair(true, TarjanStackFrame(node,node)) ); node < last_node;
++node
) {
if(UINT_MAX == components_index[node]) {
recursion_stack.push(
std::make_pair(true, TarjanStackFrame(node,node))
);
} }
while(!recursionStack.empty()) { while(!recursion_stack.empty()) {
bool beforeRecursion = recursionStack.top().first; bool before_recursion = recursion_stack.top().first;
TarjanStackFrame currentFrame = recursionStack.top().second; TarjanStackFrame currentFrame = recursion_stack.top().second;
NodeID v = currentFrame.v; NodeID v = currentFrame.v;
// SimpleLogger().Write() << "popping node " << v << (beforeRecursion ? " before " : " after ") << "recursion"; recursion_stack.pop();
recursionStack.pop();
if(beforeRecursion) { if(before_recursion) {
//Mark frame to handle tail of recursion //Mark frame to handle tail of recursion
recursionStack.push(std::make_pair(false, currentFrame)); recursion_stack.push(std::make_pair(false, currentFrame));
//Mark essential information for SCC //Mark essential information for SCC
tarjanNodes[v].index = index; tarjan_node_list[v].index = index;
tarjanNodes[v].lowlink = index; tarjan_node_list[v].lowlink = index;
tarjanStack.push(v); tarjan_stack.push(v);
tarjanNodes[v].onStack = true; tarjan_node_list[v].onStack = true;
++index; ++index;
// SimpleLogger().Write() << "pushing " << v << " onto tarjan stack, idx[" << v << "]=" << tarjanNodes[v].index << ", lowlink["<< v << "]=" << tarjanNodes[v].lowlink;
//Traverse outgoing edges //Traverse outgoing edges
for(TarjanDynamicGraph::EdgeIterator e2 = _nodeBasedGraph->BeginEdges(v); e2 < _nodeBasedGraph->EndEdges(v); ++e2) { for(
TarjanDynamicGraph::NodeIterator vprime = _nodeBasedGraph->GetTarget(e2); TarjanDynamicGraph::EdgeIterator e2 = m_node_based_graph->BeginEdges(v);
// SimpleLogger().Write() << "traversing edge (" << v << "," << vprime << ")"; e2 < m_node_based_graph->EndEdges(v);
if(UINT_MAX == tarjanNodes[vprime].index) { ++e2
) {
recursionStack.push(std::make_pair(true,TarjanStackFrame(vprime, v))); const TarjanDynamicGraph::NodeIterator vprime =
m_node_based_graph->GetTarget(e2);
if(UINT_MAX == tarjan_node_list[vprime].index) {
recursion_stack.push(
std::make_pair(
true,
TarjanStackFrame(vprime, v)
)
);
} else { } else {
// SimpleLogger().Write() << "Node " << vprime << " is already explored"; if(
if(tarjanNodes[vprime].onStack) { tarjan_node_list[vprime].onStack &&
unsigned newLowlink = std::min(tarjanNodes[v].lowlink, tarjanNodes[vprime].index); tarjan_node_list[vprime].index < tarjan_node_list[v].lowlink
// SimpleLogger().Write() << "Setting lowlink[" << v << "] from " << tarjanNodes[v].lowlink << " to " << newLowlink; ) {
tarjanNodes[v].lowlink = newLowlink; tarjan_node_list[v].lowlink = tarjan_node_list[vprime].index;
// } else {
// SimpleLogger().Write() << "But node " << vprime << " is not on stack";
} }
} }
} }
} else { } else {
tarjan_node_list[currentFrame.parent].lowlink =
// SimpleLogger().Write() << "we are at the end of recursion and checking node " << v; std::min(
{ // setting lowlink in its own scope so it does not pollute namespace tarjan_node_list[currentFrame.parent].lowlink,
// NodeID parent = (UINT_MAX == tarjanNodes[v].parent ? v : tarjanNodes[v].parent ); tarjan_node_list[v].lowlink
// SimpleLogger().Write() << "parent=" << currentFrame.parent; );
// SimpleLogger().Write() << "tarjanNodes[" << v << "].lowlink=" << tarjanNodes[v].lowlink << ", tarjanNodes[" << currentFrame.parent << "].lowlink=" << tarjanNodes[currentFrame.parent].lowlink;
//Note the index shift by 1 compared to the recursive version
tarjanNodes[currentFrame.parent].lowlink = std::min(tarjanNodes[currentFrame.parent].lowlink, tarjanNodes[v].lowlink);
// SimpleLogger().Write() << "Setting tarjanNodes[" << currentFrame.parent <<"].lowlink=" << tarjanNodes[currentFrame.parent].lowlink;
}
// SimpleLogger().Write() << "tarjanNodes[" << v << "].lowlink=" << tarjanNodes[v].lowlink << ", tarjanNodes[" << v << "].index=" << tarjanNodes[v].index;
//after recursion, lets do cycle checking //after recursion, lets do cycle checking
//Check if we found a cycle. This is the bottom part of the recursion //Check if we found a cycle. This is the bottom part of the recursion
if(tarjanNodes[v].lowlink == tarjanNodes[v].index) { if(tarjan_node_list[v].lowlink == tarjan_node_list[v].index) {
NodeID vprime; NodeID vprime;
do { do {
// SimpleLogger().Write() << "identified component " << currentComponent << ": " << tarjanStack.top(); vprime = tarjan_stack.top(); tarjan_stack.pop();
vprime = tarjanStack.top(); tarjanStack.pop(); tarjan_node_list[vprime].onStack = false;
tarjanNodes[vprime].onStack = false; components_index[vprime] = component_index;
componentsIndex[vprime] = currentComponent; ++size_of_current_component;
++sizeOfCurrentComponent;
} while( v != vprime); } while( v != vprime);
vectorOfComponentSizes.push_back(sizeOfCurrentComponent);
if(sizeOfCurrentComponent > 1000) component_size_vector.push_back(size_of_current_component);
SimpleLogger().Write() << "large component [" << currentComponent << "]=" << sizeOfCurrentComponent;
++currentComponent; if(size_of_current_component > 1000) {
sizeOfCurrentComponent = 0; SimpleLogger().Write() <<
"large component [" << component_index << "]=" <<
size_of_current_component;
}
++component_index;
size_of_current_component = 0;
} }
} }
} }
} }
SimpleLogger().Write() << "identified: " << vectorOfComponentSizes.size() << " many components, marking small components"; SimpleLogger().Write() <<
"identified: " << component_size_vector.size() <<
" many components, marking small components";
int singleCounter = 0; unsigned size_one_counter = 0;
for(unsigned i = 0; i < vectorOfComponentSizes.size(); ++i){ for(unsigned i = 0, end = component_size_vector.size(); i < end; ++i){
if(1 == vectorOfComponentSizes[i]) if(1 == component_size_vector[i]) {
++singleCounter; ++size_one_counter;
}
} }
SimpleLogger().Write() << "identified " << singleCounter << " SCCs of size 1";
SimpleLogger().Write() <<
"identified " << size_one_counter << " SCCs of size 1";
uint64_t total_network_distance = 0; uint64_t total_network_distance = 0;
p.reinit(_nodeBasedGraph->GetNumberOfNodes()); p.reinit(m_node_based_graph->GetNumberOfNodes());
for(TarjanDynamicGraph::NodeIterator u = 0; u < _nodeBasedGraph->GetNumberOfNodes(); ++u ) { for(
TarjanDynamicGraph::NodeIterator u = 0, last_u_node = m_node_based_graph->GetNumberOfNodes();
u < last_u_node;
++u
) {
p.printIncrement(); p.printIncrement();
for(TarjanDynamicGraph::EdgeIterator e1 = _nodeBasedGraph->BeginEdges(u); e1 < _nodeBasedGraph->EndEdges(u); ++e1) { for(
if(_nodeBasedGraph->GetEdgeData(e1).reversedEdge) { TarjanDynamicGraph::EdgeIterator e1 = m_node_based_graph->BeginEdges(u), last_edge = m_node_based_graph->EndEdges(u);
e1 < last_edge;
++e1
) {
if(!m_node_based_graph->GetEdgeData(e1).reversedEdge) {
continue; continue;
} }
TarjanDynamicGraph::NodeIterator v = _nodeBasedGraph->GetTarget(e1); const TarjanDynamicGraph::NodeIterator v = m_node_based_graph->GetTarget(e1);
total_network_distance += 100*ApproximateDistance( total_network_distance += 100*ApproximateDistance(
inputNodeInfoList[u].lat, m_coordinate_list[u].lat,
inputNodeInfoList[u].lon, m_coordinate_list[u].lon,
inputNodeInfoList[v].lat, m_coordinate_list[v].lat,
inputNodeInfoList[v].lon m_coordinate_list[v].lon
); );
if(_nodeBasedGraph->GetEdgeData(e1).type != SHRT_MAX) { if( SHRT_MAX != m_node_based_graph->GetEdgeData(e1).type ) {
assert(e1 != UINT_MAX); BOOST_ASSERT(e1 != UINT_MAX);
assert(u != UINT_MAX); BOOST_ASSERT(u != UINT_MAX);
assert(v != UINT_MAX); BOOST_ASSERT(v != UINT_MAX);
const unsigned size_of_containing_component =
std::min(
component_size_vector[components_index[u]],
component_size_vector[components_index[v]]
);
//edges that end on bollard nodes may actually be in two distinct components //edges that end on bollard nodes may actually be in two distinct components
if(std::min(vectorOfComponentSizes[componentsIndex[u]], vectorOfComponentSizes[componentsIndex[v]]) < 10) { if(size_of_containing_component < 10) {
//INFO("(" << inputNodeInfoList[u].lat/COORDINATE_PRECISION << ";" << inputNodeInfoList[u].lon/COORDINATE_PRECISION << ") -> (" << inputNodeInfoList[v].lat/COORDINATE_PRECISION << ";" << inputNodeInfoList[v].lon/COORDINATE_PRECISION << ")");
OGRLineString lineString; OGRLineString lineString;
lineString.addPoint(inputNodeInfoList[u].lon/COORDINATE_PRECISION, inputNodeInfoList[u].lat/COORDINATE_PRECISION); lineString.addPoint(
lineString.addPoint(inputNodeInfoList[v].lon/COORDINATE_PRECISION, inputNodeInfoList[v].lat/COORDINATE_PRECISION); m_coordinate_list[u].lon/COORDINATE_PRECISION,
OGRFeature *poFeature; m_coordinate_list[u].lat/COORDINATE_PRECISION
poFeature = OGRFeature::CreateFeature( poLayer->GetLayerDefn() ); );
lineString.addPoint(
m_coordinate_list[v].lon/COORDINATE_PRECISION,
m_coordinate_list[v].lat/COORDINATE_PRECISION
);
OGRFeature * poFeature = OGRFeature::CreateFeature(
poLayer->GetLayerDefn()
);
poFeature->SetGeometry( &lineString ); poFeature->SetGeometry( &lineString );
if( poLayer->CreateFeature( poFeature ) != OGRERR_NONE ) { if( OGRERR_NONE != poLayer->CreateFeature(poFeature) ) {
throw OSRMException( throw OSRMException(
"Failed to create feature in shapefile." "Failed to create feature in shapefile."
); );
@ -377,39 +427,66 @@ public:
} }
} }
OGRDataSource::DestroyDataSource( poDS ); OGRDataSource::DestroyDataSource( poDS );
std::vector<NodeID>().swap(vectorOfComponentSizes); std::vector<NodeID>().swap(component_size_vector);
std::vector<NodeID>().swap(componentsIndex); BOOST_ASSERT_MSG(
SimpleLogger().Write() << "total network distance: " << (uint64_t)total_network_distance/100/1000. << " km"; 0 == component_size_vector.size() &&
0 == component_size_vector.capacity(),
"component_size_vector not properly deallocated"
);
std::vector<NodeID>().swap(components_index);
BOOST_ASSERT_MSG(
0 == components_index.size() && 0 == components_index.capacity(),
"icomponents_index not properly deallocated"
);
SimpleLogger().Write()
<< "total network distance: " <<
(uint64_t)total_network_distance/100/1000. <<
" km";
} }
private: private:
unsigned CheckForEmanatingIsOnlyTurn(const NodeID u, const NodeID v) const { unsigned CheckForEmanatingIsOnlyTurn(const NodeID u, const NodeID v) const {
std::pair < NodeID, NodeID > restrictionSource = std::make_pair(u, v); std::pair < NodeID, NodeID > restriction_source = std::make_pair(u, v);
RestrictionMap::const_iterator restrIter = _restrictionMap.find(restrictionSource); RestrictionMap::const_iterator restriction_iterator = m_restriction_map.find(restriction_source);
if (restrIter != _restrictionMap.end()) { if (restriction_iterator != m_restriction_map.end()) {
unsigned index = restrIter->second; const unsigned index = restriction_iterator->second;
BOOST_FOREACH(RestrictionSource restrictionTarget, _restrictionBucketVector.at(index)) { BOOST_FOREACH(
if(restrictionTarget.second) { const RestrictionSource & restriction_target,
return restrictionTarget.first; m_restriction_bucket_list.at(index)
) {
if(restriction_target.second) {
return restriction_target.first;
} }
} }
} }
return UINT_MAX; return UINT_MAX;
} }
bool CheckIfTurnIsRestricted(const NodeID u, const NodeID v, const NodeID w) const {
bool CheckIfTurnIsRestricted(
const NodeID u,
const NodeID v,
const NodeID w
) const {
//only add an edge if turn is not a U-turn except it is the end of dead-end street. //only add an edge if turn is not a U-turn except it is the end of dead-end street.
std::pair < NodeID, NodeID > restrictionSource = std::make_pair(u, v); std::pair < NodeID, NodeID > restriction_source = std::make_pair(u, v);
RestrictionMap::const_iterator restrIter = _restrictionMap.find(restrictionSource); RestrictionMap::const_iterator restriction_iterator = m_restriction_map.find(restriction_source);
if (restrIter != _restrictionMap.end()) { if (restriction_iterator != m_restriction_map.end()) {
unsigned index = restrIter->second; const unsigned index = restriction_iterator->second;
BOOST_FOREACH(RestrictionTarget restrictionTarget, _restrictionBucketVector.at(index)) { BOOST_FOREACH(
if(w == restrictionTarget.first) const restriction_target & restriction_target,
m_restriction_bucket_list.at(index)
) {
if(w == restriction_target.first) {
return true; return true;
}
} }
} }
return false; return false;
} }
void DeleteFileIfExists(const std::string file_name) const { void DeleteFileIfExists(const std::string & file_name) const {
if (boost::filesystem::exists(file_name) ) { if (boost::filesystem::exists(file_name) ) {
boost::filesystem::remove(file_name); boost::filesystem::remove(file_name);
} }