Temporary edges saved in stxxl store; const & inline where feasible;

more efficient checks for divide-by-zero; witness search omits middle
node; Removed unneeded temporaries; Removed superflous includes; Saving
4 Bytes per node during contraction.
This commit is contained in:
DennisOSRM 2012-11-19 11:43:46 +01:00
parent b51f98fe0c
commit 5faf8d6951

View File

@ -22,16 +22,18 @@ or see http://www.gnu.org/licenses/agpl.txt.
#define CONTRACTOR_H_INCLUDED #define CONTRACTOR_H_INCLUDED
#include <algorithm> #include <algorithm>
#include <limits> #include <limits>
#include <queue>
#include <set>
#include <vector> #include <vector>
#include <cfloat> #include <cfloat>
#include <ctime> #include <ctime>
#include <boost/foreach.hpp>
#include <boost/lambda/lambda.hpp>
#include <boost/make_shared.hpp> #include <boost/make_shared.hpp>
#include <boost/shared_ptr.hpp> #include <boost/shared_ptr.hpp>
#include <stxxl.h>
#include "TemporaryStorage.h" #include "TemporaryStorage.h"
#include "../DataStructures/BinaryHeap.h" #include "../DataStructures/BinaryHeap.h"
#include "../DataStructures/DeallocatingVector.h" #include "../DataStructures/DeallocatingVector.h"
@ -75,8 +77,7 @@ private:
_Heap heap; _Heap heap;
std::vector< _ContractorEdge > insertedEdges; std::vector< _ContractorEdge > insertedEdges;
std::vector< NodeID > neighbours; std::vector< NodeID > neighbours;
_ThreadData( NodeID nodes ): heap( nodes ) { _ThreadData( NodeID nodes ): heap( nodes ) { }
}
}; };
struct _PriorityData { struct _PriorityData {
@ -92,9 +93,15 @@ private:
_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 _NodePartitionor { struct _NodePartitionor {
inline bool operator()( std::pair< NodeID, bool > & nodeData ) const { inline bool operator()(_RemainingNodeData & nodeData ) const {
return !nodeData.second; return !nodeData.isIndependent;
} }
}; };
@ -102,31 +109,30 @@ public:
template<class ContainerT > template<class ContainerT >
Contractor( int nodes, ContainerT& inputEdges) { Contractor( int nodes, ContainerT& inputEdges) {
DeallocatingVector< _ContractorEdge > edges; stxxl::vector< _ContractorEdge > edges;
typename ContainerT::deallocation_iterator diter = inputEdges.dbegin(); 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) {
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_FOREACH(typename ContainerT::value_type & currentEdge, inputEdges) { assert( newEdge.data.distance > 0 );
for(; diter!=dend; ++diter) {
_ContractorEdge edge;
edge.source = diter->source();
edge.target = diter->target();
edge.data = _ContractorEdgeData( (std::max)((int)diter->weight(), 1 ), 1, diter->id()/*, currentEdge.getNameIDOfTurnTarget(), currentEdge.turnInstruction()*/, false, diter->isForward(), diter->isBackward());
assert( edge.data.distance > 0 );
#ifndef NDEBUG #ifndef NDEBUG
if ( edge.data.distance > 24 * 60 * 60 * 10 ) { if ( newEdge.data.distance > 24 * 60 * 60 * 10 ) {
std::cout << "Edge Weight too large -> May lead to invalid CH" << std::endl; std::cout << "Edge Weight too large -> May lead to invalid CH" << std::endl;
continue; continue;
} }
#endif #endif
edges.push_back( edge ); edges.push_back( newEdge );
std::swap( edge.source, edge.target ); std::swap( newEdge.source, newEdge.target );
edge.data.forward = diter->isBackward(); newEdge.data.forward = diter->isBackward();
edge.data.backward = diter->isForward(); newEdge.data.backward = diter->isForward();
edges.push_back( edge ); 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(); inputEdges.clear();
@ -137,7 +143,6 @@ public:
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 id = edges[i].data.id; const NodeID id = edges[i].data.id;
// const short turnType = edges[i].data.turnInstruction;
//remove eigenloops //remove eigenloops
if ( source == target ) { if ( source == target ) {
i++; i++;
@ -178,7 +183,6 @@ public:
} }
std::cout << "merged " << edges.size() - edge << " edges out of " << edges.size() << std::endl; std::cout << "merged " << edges.size() - edge << " edges out of " << edges.size() << std::endl;
// edges.resize( edge ); // edges.resize( edge );
_graph = boost::make_shared<_DynamicGraph>( nodes, edges ); _graph = boost::make_shared<_DynamicGraph>( nodes, edges );
edges.clear(); edges.clear();
// unsigned maxdegree = 0; // unsigned maxdegree = 0;
@ -222,14 +226,14 @@ public:
std::cout << "Contractor is using " << maxThreads << " threads" << std::endl; std::cout << "Contractor is using " << maxThreads << " threads" << std::endl;
NodeID numberOfContractedNodes = 0; NodeID numberOfContractedNodes = 0;
std::vector< std::pair< NodeID, bool > > remainingNodes( numberOfNodes ); std::vector< _RemainingNodeData > remainingNodes( numberOfNodes );
std::vector< float > nodePriority( numberOfNodes ); std::vector< float > nodePriority( numberOfNodes );
std::vector< _PriorityData > nodeData( numberOfNodes ); std::vector< _PriorityData > nodeData( numberOfNodes );
//initialize the variables //initialize the variables
#pragma omp parallel for schedule ( guided ) #pragma omp parallel for schedule ( guided )
for ( int x = 0; x < ( int ) numberOfNodes; ++x ) for ( int x = 0; x < ( int ) numberOfNodes; ++x )
remainingNodes[x].first = x; remainingNodes[x].id = x;
std::cout << "initializing elimination PQ ..." << std::flush; std::cout << "initializing elimination PQ ..." << std::flush;
#pragma omp parallel #pragma omp parallel
@ -249,9 +253,8 @@ public:
std::cout << " [flush " << numberOfContractedNodes << " nodes] " << std::flush; std::cout << " [flush " << numberOfContractedNodes << " nodes] " << std::flush;
//Delete old heap data to free memory that we need for the coming operations //Delete old heap data to free memory that we need for the coming operations
for ( unsigned threadNum = 0; threadNum < maxThreads; threadNum++ ) { BOOST_FOREACH(_ThreadData * data, threadData)
delete threadData[threadNum]; delete data;
}
threadData.clear(); threadData.clear();
@ -265,10 +268,10 @@ public:
//build forward and backward renumbering map and remap ids in remainingNodes and Priorities. //build forward and backward renumbering map and remap ids in remainingNodes and Priorities.
for(unsigned newNodeID = 0; newNodeID < remainingNodes.size(); ++newNodeID) { for(unsigned newNodeID = 0; newNodeID < remainingNodes.size(); ++newNodeID) {
//create renumbering maps in both directions //create renumbering maps in both directions
oldNodeIDFromNewNodeIDMap[newNodeID] = remainingNodes[newNodeID].first; oldNodeIDFromNewNodeIDMap[newNodeID] = remainingNodes[newNodeID].id;
newNodeIDFromOldNodeIDMap[remainingNodes[newNodeID].first] = newNodeID; newNodeIDFromOldNodeIDMap[remainingNodes[newNodeID].id] = newNodeID;
newNodePriority[newNodeID] = nodePriority[remainingNodes[newNodeID].first]; newNodePriority[newNodeID] = nodePriority[remainingNodes[newNodeID].id];
remainingNodes[newNodeID].first = newNodeID; remainingNodes[newNodeID].id = newNodeID;
} }
TemporaryStorage & tempStorage = TemporaryStorage::GetInstance(); TemporaryStorage & tempStorage = TemporaryStorage::GetInstance();
//Write dummy number of edges to temporary file //Write dummy number of edges to temporary file
@ -342,12 +345,12 @@ public:
_ThreadData* const data = threadData[omp_get_thread_num()]; _ThreadData* const data = threadData[omp_get_thread_num()];
#pragma omp for schedule ( guided ) #pragma omp for schedule ( guided )
for ( int i = 0; i < last; ++i ) { for ( int i = 0; i < last; ++i ) {
const NodeID node = remainingNodes[i].first; const NodeID node = remainingNodes[i].id;
remainingNodes[i].second = _IsIndependent( nodePriority/*, nodeData*/, data, node ); remainingNodes[i].isIndependent = _IsIndependent( nodePriority/*, nodeData*/, data, node );
} }
} }
_NodePartitionor functor; _NodePartitionor functor;
const std::vector < std::pair < NodeID, bool > >::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(); const int firstIndependent = first - remainingNodes.begin();
//contract independent nodes //contract independent nodes
#pragma omp parallel #pragma omp parallel
@ -355,7 +358,7 @@ public:
_ThreadData* data = threadData[omp_get_thread_num()]; _ThreadData* data = threadData[omp_get_thread_num()];
#pragma omp for schedule ( guided ) nowait #pragma omp for schedule ( guided ) nowait
for ( int position = firstIndependent ; position < last; ++position ) { for ( int position = firstIndependent ; position < last; ++position ) {
NodeID x = remainingNodes[position].first; NodeID x = remainingNodes[position].id;
_Contract< false > ( data, x ); _Contract< false > ( data, x );
//nodePriority[x] = -1; //nodePriority[x] = -1;
} }
@ -367,29 +370,25 @@ public:
_ThreadData* data = threadData[omp_get_thread_num()]; _ThreadData* data = threadData[omp_get_thread_num()];
#pragma omp for schedule ( guided ) nowait #pragma omp for schedule ( guided ) nowait
for ( int position = firstIndependent ; position < last; ++position ) { for ( int position = firstIndependent ; position < last; ++position ) {
NodeID x = remainingNodes[position].first; NodeID x = remainingNodes[position].id;
_DeleteIncomingEdges( data, x ); _DeleteIncomingEdges( data, x );
} }
} }
//insert new edges //insert new edges
for ( unsigned threadNum = 0; threadNum < maxThreads; ++threadNum ) { for ( unsigned threadNum = 0; threadNum < maxThreads; ++threadNum ) {
_ThreadData& data = *threadData[threadNum]; _ThreadData& data = *threadData[threadNum];
for ( int i = 0; i < ( int ) data.insertedEdges.size(); ++i ) { BOOST_FOREACH(const _ContractorEdge& edge, data.insertedEdges) {
const _ContractorEdge& edge = data.insertedEdges[i];
_DynamicGraph::EdgeIterator currentEdgeID = _graph->FindEdge(edge.source, edge.target); _DynamicGraph::EdgeIterator currentEdgeID = _graph->FindEdge(edge.source, edge.target);
if(currentEdgeID != _graph->EndEdges(edge.source) && _graph->GetEdgeData(currentEdgeID).shortcut) { if(currentEdgeID < _graph->EndEdges(edge.source) ) {
_DynamicGraph::EdgeData & currentEdgeData = _graph->GetEdgeData(currentEdgeID); _DynamicGraph::EdgeData & currentEdgeData = _graph->GetEdgeData(currentEdgeID);
if(edge.data.forward == currentEdgeData.forward && edge.data.backward == currentEdgeData.backward ) { if( currentEdgeData.shortcut
if(_graph->GetEdgeData(_graph->FindEdge(edge.source, edge.target)).distance <= edge.data.distance) { && edge.data.forward == currentEdgeData.forward
continue; && edge.data.backward == currentEdgeData.backward ) {
} currentEdgeData.distance = std::min(currentEdgeData.distance, edge.data.distance);
if(currentEdgeData.distance > edge.data.distance) { continue;
currentEdgeData.distance = edge.data.distance;
continue;
}
} }
} }
_graph->InsertEdge( data.insertedEdges[i].source, data.insertedEdges[i].target, data.insertedEdges[i].data ); _graph->InsertEdge( edge.source, edge.target, edge.data );
} }
data.insertedEdges.clear(); data.insertedEdges.clear();
} }
@ -399,14 +398,14 @@ public:
_ThreadData* data = threadData[omp_get_thread_num()]; _ThreadData* data = threadData[omp_get_thread_num()];
#pragma omp for schedule ( guided ) nowait #pragma omp for schedule ( guided ) nowait
for ( int position = firstIndependent ; position < last; ++position ) { for ( int position = firstIndependent ; position < last; ++position ) {
NodeID x = remainingNodes[position].first; 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; numberOfContractedNodes += last - firstIndependent;
remainingNodes.resize( firstIndependent ); remainingNodes.resize( firstIndependent );
std::vector< std::pair< NodeID, bool > >( remainingNodes ).swap( remainingNodes ); std::vector< _RemainingNodeData>( remainingNodes ).swap( remainingNodes );
// unsigned maxdegree = 0; // unsigned maxdegree = 0;
// unsigned avgdegree = 0; // unsigned avgdegree = 0;
// unsigned mindegree = UINT_MAX; // unsigned mindegree = UINT_MAX;
@ -430,13 +429,13 @@ public:
p.printStatus(numberOfContractedNodes); p.printStatus(numberOfContractedNodes);
} }
for ( unsigned threadNum = 0; threadNum < maxThreads; threadNum++ ) { BOOST_FOREACH(_ThreadData * data, threadData)
delete threadData[threadNum]; delete data;
} threadData.clear();
} }
template< class Edge > template< class Edge >
void GetEdges( DeallocatingVector< Edge >& edges ) { inline void GetEdges( DeallocatingVector< Edge >& edges ) {
Percent p (_graph->GetNumberOfNodes()); Percent p (_graph->GetNumberOfNodes());
INFO("Getting edges of minimized graph"); INFO("Getting edges of minimized graph");
NodeID numberOfNodes = _graph->GetNumberOfNodes(); NodeID numberOfNodes = _graph->GetNumberOfNodes();
@ -496,11 +495,11 @@ public:
edges.push_back( newEdge ); edges.push_back( newEdge );
} }
tempStorage.deallocateSlot(temporaryStorageSlotID); tempStorage.deallocateSlot(temporaryStorageSlotID);
INFO("CH has " << edges.size() << " edges"); INFO("Hierarchy has " << edges.size() << " edges");
} }
private: private:
inline void _Dijkstra( const int maxDistance, const unsigned numTargets, const int maxNodes, _ThreadData* const data ){ 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;
@ -529,6 +528,8 @@ private:
if ( !data.forward ) if ( !data.forward )
continue; continue;
const NodeID to = _graph->GetTarget( edge ); const NodeID to = _graph->GetTarget( edge );
if(middleNode == to)
continue;
const int toDistance = distance + data.distance; const int toDistance = distance + data.distance;
//New Node discovered -> Add to Heap + Node Info Storage //New Node discovered -> Add to Heap + Node Info Storage
@ -544,7 +545,7 @@ private:
} }
} }
float _Evaluate( _ThreadData* const data, _PriorityData* const nodeData, NodeID node){ inline float _Evaluate( _ThreadData* const data, _PriorityData* const nodeData, const NodeID node){
_ContractionInformation stats; _ContractionInformation stats;
//perform simulated contraction //perform simulated contraction
@ -552,7 +553,7 @@ private:
// Result will contain the priority // Result will contain the priority
float result; float result;
if ( stats.edgesDeleted == 0 || stats.originalEdgesDeleted == 0 ) if ( 0 == (stats.edgesDeleted*stats.originalEdgesDeleted) )
result = 1 * nodeData->depth; result = 1 * nodeData->depth;
else else
result = 2 * ((( float ) stats.edgesAdded ) / stats.edgesDeleted ) + 4 * ((( float ) stats.originalEdgesAdded ) / stats.originalEdgesDeleted ) + 1 * nodeData->depth; result = 2 * ((( float ) stats.edgesAdded ) / stats.edgesDeleted ) + 4 * ((( float ) stats.originalEdgesAdded ) / stats.originalEdgesDeleted ) + 1 * nodeData->depth;
@ -561,7 +562,7 @@ private:
} }
template< bool Simulate > template< bool Simulate >
bool _Contract( _ThreadData* data, NodeID node, _ContractionInformation* stats = NULL ) { inline bool _Contract( _ThreadData* data, NodeID node, _ContractionInformation* stats = NULL ) {
_Heap& heap = data->heap; _Heap& heap = data->heap;
int insertedEdgesSize = data->insertedEdges.size(); int insertedEdgesSize = data->insertedEdges.size();
std::vector< _ContractorEdge >& insertedEdges = data->insertedEdges; std::vector< _ContractorEdge >& insertedEdges = data->insertedEdges;
@ -579,8 +580,6 @@ private:
heap.Clear(); heap.Clear();
heap.Insert( source, 0, _HeapData() ); heap.Insert( source, 0, _HeapData() );
// if ( node != source )
// heap.Insert( node, inData.distance, _HeapData() );
int maxDistance = 0; int maxDistance = 0;
unsigned numTargets = 0; unsigned numTargets = 0;
@ -592,17 +591,15 @@ private:
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( 0, true ) ); heap.Insert( target, INT_MAX, _HeapData( 0, true ) );
++numTargets; ++numTargets;
} else if ( pathDistance < heap.GetKey( target ) ) {
heap.DecreaseKey( target, pathDistance );
} }
} }
if( Simulate ) if( Simulate )
_Dijkstra( maxDistance, numTargets, 1000, data ); _Dijkstra( maxDistance, numTargets, 1000, data, node );
else else
_Dijkstra( maxDistance, numTargets, 2000, data ); _Dijkstra( maxDistance, numTargets, 2000, data, node );
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 _ContractorEdgeData& outData = _graph->GetEdgeData( outEdge ); const _ContractorEdgeData& outData = _graph->GetEdgeData( outEdge );
@ -611,7 +608,7 @@ private:
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;
const int distance = heap.GetKey( target ); const int distance = heap.GetKey( target );
if ( pathDistance <= distance ) { if ( pathDistance < distance ) {
if ( Simulate ) { if ( Simulate ) {
assert( stats != NULL ); assert( stats != NULL );
stats->edgesAdded+=2; stats->edgesAdded+=2;
@ -655,7 +652,7 @@ private:
return true; return true;
} }
void _DeleteIncomingEdges( _ThreadData* data, NodeID node ) { inline void _DeleteIncomingEdges( _ThreadData* data, const NodeID node ) {
std::vector< NodeID >& neighbours = data->neighbours; std::vector< NodeID >& neighbours = data->neighbours;
neighbours.clear(); neighbours.clear();
@ -670,17 +667,16 @@ private:
neighbours.resize( std::unique( neighbours.begin(), neighbours.end() ) - neighbours.begin() ); neighbours.resize( std::unique( neighbours.begin(), neighbours.end() ) - neighbours.begin() );
for ( int i = 0, e = ( int ) neighbours.size(); i < e; ++i ) { for ( int i = 0, e = ( int ) neighbours.size(); i < e; ++i ) {
// const NodeID u = neighbours[i];
_graph->DeleteEdgesTo( neighbours[i], node ); _graph->DeleteEdgesTo( neighbours[i], node );
} }
} }
bool _UpdateNeighbours( std::vector< float > & priorities, std::vector< _PriorityData > & nodeData, _ThreadData* const data, NodeID node) { inline bool _UpdateNeighbours( std::vector< float > & priorities, std::vector< _PriorityData > & nodeData, _ThreadData* const data, const NodeID node) {
std::vector< NodeID >& neighbours = data->neighbours; std::vector< NodeID >& neighbours = data->neighbours;
neighbours.clear(); neighbours.clear();
//find all neighbours //find all neighbours
for ( _DynamicGraph::EdgeIterator e = _graph->BeginEdges( node ) ; e < _graph->EndEdges( node ) ; ++e ) { for ( _DynamicGraph::EdgeIterator e = _graph->BeginEdges( node ), endEdges = _graph->EndEdges( node ) ; e < endEdges ; ++e ) {
const NodeID u = _graph->GetTarget( e ); const NodeID u = _graph->GetTarget( e );
if ( u == node ) if ( u == node )
continue; continue;
@ -691,16 +687,13 @@ private:
std::sort( neighbours.begin(), neighbours.end() ); std::sort( neighbours.begin(), neighbours.end() );
neighbours.resize( std::unique( neighbours.begin(), neighbours.end() ) - neighbours.begin() ); neighbours.resize( std::unique( neighbours.begin(), neighbours.end() ) - neighbours.begin() );
int neighbourSize = ( int ) neighbours.size(); BOOST_FOREACH(const NodeID u, neighbours) {
for ( int i = 0, e = neighbourSize; i < e; ++i ) {
const NodeID u = neighbours[i];
priorities[u] = _Evaluate( data, &( nodeData )[u], u ); priorities[u] = _Evaluate( data, &( nodeData )[u], u );
} }
return true; return true;
} }
bool _IsIndependent( const std::vector< float >& priorities/*, const std::vector< _PriorityData >& nodeData*/, _ThreadData* const data, NodeID node ) { inline bool _IsIndependent( const std::vector< float >& priorities/*, const std::vector< _PriorityData >& nodeData*/, _ThreadData* const data, NodeID node ) const {
const double priority = priorities[node]; const double priority = priorities[node];
std::vector< NodeID >& neighbours = data->neighbours; std::vector< NodeID >& neighbours = data->neighbours;
@ -726,9 +719,7 @@ private:
neighbours.resize( std::unique( neighbours.begin(), neighbours.end() ) - neighbours.begin() ); neighbours.resize( std::unique( neighbours.begin(), neighbours.end() ) - neighbours.begin() );
//examine all neighbours that are at most 2 hops away //examine all neighbours that are at most 2 hops away
for ( std::vector< NodeID >::const_iterator i = neighbours.begin(), lastNode = neighbours.end(); i != lastNode; ++i ) { BOOST_FOREACH(const NodeID u, neighbours) {
const NodeID u = *i;
for ( _DynamicGraph::EdgeIterator e = _graph->BeginEdges( u ) ; e < _graph->EndEdges( u ) ; ++e ) { for ( _DynamicGraph::EdgeIterator e = _graph->BeginEdges( u ) ; e < _graph->EndEdges( u ) ; ++e ) {
const NodeID target = _graph->GetTarget( e ); const NodeID target = _graph->GetTarget( e );
if(node==target) if(node==target)
@ -764,10 +755,8 @@ private:
boost::shared_ptr<_DynamicGraph> _graph; boost::shared_ptr<_DynamicGraph> _graph;
std::vector<_DynamicGraph::InputEdge> contractedEdges; std::vector<_DynamicGraph::InputEdge> contractedEdges;
// std::string temporaryEdgeStorageFilename;
unsigned temporaryStorageSlotID; unsigned temporaryStorageSlotID;
std::vector<NodeID> oldNodeIDFromNewNodeIDMap; std::vector<NodeID> oldNodeIDFromNewNodeIDMap;
XORFastHash fastHash; XORFastHash fastHash;
}; };