2010-07-09 05:05:40 -04:00
/*
open source routing machine
Copyright ( C ) Dennis Luxen , others 2010
This program is free software ; you can redistribute it and / or modify
it under the terms of the GNU AFFERO General Public License as published by
the Free Software Foundation ; either version 3 of the License , or
any later version .
This program is distributed in the hope that it will be useful ,
but WITHOUT ANY WARRANTY ; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE . See the
GNU General Public License for more details .
You should have received a copy of the GNU Affero General Public License
along with this program ; if not , write to the Free Software
Foundation , Inc . , 59 Temple Place , Suite 330 , Boston , MA 02111 - 1307 USA
or see http : //www.gnu.org/licenses/agpl.txt.
2010-08-12 11:42:22 -04:00
*/
2010-07-09 05:05:40 -04:00
# ifndef CONTRACTOR_H_INCLUDED
# define CONTRACTOR_H_INCLUDED
# include <algorithm>
2011-11-25 06:01:52 -05:00
# include <boost/shared_ptr.hpp>
2010-09-02 11:47:55 -04:00
# include "../DataStructures/DynamicGraph.h"
2010-10-01 06:30:46 -04:00
# include "../DataStructures/Percent.h"
2011-03-24 09:32:15 -04:00
# include "../DataStructures/BinaryHeap.h"
2011-11-26 10:42:15 -05:00
# include "../Util/OpenMPReplacement.h"
2012-04-04 03:55:43 -04:00
# include "../Util/StringUtil.h"
2010-07-09 05:05:40 -04:00
# include <ctime>
# include <vector>
# include <queue>
# include <set>
# include <stack>
# include <limits>
class Contractor {
2010-09-23 11:34:22 -04:00
private :
2012-02-23 10:29:55 -05:00
struct _EdgeBasedContractorEdgeData {
_EdgeBasedContractorEdgeData ( ) :
2012-04-25 04:51:16 -04:00
distance ( 0 ) , originalEdges ( 0 ) , id ( 0 ) /*, nameID(0), turnInstruction(0)*/ , shortcut ( 0 ) , forward ( 0 ) , backward ( 0 ) { }
_EdgeBasedContractorEdgeData ( unsigned _distance , unsigned _originalEdges , unsigned _id /*, unsigned _nameID, short _turnInstruction*/ , bool _shortcut , bool _forward , bool _backward ) :
distance ( _distance ) , originalEdges ( _originalEdges ) , id ( _id ) /*, nameID(_nameID), turnInstruction(_turnInstruction)*/ , shortcut ( _shortcut ) , forward ( _forward ) , backward ( _backward ) , originalViaNodeID ( false ) { }
2012-02-23 10:29:55 -05:00
unsigned distance ;
unsigned originalEdges ;
2012-04-25 04:51:16 -04:00
unsigned id ;
// unsigned nameID;
// short turnInstruction;
2012-02-23 10:29:55 -05:00
bool shortcut : 1 ;
bool forward : 1 ;
bool backward : 1 ;
2012-04-04 03:55:43 -04:00
bool originalViaNodeID : 1 ;
2012-02-23 10:29:55 -05:00
} data ;
struct _HeapData {
short hop ;
bool target ;
_HeapData ( ) : hop ( 0 ) , target ( false ) { }
_HeapData ( short h , bool t ) : hop ( h ) , target ( t ) { }
} ;
typedef DynamicGraph < _EdgeBasedContractorEdgeData > _DynamicGraph ;
typedef BinaryHeap < NodeID , NodeID , int , _HeapData > _Heap ;
typedef _DynamicGraph : : InputEdge _ImportEdge ;
struct _ThreadData {
_Heap heap ;
std : : vector < _ImportEdge > insertedEdges ;
std : : vector < NodeID > neighbours ;
_ThreadData ( NodeID nodes ) : heap ( nodes ) {
}
} ;
struct _PriorityData {
int depth ;
NodeID bias ;
_PriorityData ( ) : depth ( 0 ) , bias ( 0 ) { }
} ;
struct _ContractionInformation {
int edgesDeleted ;
int edgesAdded ;
int originalEdgesDeleted ;
int originalEdgesAdded ;
_ContractionInformation ( ) : edgesDeleted ( 0 ) , edgesAdded ( 0 ) , originalEdgesDeleted ( 0 ) , originalEdgesAdded ( 0 ) { }
} ;
struct _NodePartitionor {
bool operator ( ) ( std : : pair < NodeID , bool > & nodeData ) const {
return ! nodeData . second ;
}
} ;
2010-07-09 05:05:40 -04:00
public :
2012-02-23 10:29:55 -05:00
template < class InputEdge >
2012-03-07 02:49:10 -05:00
Contractor ( int nodes , std : : vector < InputEdge > & inputEdges ) {
2012-02-23 10:29:55 -05:00
std : : vector < _ImportEdge > edges ;
edges . reserve ( 2 * inputEdges . size ( ) ) ;
BOOST_FOREACH ( InputEdge & currentEdge , inputEdges ) {
_ImportEdge edge ;
edge . source = currentEdge . source ( ) ;
edge . target = currentEdge . target ( ) ;
2012-04-25 04:51:16 -04:00
edge . data = _EdgeBasedContractorEdgeData ( ( std : : max ) ( ( int ) currentEdge . weight ( ) , 1 ) , 1 , currentEdge . id ( ) /*, currentEdge.getNameIDOfTurnTarget(), currentEdge.turnInstruction()*/ , false , currentEdge . isForward ( ) , currentEdge . isBackward ( ) ) ;
2012-02-23 10:29:55 -05:00
assert ( edge . data . distance > 0 ) ;
2011-12-10 12:26:33 -05:00
# ifdef NDEBUG
2012-02-23 10:29:55 -05:00
if ( edge . data . distance > 24 * 60 * 60 * 10 ) {
std : : cout < < " Edge Weight too large -> May lead to invalid CH " < < std : : endl ;
continue ;
}
2011-03-15 11:19:20 -04:00
# endif
2012-02-23 10:29:55 -05:00
edges . push_back ( edge ) ;
std : : swap ( edge . source , edge . target ) ;
edge . data . forward = currentEdge . isBackward ( ) ;
edge . data . backward = currentEdge . isForward ( ) ;
edges . push_back ( edge ) ;
}
2012-04-14 09:28:45 -04:00
//clear input vector and trim the current set of edges with the well-known swap trick
2012-02-23 10:29:55 -05:00
std : : vector < InputEdge > ( ) . swap ( inputEdges ) ;
2012-04-14 09:28:45 -04:00
2012-02-23 10:29:55 -05:00
sort ( edges . begin ( ) , edges . end ( ) ) ;
NodeID edge = 0 ;
for ( NodeID i = 0 ; i < edges . size ( ) ; ) {
const NodeID source = edges [ i ] . source ;
const NodeID target = edges [ i ] . target ;
2012-04-25 04:51:16 -04:00
const NodeID id = edges [ i ] . data . id ;
// const short turnType = edges[i].data.turnInstruction;
2012-02-23 10:29:55 -05:00
//remove eigenloops
if ( source = = target ) {
i + + ;
continue ;
}
_ImportEdge forwardEdge ;
_ImportEdge backwardEdge ;
forwardEdge . source = backwardEdge . source = source ;
forwardEdge . target = backwardEdge . target = target ;
forwardEdge . data . forward = backwardEdge . data . backward = true ;
forwardEdge . data . backward = backwardEdge . data . forward = false ;
2012-04-25 04:51:16 -04:00
// forwardEdge.data.turnInstruction = backwardEdge.data.turnInstruction = turnType;
// forwardEdge.data.nameID = backwardEdge.data.nameID = edges[i].data.nameID;
2012-02-23 10:29:55 -05:00
forwardEdge . data . shortcut = backwardEdge . data . shortcut = false ;
2012-04-25 04:51:16 -04:00
forwardEdge . data . id = backwardEdge . data . id = id ;
2012-02-23 10:29:55 -05:00
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 ) ;
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 ( ) ) {
forwardEdge . data . backward = true ;
edges [ edge + + ] = forwardEdge ;
}
} else { //insert seperate edges
if ( ( ( int ) forwardEdge . data . distance ) ! = std : : numeric_limits < int > : : max ( ) ) {
edges [ edge + + ] = forwardEdge ;
}
if ( ( int ) backwardEdge . data . distance ! = std : : numeric_limits < int > : : max ( ) ) {
edges [ edge + + ] = backwardEdge ;
}
}
}
2012-04-14 09:05:51 -04:00
std : : cout < < " ok " < < " merged " < < edges . size ( ) - edge < < " edges out of " < < edges . size ( ) < < std : : endl ;
2012-02-23 10:29:55 -05:00
edges . resize ( edge ) ;
2012-04-14 09:28:45 -04:00
std : : vector < _ImportEdge > ( edges ) . swap ( edges ) ;
2012-02-23 10:29:55 -05:00
_graph . reset ( new _DynamicGraph ( nodes , edges ) ) ;
std : : vector < _ImportEdge > ( ) . swap ( edges ) ;
2012-03-07 02:49:10 -05:00
// unsigned maxdegree = 0;
// NodeID highestNode = 0;
//
// for(unsigned i = 0; i < _graph->GetNumberOfNodes(); ++i) {
// unsigned degree = _graph->EndEdges(i) - _graph->BeginEdges(i);
// if(degree > maxdegree) {
// maxdegree = degree;
// highestNode = i;
// }
// }
//
// INFO("edges at node with id " << highestNode << " has degree " << maxdegree);
// for(unsigned i = _graph->BeginEdges(highestNode); i < _graph->EndEdges(highestNode); ++i) {
// INFO(" ->(" << highestNode << "," << _graph->GetTarget(i) << "); via: " << _graph->GetEdgeData(i).via);
// }
2012-04-04 03:55:43 -04:00
//Create temporary file
GetTemporaryFileName ( temporaryEdgeStorageFilename ) ;
2012-04-14 09:05:51 -04:00
std : : cout < < " contractor finished initalization " < < std : : endl ;
2012-02-23 10:29:55 -05:00
}
2012-04-04 03:55:43 -04:00
~ Contractor ( ) {
//Delete temporary file
2012-04-04 07:08:13 -04:00
remove ( temporaryEdgeStorageFilename . c_str ( ) ) ;
2012-04-04 03:55:43 -04:00
}
2012-02-23 10:29:55 -05:00
void Run ( ) {
const NodeID numberOfNodes = _graph - > GetNumberOfNodes ( ) ;
Percent p ( numberOfNodes ) ;
unsigned maxThreads = omp_get_max_threads ( ) ;
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 < std : : pair < NodeID , bool > > remainingNodes ( numberOfNodes ) ;
std : : vector < double > nodePriority ( numberOfNodes ) ;
std : : vector < _PriorityData > nodeData ( numberOfNodes ) ;
//initialize the variables
2010-07-09 05:05:40 -04:00
# pragma omp parallel for schedule ( guided )
2012-02-23 10:29:55 -05:00
for ( int x = 0 ; x < ( int ) numberOfNodes ; + + x )
remainingNodes [ x ] . first = x ;
std : : random_shuffle ( remainingNodes . begin ( ) , remainingNodes . end ( ) ) ;
for ( int x = 0 ; x < ( int ) numberOfNodes ; + + x )
nodeData [ remainingNodes [ x ] . first ] . bias = x ;
2010-07-09 05:05:40 -04:00
2012-02-23 10:29:55 -05:00
std : : cout < < " initializing elimination PQ ... " < < std : : flush ;
2010-07-09 05:05:40 -04:00
# pragma omp parallel
2012-02-23 10:29:55 -05:00
{
_ThreadData * data = threadData [ omp_get_thread_num ( ) ] ;
2011-11-25 08:43:56 -05:00
# pragma omp parallel for schedule ( guided )
2012-02-23 10:29:55 -05:00
for ( int x = 0 ; x < ( int ) numberOfNodes ; + + x ) {
2012-03-07 02:49:10 -05:00
nodePriority [ x ] = _Evaluate ( data , & nodeData [ x ] , x ) ;
2012-02-23 10:29:55 -05:00
}
}
std : : cout < < " ok " < < std : : endl < < " preprocessing ... " < < std : : flush ;
2012-03-24 15:15:04 -04:00
bool flushedContractor = false ;
2012-02-23 10:29:55 -05:00
while ( numberOfContractedNodes < numberOfNodes ) {
2012-04-04 05:11:54 -04:00
if ( ! flushedContractor & & ( numberOfContractedNodes > ( numberOfNodes * 0.75 ) ) ) {
2012-03-24 15:15:04 -04:00
INFO ( " Flushing memory after " < < numberOfContractedNodes < < " nodes " ) ;
2012-04-04 03:55:43 -04:00
2012-03-24 15:15:04 -04:00
//Delete old heap data to free memory that we need for the coming operations
for ( unsigned threadNum = 0 ; threadNum < maxThreads ; threadNum + + ) {
delete threadData [ threadNum ] ;
}
threadData . clear ( ) ;
//Create new priority array
std : : vector < double > newNodePriority ( remainingNodes . size ( ) ) ;
//this map gives the old IDs from the new ones, necessary to get a consistent graph at the end of contraction
2012-04-04 03:55:43 -04:00
oldNodeIDFromNewNodeIDMap . resize ( remainingNodes . size ( ) ) ;
2012-03-24 15:15:04 -04:00
//this map gives the new IDs from the old ones, necessary to remap targets from the remaining graph
2012-04-04 03:55:43 -04:00
std : : vector < NodeID > newNodeIDFromOldNodeIDMap ( numberOfNodes , UINT_MAX ) ;
2012-03-24 15:15:04 -04:00
//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
2012-04-04 03:55:43 -04:00
oldNodeIDFromNewNodeIDMap [ newNodeID ] = remainingNodes [ newNodeID ] . first ;
newNodeIDFromOldNodeIDMap [ remainingNodes [ newNodeID ] . first ] = newNodeID ;
2012-03-24 15:15:04 -04:00
newNodePriority [ newNodeID ] = nodePriority [ remainingNodes [ newNodeID ] . first ] ;
remainingNodes [ newNodeID ] . first = newNodeID ;
}
//create new _DynamicGraph, goes out of scope after the renumbering
boost : : shared_ptr < _DynamicGraph > _newGraph ( new _DynamicGraph ( remainingNodes . size ( ) ) ) ;
2012-04-04 03:55:43 -04:00
//Write dummy number of edges to temporary file
std : : ofstream temporaryEdgeStorage ( temporaryEdgeStorageFilename . c_str ( ) , std : : ios : : binary ) ;
initialFilePosition = temporaryEdgeStorage . tellp ( ) ;
unsigned numberOfTemporaryEdges = 0 ;
temporaryEdgeStorage . write ( ( char * ) & numberOfTemporaryEdges , sizeof ( unsigned ) ) ;
//walk over all nodes
for ( unsigned i = 0 ; i < _graph - > GetNumberOfNodes ( ) ; + + i ) {
//INFO("Restructuring node " << i << "|" << _graph->GetNumberOfNodes());
const NodeID start = i ;
//UINT_MAX indicates that node is already contracted
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.
temporaryEdgeStorage . write ( ( char * ) & start , sizeof ( NodeID ) ) ;
temporaryEdgeStorage . write ( ( char * ) & target , sizeof ( NodeID ) ) ;
temporaryEdgeStorage . write ( ( char * ) & data , sizeof ( _DynamicGraph : : EdgeData ) ) ;
+ + numberOfTemporaryEdges ;
} else {
//node is not yet contracted.
//add (renumbered) outgoing edges to new DynamicGraph.
data . originalViaNodeID = true ;
2012-04-04 07:08:13 -04:00
assert ( UINT_MAX ! = newNodeIDFromOldNodeIDMap [ start ] ) ;
assert ( UINT_MAX ! = newNodeIDFromOldNodeIDMap [ target ] ) ;
2012-04-04 03:55:43 -04:00
_newGraph - > InsertEdge ( newNodeIDFromOldNodeIDMap [ start ] , newNodeIDFromOldNodeIDMap [ target ] , data ) ;
}
}
2012-03-24 15:15:04 -04:00
}
2012-04-04 03:55:43 -04:00
//Note the number of temporarily stored edges
temporaryEdgeStorage . seekp ( initialFilePosition ) ;
temporaryEdgeStorage . write ( ( char * ) & numberOfTemporaryEdges , sizeof ( unsigned ) ) ;
temporaryEdgeStorage . close ( ) ;
2012-04-04 07:08:13 -04:00
// INFO("Flushed " << numberOfTemporaryEdges << " edges to disk");
2012-04-04 03:55:43 -04:00
2012-03-24 15:15:04 -04:00
//Delete map from old NodeIDs to new ones.
2012-04-04 03:55:43 -04:00
std : : vector < NodeID > ( ) . swap ( newNodeIDFromOldNodeIDMap ) ;
2012-03-24 15:15:04 -04:00
//Replace old priorities array by new one
nodePriority . swap ( newNodePriority ) ;
//Delete old nodePriority vector
std : : vector < double > ( ) . swap ( newNodePriority ) ;
//Alten Graphen löschen und neuen Graphen speichern.
2012-04-04 03:55:43 -04:00
//reinitialize heaps and ThreadData objects with appropriate size
2012-03-24 15:15:04 -04:00
for ( unsigned threadNum = 0 ; threadNum < maxThreads ; + + threadNum ) {
2012-04-04 03:55:43 -04:00
threadData . push_back ( new _ThreadData ( _newGraph - > GetNumberOfNodes ( ) ) ) ;
2012-03-24 15:15:04 -04:00
}
2012-04-04 03:55:43 -04:00
//old Graph is removed
2012-03-24 15:15:04 -04:00
_graph . swap ( _newGraph ) ;
flushedContractor = true ;
}
2012-02-23 10:29:55 -05:00
const int last = ( int ) remainingNodes . size ( ) ;
2011-11-25 08:43:56 -05:00
# pragma omp parallel
2012-02-23 10:29:55 -05:00
{
//determine independent node set
_ThreadData * const data = threadData [ omp_get_thread_num ( ) ] ;
2011-11-25 08:43:56 -05:00
# pragma omp for schedule ( guided )
2012-02-23 10:29:55 -05:00
for ( int i = 0 ; i < last ; + + i ) {
const NodeID node = remainingNodes [ i ] . first ;
remainingNodes [ i ] . second = _IsIndependent ( nodePriority , nodeData , data , node ) ;
}
}
_NodePartitionor functor ;
const std : : vector < std : : pair < NodeID , bool > > : : const_iterator first = stable_partition ( remainingNodes . begin ( ) , remainingNodes . end ( ) , functor ) ;
const int firstIndependent = first - remainingNodes . begin ( ) ;
//contract independent nodes
2010-07-09 05:05:40 -04:00
# pragma omp parallel
2012-02-23 10:29:55 -05:00
{
_ThreadData * data = threadData [ omp_get_thread_num ( ) ] ;
2010-07-09 05:05:40 -04:00
# pragma omp for schedule ( guided ) nowait
2012-02-23 10:29:55 -05:00
for ( int position = firstIndependent ; position < last ; + + position ) {
NodeID x = remainingNodes [ position ] . first ;
2012-03-07 02:49:10 -05:00
_Contract < false > ( data , x ) ;
2012-02-23 10:29:55 -05:00
nodePriority [ x ] = - 1 ;
}
std : : sort ( data - > insertedEdges . begin ( ) , data - > insertedEdges . end ( ) ) ;
}
2010-07-09 05:05:40 -04:00
# pragma omp parallel
2012-02-23 10:29:55 -05:00
{
_ThreadData * data = threadData [ omp_get_thread_num ( ) ] ;
2010-07-09 05:05:40 -04:00
# pragma omp for schedule ( guided ) nowait
2012-02-23 10:29:55 -05:00
for ( int position = firstIndependent ; position < last ; + + position ) {
NodeID x = remainingNodes [ position ] . first ;
_DeleteIncomingEdges ( data , x ) ;
}
}
//insert new edges
for ( unsigned threadNum = 0 ; threadNum < maxThreads ; + + threadNum ) {
_ThreadData & data = * threadData [ threadNum ] ;
for ( int i = 0 ; i < ( int ) data . insertedEdges . size ( ) ; + + i ) {
const _ImportEdge & edge = data . insertedEdges [ i ] ;
_DynamicGraph : : EdgeIterator currentEdgeID = _graph - > FindEdge ( edge . source , edge . target ) ;
if ( currentEdgeID ! = _graph - > EndEdges ( edge . source ) ) {
_DynamicGraph : : EdgeData & currentEdgeData = _graph - > GetEdgeData ( currentEdgeID ) ;
if ( edge . data . forward = = currentEdgeData . forward & & edge . data . backward = = currentEdgeData . backward ) {
if ( _graph - > GetEdgeData ( _graph - > FindEdge ( edge . source , edge . target ) ) . distance < = edge . data . distance ) {
continue ;
}
if ( currentEdgeData . distance > edge . data . distance ) {
currentEdgeData . distance = edge . data . distance ;
continue ;
}
}
}
_graph - > InsertEdge ( edge . source , edge . target , edge . data ) ;
}
data . insertedEdges . clear ( ) ;
}
//update priorities
2010-07-09 05:05:40 -04:00
# pragma omp parallel
2012-02-23 10:29:55 -05:00
{
_ThreadData * data = threadData [ omp_get_thread_num ( ) ] ;
2010-07-09 05:05:40 -04:00
# pragma omp for schedule ( guided ) nowait
2012-02-23 10:29:55 -05:00
for ( int position = firstIndependent ; position < last ; + + position ) {
NodeID x = remainingNodes [ position ] . first ;
2012-03-07 02:49:10 -05:00
_UpdateNeighbours ( nodePriority , nodeData , data , x ) ;
2012-02-23 10:29:55 -05:00
}
}
//remove contracted nodes from the pool
numberOfContractedNodes + = last - firstIndependent ;
remainingNodes . resize ( firstIndependent ) ;
std : : vector < std : : pair < NodeID , bool > > ( remainingNodes ) . swap ( remainingNodes ) ;
2012-03-07 02:49:10 -05:00
// 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);
// if(degree > maxdegree)
// maxdegree = degree;
// if(degree < mindegree)
// mindegree = degree;
//
// avgdegree += degree;
// quaddegree += (degree*degree);
// }
//
// avgdegree /= std::max((unsigned)1,(unsigned)remainingNodes.size() );
// quaddegree /= std::max((unsigned)1,(unsigned)remainingNodes.size() );
// INFO("rest: " << remainingNodes.size() << ", max: " << maxdegree << ", min: " << mindegree << ", avg: " << avgdegree << ", quad: " << quaddegree);
2012-02-23 10:29:55 -05:00
p . printStatus ( numberOfContractedNodes ) ;
}
for ( unsigned threadNum = 0 ; threadNum < maxThreads ; threadNum + + ) {
delete threadData [ threadNum ] ;
}
}
template < class Edge >
void GetEdges ( std : : vector < Edge > & edges ) {
NodeID numberOfNodes = _graph - > GetNumberOfNodes ( ) ;
for ( NodeID node = 0 ; node < numberOfNodes ; + + node ) {
for ( _DynamicGraph : : EdgeIterator edge = _graph - > BeginEdges ( node ) , endEdges = _graph - > EndEdges ( node ) ; edge < endEdges ; edge + + ) {
const NodeID target = _graph - > GetTarget ( edge ) ;
2012-04-04 03:55:43 -04:00
const _DynamicGraph : : EdgeData & data = _graph - > GetEdgeData ( edge ) ;
2012-02-23 10:29:55 -05:00
Edge newEdge ;
2012-04-04 03:55:43 -04:00
newEdge . source = oldNodeIDFromNewNodeIDMap [ node ] ;
newEdge . target = oldNodeIDFromNewNodeIDMap [ target ] ;
assert ( UINT_MAX ! = newEdge . source ) ;
assert ( UINT_MAX ! = newEdge . target ) ;
2012-04-04 07:08:13 -04:00
2012-02-23 10:29:55 -05:00
newEdge . data . distance = data . distance ;
newEdge . data . shortcut = data . shortcut ;
2012-04-04 03:55:43 -04:00
if ( ! data . originalViaNodeID )
2012-04-25 04:51:16 -04:00
newEdge . data . id = oldNodeIDFromNewNodeIDMap [ data . id ] ;
2012-04-04 03:55:43 -04:00
else
2012-04-25 04:51:16 -04:00
newEdge . data . id = data . id ;
2012-04-04 03:55:43 -04:00
2012-04-04 07:08:13 -04:00
assert ( newEdge . data . via ! = UINT_MAX ) ;
2012-04-25 04:51:16 -04:00
// newEdge.data.nameID = data.nameID;
// newEdge.data.turnInstruction = data.turnInstruction;
2012-02-23 10:29:55 -05:00
newEdge . data . forward = data . forward ;
newEdge . data . backward = data . backward ;
edges . push_back ( newEdge ) ;
}
}
2012-04-04 03:55:43 -04:00
std : : ifstream temporaryEdgeStorage ( temporaryEdgeStorageFilename . c_str ( ) , std : : ios : : binary ) ;
//Also get the edges from temporary storage
unsigned numberOfTemporaryEdges = 0 ;
temporaryEdgeStorage . read ( ( char * ) & numberOfTemporaryEdges , sizeof ( unsigned ) ) ;
//loads edges of graph before renumbering, no need for further numbering action.
NodeID start ;
NodeID target ;
_DynamicGraph : : EdgeData data ;
for ( unsigned i = 0 ; i < numberOfTemporaryEdges ; + + i ) {
temporaryEdgeStorage . read ( ( char * ) & start , sizeof ( NodeID ) ) ;
temporaryEdgeStorage . read ( ( char * ) & target , sizeof ( NodeID ) ) ;
temporaryEdgeStorage . read ( ( char * ) & data , sizeof ( _DynamicGraph : : EdgeData ) ) ;
Edge newEdge ;
newEdge . source = start ;
newEdge . target = target ;
newEdge . data . distance = data . distance ;
newEdge . data . shortcut = data . shortcut ;
2012-04-25 04:51:16 -04:00
newEdge . data . id = data . id ;
// newEdge.data.nameID = data.nameID;
// newEdge.data.turnInstruction = data.turnInstruction;
2012-04-04 03:55:43 -04:00
newEdge . data . forward = data . forward ;
newEdge . data . backward = data . backward ;
edges . push_back ( newEdge ) ;
}
temporaryEdgeStorage . close ( ) ;
2012-02-23 10:29:55 -05:00
}
2010-08-12 11:42:22 -04:00
2010-07-09 05:05:40 -04:00
private :
2012-02-23 10:29:55 -05:00
inline void _Dijkstra ( const int maxDistance , const unsigned numTargets , const int maxNodes , const int hopLimit , _ThreadData * const data ) {
_Heap & heap = data - > heap ;
int nodes = 0 ;
unsigned targetsFound = 0 ;
while ( heap . Size ( ) > 0 ) {
const NodeID node = heap . DeleteMin ( ) ;
const int distance = heap . GetKey ( node ) ;
const short currentHop = heap . GetData ( node ) . hop + 1 ;
if ( + + nodes > maxNodes )
return ;
//Destination settled?
if ( distance > maxDistance )
return ;
if ( heap . GetData ( node ) . target ) {
+ + targetsFound ;
if ( targetsFound > = numTargets )
return ;
}
if ( currentHop > = hopLimit )
2012-02-07 05:52:22 -05:00
continue ;
2012-02-23 10:29:55 -05:00
//iterate over all edges of node
for ( _DynamicGraph : : EdgeIterator edge = _graph - > BeginEdges ( node ) , endEdges = _graph - > EndEdges ( node ) ; edge ! = endEdges ; + + edge ) {
const _EdgeBasedContractorEdgeData & data = _graph - > GetEdgeData ( edge ) ;
if ( ! data . forward )
continue ;
const NodeID to = _graph - > GetTarget ( edge ) ;
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 ) ) ;
//Found a shorter Path -> Update distance
else if ( toDistance < heap . GetKey ( to ) ) {
heap . DecreaseKey ( to , toDistance ) ;
heap . GetData ( to ) . hop = currentHop ;
}
}
}
}
2012-03-07 02:49:10 -05:00
double _Evaluate ( _ThreadData * const data , _PriorityData * const nodeData , NodeID node ) {
2012-02-23 10:29:55 -05:00
_ContractionInformation stats ;
//perform simulated contraction
2012-03-07 02:49:10 -05:00
_Contract < true > ( data , node , & stats ) ;
2012-02-23 10:29:55 -05:00
// Result will contain the priority
2012-03-07 02:49:10 -05:00
double result ;
2012-02-23 10:29:55 -05:00
if ( stats . edgesDeleted = = 0 | | stats . originalEdgesDeleted = = 0 )
2012-03-07 02:49:10 -05:00
result = 1 * nodeData - > depth ;
else
result = 2 * ( ( ( double ) stats . edgesAdded ) / stats . edgesDeleted ) + 4 * ( ( ( double ) stats . originalEdgesAdded ) / stats . originalEdgesDeleted ) + 1 * nodeData - > depth ;
assert ( result > = 0 ) ;
return result ;
2012-02-23 10:29:55 -05:00
}
2012-03-07 02:49:10 -05:00
template < bool Simulate >
2012-02-23 10:29:55 -05:00
bool _Contract ( _ThreadData * data , NodeID node , _ContractionInformation * stats = NULL ) {
_Heap & heap = data - > heap ;
int insertedEdgesSize = data - > insertedEdges . size ( ) ;
std : : vector < _ImportEdge > & insertedEdges = data - > insertedEdges ;
for ( _DynamicGraph : : EdgeIterator inEdge = _graph - > BeginEdges ( node ) , endInEdges = _graph - > EndEdges ( node ) ; inEdge ! = endInEdges ; + + inEdge ) {
const _EdgeBasedContractorEdgeData & inData = _graph - > GetEdgeData ( inEdge ) ;
const NodeID source = _graph - > GetTarget ( inEdge ) ;
if ( Simulate ) {
assert ( stats ! = NULL ) ;
+ + stats - > edgesDeleted ;
stats - > originalEdgesDeleted + = inData . originalEdges ;
}
if ( ! inData . backward )
continue ;
heap . Clear ( ) ;
heap . Insert ( source , 0 , _HeapData ( ) ) ;
if ( node ! = source )
heap . Insert ( node , inData . distance , _HeapData ( ) ) ;
int maxDistance = 0 ;
unsigned numTargets = 0 ;
for ( _DynamicGraph : : EdgeIterator outEdge = _graph - > BeginEdges ( node ) , endOutEdges = _graph - > EndEdges ( node ) ; outEdge ! = endOutEdges ; + + outEdge ) {
const _EdgeBasedContractorEdgeData & outData = _graph - > GetEdgeData ( outEdge ) ;
if ( ! outData . forward )
continue ;
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 , pathDistance , _HeapData ( 0 , true ) ) ;
+ + numTargets ;
} else if ( pathDistance < heap . GetKey ( target ) ) {
heap . DecreaseKey ( target , pathDistance ) ;
}
}
if ( Simulate )
_Dijkstra ( maxDistance , numTargets , 1000 , ( true ? INT_MAX : 5 ) , data ) ;
else
_Dijkstra ( maxDistance , numTargets , 2000 , ( true ? INT_MAX : 7 ) , data ) ;
for ( _DynamicGraph : : EdgeIterator outEdge = _graph - > BeginEdges ( node ) , endOutEdges = _graph - > EndEdges ( node ) ; outEdge ! = endOutEdges ; + + outEdge ) {
const _EdgeBasedContractorEdgeData & outData = _graph - > GetEdgeData ( outEdge ) ;
if ( ! outData . forward )
continue ;
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 {
_ImportEdge newEdge ;
newEdge . source = source ;
newEdge . target = target ;
2012-04-25 04:51:16 -04:00
newEdge . data = _EdgeBasedContractorEdgeData ( pathDistance , outData . originalEdges + inData . originalEdges , node /*, 0, inData.turnInstruction*/ , true , true , false ) ; ;
2012-02-23 10:29:55 -05:00
insertedEdges . push_back ( newEdge ) ;
std : : swap ( newEdge . source , newEdge . target ) ;
newEdge . data . forward = false ;
newEdge . data . backward = true ;
insertedEdges . push_back ( newEdge ) ;
}
}
}
}
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 )
continue ;
if ( insertedEdges [ other ] . target ! = insertedEdges [ i ] . target )
continue ;
if ( insertedEdges [ other ] . data . distance ! = insertedEdges [ i ] . data . distance )
continue ;
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 ;
found = true ;
break ;
}
if ( ! found )
insertedEdges [ insertedEdgesSize + + ] = insertedEdges [ i ] ;
}
insertedEdges . resize ( insertedEdgesSize ) ;
}
return true ;
}
void _DeleteIncomingEdges ( _ThreadData * data , NodeID node ) {
std : : vector < NodeID > & 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 ) ;
}
//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 ) {
// const NodeID u = neighbours[i];
_graph - > DeleteEdgesTo ( neighbours [ i ] , node ) ;
}
}
2012-03-07 02:49:10 -05:00
bool _UpdateNeighbours ( std : : vector < double > & priorities , std : : vector < _PriorityData > & nodeData , _ThreadData * const data , NodeID node ) {
2012-02-23 10:29:55 -05:00
std : : vector < NodeID > & 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 )
continue ;
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 ( ) ) ;
int neighbourSize = ( int ) neighbours . size ( ) ;
for ( int i = 0 , e = neighbourSize ; i < e ; + + i ) {
const NodeID u = neighbours [ i ] ;
2012-03-07 02:49:10 -05:00
priorities [ u ] = _Evaluate ( data , & ( nodeData ) [ u ] , u ) ;
2012-02-23 10:29:55 -05:00
}
return true ;
}
bool _IsIndependent ( const std : : vector < double > & priorities , const std : : vector < _PriorityData > & nodeData , _ThreadData * const data , NodeID node ) {
const double priority = priorities [ node ] ;
std : : vector < NodeID > & neighbours = data - > neighbours ;
neighbours . clear ( ) ;
for ( _DynamicGraph : : EdgeIterator e = _graph - > BeginEdges ( node ) ; e < _graph - > EndEdges ( node ) ; + + e ) {
const NodeID target = _graph - > GetTarget ( e ) ;
const double targetPriority = priorities [ target ] ;
assert ( targetPriority > = 0 ) ;
//found a neighbour with lower priority?
if ( priority > targetPriority )
return false ;
//tie breaking
if ( priority = = targetPriority & & nodeData [ node ] . bias < nodeData [ target ] . bias )
return false ;
neighbours . push_back ( target ) ;
}
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 ( std : : vector < NodeID > : : const_iterator i = neighbours . begin ( ) , lastNode = neighbours . end ( ) ; i ! = lastNode ; + + i ) {
const NodeID u = * i ;
for ( _DynamicGraph : : EdgeIterator e = _graph - > BeginEdges ( u ) ; e < _graph - > EndEdges ( u ) ; + + e ) {
const NodeID target = _graph - > GetTarget ( e ) ;
const double targetPriority = priorities [ target ] ;
assert ( targetPriority > = 0 ) ;
//found a neighbour with lower priority?
if ( priority > targetPriority )
return false ;
//tie breaking
if ( priority = = targetPriority & & nodeData [ node ] . bias < nodeData [ target ] . bias )
return false ;
}
}
return true ;
}
boost : : shared_ptr < _DynamicGraph > _graph ;
2012-03-24 15:15:04 -04:00
std : : vector < _DynamicGraph : : InputEdge > contractedEdges ;
2012-04-04 03:55:43 -04:00
std : : string temporaryEdgeStorageFilename ;
std : : vector < NodeID > oldNodeIDFromNewNodeIDMap ;
long initialFilePosition ;
2010-07-09 05:05:40 -04:00
} ;
# endif // CONTRACTOR_H_INCLUDED