Backport from Monav

This commit is contained in:
DennisOSRM 2011-11-14 13:12:22 +01:00
parent c6f6a7baed
commit afaca23f12

View File

@ -43,19 +43,16 @@ class Contractor {
private: private:
union _MiddleName { struct _EdgeBasedContractorEdgeData {
NodeID middle;
NodeID nameID;
};
struct _EdgeData {
unsigned distance; unsigned distance;
unsigned originalEdges : 29; unsigned originalEdges;
bool shortcut : 1; unsigned via;
bool forward : 1; unsigned nameID1;
bool backward : 1; unsigned nameID2;
short type:6; bool shortcut;
_MiddleName middleName; bool forward;
bool backward;
short turnType;
} data; } data;
struct _HeapData { struct _HeapData {
@ -64,7 +61,7 @@ private:
_HeapData( bool t ) : target(t) {} _HeapData( bool t ) : target(t) {}
}; };
typedef DynamicGraph< _EdgeData > _DynamicGraph; typedef DynamicGraph< _EdgeBasedContractorEdgeData > _DynamicGraph;
typedef BinaryHeap< NodeID, NodeID, int, _HeapData> _Heap; typedef BinaryHeap< NodeID, NodeID, int, _HeapData> _Heap;
typedef _DynamicGraph::InputEdge _ImportEdge; typedef _DynamicGraph::InputEdge _ImportEdge;
@ -118,8 +115,9 @@ public:
} }
#endif #endif
edge.data.shortcut = false; edge.data.shortcut = false;
edge.data.middleName.nameID = i->name(); edge.data.nameID1 = i->nameID1();
edge.data.type = i->type(); edge.data.nameID2 = i->nameID2();
edge.data.turnType = i->turnType();
edge.data.forward = i->isForward(); edge.data.forward = i->isForward();
edge.data.backward = i->isBackward(); edge.data.backward = i->isBackward();
edge.data.originalEdges = 1; edge.data.originalEdges = 1;
@ -129,7 +127,7 @@ public:
edge.data.backward = i->isForward(); edge.data.backward = i->isForward();
edges.push_back( edge ); edges.push_back( edge );
} }
// std::vector< InputEdge >().swap( inputEdges ); //free memory // std::vector< InputEdge >().swap( inputEdges ); //free memory
#ifdef _GLIBCXX_PARALLEL #ifdef _GLIBCXX_PARALLEL
__gnu_parallel::sort( edges.begin(), edges.end() ); __gnu_parallel::sort( edges.begin(), edges.end() );
#else #else
@ -139,9 +137,9 @@ public:
for ( NodeID i = 0; i < edges.size(); ) { for ( NodeID i = 0; i < edges.size(); ) {
const NodeID source = edges[i].source; const NodeID source = edges[i].source;
const NodeID target = edges[i].target; const NodeID target = edges[i].target;
const NodeID middle = edges[i].data.middleName.nameID; const NodeID via = edges[i].data.via;
const short type = edges[i].data.type; const short turnType = edges[i].data.turnType;
assert(type >= 0); assert(turnType >= 0);
//remove eigenloops //remove eigenloops
if ( source == target ) { if ( source == target ) {
i++; i++;
@ -153,9 +151,11 @@ public:
forwardEdge.target = backwardEdge.target = target; forwardEdge.target = backwardEdge.target = target;
forwardEdge.data.forward = backwardEdge.data.backward = true; forwardEdge.data.forward = backwardEdge.data.backward = true;
forwardEdge.data.backward = backwardEdge.data.forward = false; forwardEdge.data.backward = backwardEdge.data.forward = false;
forwardEdge.data.type = backwardEdge.data.type = type; forwardEdge.data.turnType = backwardEdge.data.turnType = turnType;
forwardEdge.data.middleName.nameID = backwardEdge.data.middleName.nameID = middle; forwardEdge.data.nameID1 = backwardEdge.data.nameID2 = edges[i].data.nameID1;
forwardEdge.data.nameID2 = backwardEdge.data.nameID1 = edges[i].data.nameID2;
forwardEdge.data.shortcut = backwardEdge.data.shortcut = false; forwardEdge.data.shortcut = backwardEdge.data.shortcut = false;
forwardEdge.data.via = backwardEdge.data.via = via;
forwardEdge.data.originalEdges = backwardEdge.data.originalEdges = 1; forwardEdge.data.originalEdges = backwardEdge.data.originalEdges = 1;
forwardEdge.data.distance = backwardEdge.data.distance = std::numeric_limits< int >::max(); forwardEdge.data.distance = backwardEdge.data.distance = std::numeric_limits< int >::max();
//remove parallel edges //remove parallel edges
@ -295,12 +295,12 @@ public:
const NodeID target = _graph->GetTarget( e ); const NodeID target = _graph->GetTarget( e );
if ( target != edge.target ) if ( target != edge.target )
continue; continue;
_EdgeData& data = _graph->GetEdgeData( e ); _EdgeBasedContractorEdgeData& data = _graph->GetEdgeData( e );
if ( data.distance != edge.data.distance ) if ( data.distance != edge.data.distance )
continue; continue;
if ( data.shortcut != edge.data.shortcut ) if ( data.shortcut != edge.data.shortcut )
continue; continue;
if ( data.middleName.middle != edge.data.middleName.middle ) if ( data.via != edge.data.via )
continue; continue;
data.forward |= edge.data.forward; data.forward |= edge.data.forward;
data.backward |= edge.data.backward; data.backward |= edge.data.backward;
@ -340,7 +340,7 @@ public:
} }
cout << "[contractor] checking sanity of generated data ..." << flush; cout << "[contractor] checking sanity of generated data ..." << flush;
_CheckCH<_EdgeData>(); _CheckCH<_EdgeBasedContractorEdgeData>();
cout << "ok" << endl; cout << "ok" << endl;
std::cout << "[contractor] max level: " << maxDepth << std::endl; std::cout << "[contractor] max level: " << maxDepth << std::endl;
} }
@ -351,20 +351,15 @@ public:
for ( NodeID node = 0; node < numberOfNodes; ++node ) { for ( NodeID node = 0; node < numberOfNodes; ++node ) {
for ( _DynamicGraph::EdgeIterator edge = _graph->BeginEdges( node ), endEdges = _graph->EndEdges( node ); edge < endEdges; edge++ ) { for ( _DynamicGraph::EdgeIterator edge = _graph->BeginEdges( node ), endEdges = _graph->EndEdges( node ); edge < endEdges; edge++ ) {
const NodeID target = _graph->GetTarget( edge ); const NodeID target = _graph->GetTarget( edge );
const _EdgeData& data = _graph->GetEdgeData( edge ); const _EdgeBasedContractorEdgeData& data = _graph->GetEdgeData( edge );
Edge newEdge; Edge newEdge;
newEdge.source = node; newEdge.source = node;
newEdge.target = target; newEdge.target = target;
newEdge.data.distance = data.distance; newEdge.data.distance = data.distance;
newEdge.data.shortcut = data.shortcut; newEdge.data.shortcut = data.shortcut;
if(data.shortcut) { newEdge.data.via = data.via;
newEdge.data.middleName.middle = data.middleName.middle; newEdge.data.nameID1 = data.nameID1;
newEdge.data.type = -1; newEdge.data.nameID2 = data.nameID2;
} else {
newEdge.data.middleName.nameID = data.middleName.nameID;
newEdge.data.type = data.type;
assert(newEdge.data.type >= 0);
}
newEdge.data.forward = data.forward; newEdge.data.forward = data.forward;
newEdge.data.backward = data.backward; newEdge.data.backward = data.backward;
@ -383,6 +378,7 @@ private:
_Heap& heap = data->heap; _Heap& heap = data->heap;
unsigned nodes = 0; unsigned nodes = 0;
unsigned targetsFound = 0;
while ( heap.Size() > 0 ) { while ( heap.Size() > 0 ) {
const NodeID node = heap.DeleteMin(); const NodeID node = heap.DeleteMin();
const int distance = heap.GetKey( node ); const int distance = heap.GetKey( node );
@ -392,9 +388,15 @@ private:
if ( distance > maxDistance ) if ( distance > maxDistance )
return; return;
if ( heap.GetData( node ).target ) {
targetsFound++;
if ( targetsFound >= numTargets )
return;
}
//iterate over all edges of node //iterate over all edges of node
for ( _DynamicGraph::EdgeIterator edge = _graph->BeginEdges( node ), endEdges = _graph->EndEdges( node ); edge != endEdges; ++edge ) { for ( _DynamicGraph::EdgeIterator edge = _graph->BeginEdges( node ), endEdges = _graph->EndEdges( node ); edge != endEdges; ++edge ) {
const _EdgeData& data = _graph->GetEdgeData( edge ); const _EdgeBasedContractorEdgeData& data = _graph->GetEdgeData( edge );
if ( !data.forward ) if ( !data.forward )
continue; continue;
const NodeID to = _graph->GetTarget( edge ); const NodeID to = _graph->GetTarget( edge );
@ -442,8 +444,8 @@ private:
for ( _DynamicGraph::EdgeIterator edge = _graph->BeginEdges( node ), endEdges = _graph->EndEdges( node ); edge != endEdges; ++edge ) { for ( _DynamicGraph::EdgeIterator edge = _graph->BeginEdges( node ), endEdges = _graph->EndEdges( node ); edge != endEdges; ++edge ) {
const NodeID start = node; const NodeID start = node;
const NodeID target = _graph->GetTarget( edge ); const NodeID target = _graph->GetTarget( edge );
const _EdgeData& data = _graph->GetEdgeData( edge ); const _EdgeBasedContractorEdgeData& data = _graph->GetEdgeData( edge );
const NodeID middle = data.middleName.middle; const NodeID middle = data.via;
assert(start != target); assert(start != target);
if(data.shortcut) if(data.shortcut)
{ {
@ -466,7 +468,7 @@ private:
template< bool Simulate > bool _Contract( _ThreadData* data, NodeID node, _ContractionInformation* stats = NULL ) { template< bool Simulate > bool _Contract( _ThreadData* data, NodeID node, _ContractionInformation* stats = NULL ) {
_Heap& heap = data->heap; _Heap& heap = data->heap;
for ( _DynamicGraph::EdgeIterator inEdge = _graph->BeginEdges( node ), endInEdges = _graph->EndEdges( node ); inEdge != endInEdges; ++inEdge ) { for ( _DynamicGraph::EdgeIterator inEdge = _graph->BeginEdges( node ), endInEdges = _graph->EndEdges( node ); inEdge != endInEdges; ++inEdge ) {
const _EdgeData& inData = _graph->GetEdgeData( inEdge ); const _EdgeBasedContractorEdgeData& inData = _graph->GetEdgeData( inEdge );
const NodeID source = _graph->GetTarget( inEdge ); const NodeID source = _graph->GetTarget( inEdge );
if ( Simulate ) { if ( Simulate ) {
assert( stats != NULL ); assert( stats != NULL );
@ -482,18 +484,22 @@ private:
if ( node != source ) if ( node != source )
heap.Insert( node, inData.distance, _HeapData() ); heap.Insert( node, inData.distance, _HeapData() );
int maxDistance = 0; int maxDistance = 0;
unsigned numTargets = 0;
for ( _DynamicGraph::EdgeIterator outEdge = _graph->BeginEdges( node ), endOutEdges = _graph->EndEdges( node ); outEdge != endOutEdges; ++outEdge ) { for ( _DynamicGraph::EdgeIterator outEdge = _graph->BeginEdges( node ), endOutEdges = _graph->EndEdges( node ); outEdge != endOutEdges; ++outEdge ) {
const _EdgeData& outData = _graph->GetEdgeData( outEdge ); const _EdgeBasedContractorEdgeData& outData = _graph->GetEdgeData( outEdge );
if ( !outData.forward ) if ( !outData.forward )
continue; continue;
const NodeID target = _graph->GetTarget( outEdge ); const NodeID target = _graph->GetTarget( outEdge );
const int pathDistance = inData.distance + outData.distance; const int pathDistance = inData.distance + outData.distance;
maxDistance = (std::max)( maxDistance, pathDistance ); maxDistance = (std::max)( maxDistance, pathDistance );
if ( !heap.WasInserted( target ) ) if ( !heap.WasInserted( target ) ) {
heap.Insert( target, pathDistance, _HeapData(true) ); heap.Insert( target, pathDistance, _HeapData( true ) );
else if ( pathDistance < heap.GetKey( target ) ) numTargets++;
} else if ( pathDistance < heap.GetKey( target ) ) {
heap.DecreaseKey( target, pathDistance ); heap.DecreaseKey( target, pathDistance );
}
} }
if( Simulate ) if( Simulate )
@ -502,7 +508,7 @@ private:
_Dijkstra( source, maxDistance, 1000, data ); _Dijkstra( source, maxDistance, 1000, data );
for ( _DynamicGraph::EdgeIterator outEdge = _graph->BeginEdges( node ), endOutEdges = _graph->EndEdges( node ); outEdge != endOutEdges; ++outEdge ) { for ( _DynamicGraph::EdgeIterator outEdge = _graph->BeginEdges( node ), endOutEdges = _graph->EndEdges( node ); outEdge != endOutEdges; ++outEdge ) {
const _EdgeData& outData = _graph->GetEdgeData( outEdge ); const _EdgeBasedContractorEdgeData& outData = _graph->GetEdgeData( outEdge );
if ( !outData.forward ) if ( !outData.forward )
continue; continue;
const NodeID target = _graph->GetTarget( outEdge ); const NodeID target = _graph->GetTarget( outEdge );
@ -521,9 +527,10 @@ private:
newEdge.data.distance = pathDistance; newEdge.data.distance = pathDistance;
newEdge.data.forward = true; newEdge.data.forward = true;
newEdge.data.backward = false; newEdge.data.backward = false;
newEdge.data.middleName.middle = node; newEdge.data.via = node;
newEdge.data.shortcut = true; newEdge.data.shortcut = true;
newEdge.data.originalEdges = outData.originalEdges + inData.originalEdges; newEdge.data.originalEdges = outData.originalEdges + inData.originalEdges;
data->insertedEdges.push_back( newEdge ); data->insertedEdges.push_back( newEdge );
std::swap( newEdge.source, newEdge.target ); std::swap( newEdge.source, newEdge.target );
newEdge.data.forward = false; newEdge.data.forward = false;