fixing sentinel nodes in adjacency list graph data structure

This commit is contained in:
Dennis Luxen 2014-03-19 16:42:37 +01:00
parent fdebec6448
commit 87f036e538
10 changed files with 153 additions and 63 deletions

View File

@ -48,7 +48,8 @@ EdgeBasedGraphFactory::EdgeBasedGraphFactory(
) : speed_profile(speed_profile),
m_turn_restrictions_count(0),
m_number_of_edge_based_nodes(std::numeric_limits<unsigned>::max()),
m_node_info_list(node_info_list)
m_node_info_list(node_info_list),
max_id(0)
{
BOOST_FOREACH(const TurnRestriction & restriction, input_restrictions_list) {
std::pair<NodeID, NodeID> restriction_source =
@ -384,10 +385,20 @@ void EdgeBasedGraphFactory::InsertEdgeBasedNode(
const unsigned geometry_size = forward_geometry.size();
BOOST_ASSERT( geometry_size > 1 );
NodeID current_edge_start_coordinate_id = u;
if (forward_data.edgeBasedNodeID != SPECIAL_NODEID)
{
max_id = std::max(forward_data.edgeBasedNodeID, max_id);
}
if (SPECIAL_NODEID != reverse_data.edgeBasedNodeID)
{
max_id = std::max(reverse_data.edgeBasedNodeID, max_id);
}
// traverse arrays from start and end respectively
for( unsigned i = 0; i < geometry_size; ++i ) {
BOOST_ASSERT( current_edge_start_coordinate_id == reverse_geometry[geometry_size-1-i].first );
const NodeID current_edge_target_coordinate_id = forward_geometry[i].first;
BOOST_ASSERT( current_edge_target_coordinate_id != current_edge_start_coordinate_id);
// build edges
m_edge_based_node_list.push_back(
@ -888,6 +899,7 @@ void EdgeBasedGraphFactory::Run(
" skips " << skipped_uturns_counter << " U turns";
SimpleLogger().Write() <<
" skips " << skipped_barrier_turns_counter << " turns over barriers";
SimpleLogger().Write(logDEBUG) << "maximum written id: " << max_id;
}
int EdgeBasedGraphFactory::GetTurnPenalty(

View File

@ -206,6 +206,8 @@ private:
const NodeID v,
const NodeID w
);
unsigned max_id;
};
#endif /* EDGEBASEDGRAPHFACTORY_H_ */

View File

@ -29,6 +29,7 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#define PHANTOMNODES_H_
#include <osrm/Coordinate.h>
#include "../Util/SimpleLogger.h"
#include "../typedefs.h"
struct PhantomNode {
@ -59,11 +60,14 @@ struct PhantomNode {
int GetForwardWeightPlusOffset() const {
return forward_weight + forward_offset;
SimpleLogger().Write(logDEBUG) << "->fwd_offset: " << forward_offset << ", weight: " << forward_weight;
return reverse_offset + forward_weight;
}
int GetReverseWeightPlusOffset() const {
return reverse_offset + reverse_weight;
SimpleLogger().Write(logDEBUG) << "->rev_offset: " << reverse_offset << ", weight: " << reverse_weight;
return forward_offset + reverse_weight;
}
void Reset() {

View File

@ -101,6 +101,12 @@ public:
_nodes.swap(nodes);
_edges.swap(edges);
for(unsigned i = 0; i < _numNodes; ++i)
{
SimpleLogger().Write(logDEBUG) << "edges of " << i << ": [" << BeginEdges(i) << "," << EndEdges(i) << ")";
}
#ifndef NDEBUG
Percent p(GetNumberOfNodes());
for(unsigned u = 0; u < GetNumberOfNodes(); ++u) {
@ -112,7 +118,7 @@ public:
if(eid2 == UINT_MAX) {
SimpleLogger().Write(logWARNING) <<
"cannot find first segment of edge (" <<
u << "," << data.id << "," << v << ")";
u << "," << data.id << "," << v << "), eid: " << eid;
data.shortcut = false;
BOOST_ASSERT(false);
@ -121,7 +127,7 @@ public:
if(eid2 == UINT_MAX) {
SimpleLogger().Write(logWARNING) <<
"cannot find second segment of edge (" <<
u << "," << data.id << "," << v << ")";
u << "," << data.id << "," << v << "), eid2: " << eid2;
data.shortcut = false;
BOOST_ASSERT(false);
}
@ -129,6 +135,10 @@ public:
}
p.printIncrement();
}
for(unsigned i = 0; i < _numNodes; ++i)
{
SimpleLogger().Write(logDEBUG) << "edges of " << i << ": [" << BeginEdges(i) << "," << EndEdges(i) << ")";
}
#endif
}
@ -157,11 +167,11 @@ public:
}
EdgeIterator BeginEdges( const NodeIterator n ) const {
return EdgeIterator( _nodes[n].firstEdge );
return EdgeIterator( _nodes.at(n).firstEdge );
}
EdgeIterator EndEdges( const NodeIterator n ) const {
return EdgeIterator( _nodes[n+1].firstEdge );
return EdgeIterator( _nodes.at(n+1).firstEdge );
}
//searches for a specific edge

View File

@ -765,11 +765,11 @@ public:
if (SPECIAL_NODEID != result_phantom_node.forward_node_id)
{
result_phantom_node.forward_weight *= (1.-ratio);
result_phantom_node.forward_weight *= (ratio);
}
if( SPECIAL_NODEID != result_phantom_node.reverse_node_id )
{
result_phantom_node.reverse_weight *= ratio;
result_phantom_node.reverse_weight *= 1.-ratio;
}
result_phantom_node.ratio = ratio;

View File

@ -86,6 +86,7 @@ public:
const PhantomNodes & phantom_node_pair,
RawRouteData & raw_route_data
) {
SimpleLogger().Write(logDEBUG) << "alt path routing";
if( //phantom_node_pair.AtLeastOnePhantomNodeIsUINTMAX() ||
phantom_node_pair.PhantomNodesHaveEqualLocation()
) {
@ -628,7 +629,7 @@ private:
const NodeID node = forward_heap.DeleteMin();
const int distance = forward_heap.GetKey(node);
const int scaled_distance = (distance-edge_expansion_offset)/(1.+VIAPATH_EPSILON);
SimpleLogger().Write(logDEBUG) << "node: " << node << ", distance: " << distance << ", ub: " << *upper_bound_to_shortest_path_distance << ", scaled_distance: " << scaled_distance;
// SimpleLogger().Write(logDEBUG) << "node: " << node << ", distance: " << distance << ", ub: " << *upper_bound_to_shortest_path_distance << ", scaled_distance: " << scaled_distance;
if(
(INVALID_EDGE_WEIGHT != *upper_bound_to_shortest_path_distance) &&
(scaled_distance > *upper_bound_to_shortest_path_distance)

View File

@ -67,9 +67,10 @@ public:
) const {
const NodeID node = forward_heap.DeleteMin();
const int distance = forward_heap.GetKey(node);
// SimpleLogger().Write() << (forward_direction ? "fwd" : "rev") << " settled (" << forward_heap.GetData( node ).parent << "," << node << ")=" << distance;
SimpleLogger().Write() << (forward_direction ? "fwd" : "rev") << " settled (" << forward_heap.GetData( node ).parent << "," << node << ")=" << distance;
if(reverse_heap.WasInserted(node) ){
const int new_distance = reverse_heap.GetKey(node) + distance;
SimpleLogger().Write(logDEBUG) << "new_distance: " << new_distance;
if(new_distance < *upper_bound ){
if( new_distance >= 0 ) {
*middle_node_id = node;
@ -79,6 +80,7 @@ public:
}
if( (distance-edge_expansion_offset) > *upper_bound ){
SimpleLogger().Write() << "found path";
forward_heap.DeleteAll();
return;
}
@ -99,12 +101,13 @@ public:
if(forward_heap.WasInserted( to )) {
if(forward_heap.GetKey( to ) + edge_weight < distance) {
SimpleLogger().Write(logDEBUG) << "stalled";
return;
}
}
}
}
SimpleLogger().Write(logDEBUG) << "done stalling";
for(
EdgeID edge = facade->BeginEdges(node), end_edge = facade->EndEdges(node);
edge < end_edge;
@ -122,12 +125,14 @@ public:
//New Node discovered -> Add to Heap + Node Info Storage
if ( !forward_heap.WasInserted( to ) ) {
SimpleLogger().Write() << "insert (" << node << "," << to << "), distance: " << to_distance << ", edge id: " << edge;
forward_heap.Insert( to, to_distance, node );
}
//Found a shorter Path -> Update distance
else if ( to_distance < forward_heap.GetKey( to ) ) {
forward_heap.GetData( to ).parent = node;
forward_heap.DecreaseKey( to, to_distance );
SimpleLogger().Write() << "decrease (" << node << "," << to << "), distance: " << to_distance;
//new parent
}
}
@ -286,8 +291,8 @@ public:
if (is_local_path)
{
SimpleLogger().Write(logDEBUG) << "case3";
start_index = phantom_node_pair.startPhantom.fwd_segment_position - 1;
end_index = phantom_node_pair.targetPhantom.fwd_segment_position - 1;
start_index = phantom_node_pair.startPhantom.fwd_segment_position;
end_index = phantom_node_pair.targetPhantom.fwd_segment_position;
if (target_traversed_in_reverse)
{
SimpleLogger().Write(logDEBUG) << "case4";
@ -301,11 +306,15 @@ public:
BOOST_ASSERT( start_index >= 0 );
// BOOST_ASSERT( start_index <= end_index );
for(
unsigned i = start_index;
int i = start_index;
i != end_index;
( start_index < end_index ? ++i :--i)
) {
SimpleLogger().Write(logDEBUG) << "[" << i << "]" << facade->GetCoordinateOfNode(id_vector[i]);
BOOST_ASSERT( i >= -1 );
if ( i >= 0 )
{
SimpleLogger().Write(logDEBUG) << "[" << i << "]" << facade->GetCoordinateOfNode(id_vector[i]);
}
unpacked_path.push_back(
PathData(
id_vector[i],

View File

@ -113,12 +113,12 @@ public:
SimpleLogger().Write(logDEBUG) << "fwd1 insert: " << phantom_node_pair.startPhantom.forward_node_id << ", w: " << -phantom_node_pair.startPhantom.GetForwardWeightPlusOffset();
forward_heap1.Insert(
phantom_node_pair.startPhantom.forward_node_id,
-distance1-phantom_node_pair.startPhantom.GetForwardWeightPlusOffset(),
distance1-phantom_node_pair.startPhantom.GetForwardWeightPlusOffset(),
phantom_node_pair.startPhantom.forward_node_id
);
forward_heap2.Insert(
phantom_node_pair.startPhantom.forward_node_id,
-distance1-phantom_node_pair.startPhantom.GetForwardWeightPlusOffset(),
distance1-phantom_node_pair.startPhantom.GetForwardWeightPlusOffset(),
phantom_node_pair.startPhantom.forward_node_id
);
}
@ -129,12 +129,12 @@ public:
SimpleLogger().Write(logDEBUG) << "fwd1 insert: " << phantom_node_pair.startPhantom.reverse_node_id << ", w: " << -phantom_node_pair.startPhantom.GetReverseWeightPlusOffset();
forward_heap1.Insert(
phantom_node_pair.startPhantom.reverse_node_id,
-distance2-phantom_node_pair.startPhantom.GetReverseWeightPlusOffset(),
distance2-phantom_node_pair.startPhantom.GetReverseWeightPlusOffset(),
phantom_node_pair.startPhantom.reverse_node_id
);
forward_heap2.Insert(
phantom_node_pair.startPhantom.reverse_node_id,
-distance2-phantom_node_pair.startPhantom.GetReverseWeightPlusOffset(),
distance2-phantom_node_pair.startPhantom.GetReverseWeightPlusOffset(),
phantom_node_pair.startPhantom.reverse_node_id
);
}
@ -369,8 +369,8 @@ public:
for(unsigned i = 0; i < packed_legs1.size(); ++i){
BOOST_ASSERT( !phantom_nodes_vector.empty() );
const bool at_beginning = (packed_legs1[i] == packed_legs1.front());
const bool at_end = (packed_legs1[i] == packed_legs1.back());
// const bool at_beginning = (packed_legs1[i] == packed_legs1.front());
// const bool at_end = (packed_legs1[i] == packed_legs1.back());
BOOST_ASSERT(packed_legs1.size() == raw_route_data.unpacked_path_segments.size() );
PhantomNodes unpack_phantom_node_pair = phantom_nodes_vector[i];

View File

@ -446,6 +446,9 @@ unsigned readHSGRFromStream(
hsgr_input_stream.read( (char*) &number_of_nodes, sizeof(unsigned) );
BOOST_ASSERT_MSG( 0 != number_of_nodes, "number of nodes is zero");
hsgr_input_stream.read( (char*) &number_of_edges, sizeof(unsigned) );
SimpleLogger().Write() << "number_of_nodes: " << number_of_nodes << ", number_of_edges: " << number_of_edges;
// BOOST_ASSERT_MSG( 0 != number_of_edges, "number of edges is zero");
node_list.resize(number_of_nodes + 1);
hsgr_input_stream.read(
@ -459,6 +462,16 @@ unsigned readHSGRFromStream(
number_of_edges*sizeof(EdgeT)
);
hsgr_input_stream.close();
for(unsigned i = 0; i < number_of_nodes; ++i)
{
SimpleLogger().Write(logDEBUG) << "node_list[" << i << "]=" << node_list[i].firstEdge;
}
for(unsigned i = 0; i < number_of_edges; ++i)
{
SimpleLogger().Write(logDEBUG) << "edge_list[" << i << "]=(*," << edge_list[i].target << "), w: " << edge_list[i].data.distance;
}
return number_of_nodes;
}

View File

@ -181,7 +181,7 @@ int main (int argc, char *argv[]) {
restrictionsInstream.close();
std::ifstream in;
in.open (input_path.c_str(), std::ifstream::in | std::ifstream::binary);
in.open(input_path.c_str(), std::ifstream::in|std::ifstream::binary);
const std::string nodeOut = input_path.string() + ".nodes";
const std::string edgeOut = input_path.string() + ".edges";
@ -327,86 +327,126 @@ int main (int argc, char *argv[]) {
*/
std::sort(contractedEdgeList.begin(), contractedEdgeList.end());
unsigned numberOfNodes = 0;
unsigned numberOfEdges = contractedEdgeList.size();
unsigned max_used_node_id = 0;
unsigned contracted_edge_count = contractedEdgeList.size();
SimpleLogger().Write() <<
"Serializing compacted graph of " <<
numberOfEdges <<
contracted_edge_count <<
" edges";
std::ofstream hsgr_output_stream(graphOut, std::ios::binary);
hsgr_output_stream.write((char*)&uuid_orig, sizeof(UUID) );
BOOST_FOREACH(const QueryEdge & edge, contractedEdgeList) {
BOOST_FOREACH(const QueryEdge & edge, contractedEdgeList)
{
BOOST_ASSERT( UINT_MAX != edge.source );
BOOST_ASSERT( UINT_MAX != edge.target );
if(edge.source > numberOfNodes) {
numberOfNodes = edge.source;
}
if(edge.target > numberOfNodes) {
numberOfNodes = edge.target;
}
max_used_node_id = std::max(max_used_node_id, edge.source);
max_used_node_id = std::max(max_used_node_id, edge.target);
}
numberOfNodes+=1;
SimpleLogger().Write(logDEBUG) << "input graph has " << edgeBasedNodeNumber << " nodes";
SimpleLogger().Write(logDEBUG) << "contracted graph has " << max_used_node_id << " nodes";
max_used_node_id+=1;
std::vector< StaticGraph<EdgeData>::_StrNode > _nodes;
_nodes.resize( numberOfNodes + 1 );
std::vector< StaticGraph<EdgeData>::_StrNode > node_array;
node_array.resize( edgeBasedNodeNumber + 1);
SimpleLogger().Write() << "Building node array";
StaticGraph<EdgeData>::EdgeIterator edge = 0;
StaticGraph<EdgeData>::EdgeIterator position = 0;
for ( StaticGraph<EdgeData>::NodeIterator node = 0; node < numberOfNodes; ++node ) {
StaticGraph<EdgeData>::EdgeIterator lastEdge = edge;
while ( edge < numberOfEdges && contractedEdgeList[edge].source == node )
StaticGraph<EdgeData>::EdgeIterator lastEdge = edge;
for ( StaticGraph<EdgeData>::NodeIterator node = 0; node < max_used_node_id; ++node ) {
lastEdge = edge;
while ( edge < contracted_edge_count && contractedEdgeList[edge].source == node )
{
++edge;
_nodes[node].firstEdge = position; //=edge
}
node_array[node].firstEdge = position; //=edge
position += edge - lastEdge; //remove
SimpleLogger().Write(logDEBUG) << "node: " << node << ", edge: " << edge << ", position: " << position << ", lastEdge: " << lastEdge;
}
_nodes.back().firstEdge = numberOfEdges; //sentinel element
++numberOfNodes;
SimpleLogger().Write(logDEBUG) << "contracted_edge_count: " << contracted_edge_count << ", position: " << position << ", lastEdge: " << lastEdge;
SimpleLogger().Write(logDEBUG) << "marking range [" << max_used_node_id << "," << node_array.size() << ") as dummies";
BOOST_ASSERT_MSG(
_nodes.size() == numberOfNodes,
"no. of nodes dont match"
);
for (unsigned sentinel_counter = max_used_node_id;
sentinel_counter != node_array.size();
++sentinel_counter
)
{
//sentinel element, guarded against underflow
node_array[sentinel_counter].firstEdge = contracted_edge_count;
SimpleLogger().Write(logDEBUG) << "node_array[" << sentinel_counter << "].firstEdge = " << node_array[sentinel_counter].firstEdge;
}
// node_array.back().firstEdge = contracted_edge_count; //sentinel element
// ++max_used_node_id;
// BOOST_ASSERT_MSG(
// node_array.size() == max_used_node_id,
// "no. of nodes dont match"
// );
for(unsigned i = 0; i < node_array.size(); ++i)
{
SimpleLogger().Write() << "node_array[" << i << "].firstEdge = " << node_array[i].firstEdge;
}
unsigned node_array_size = node_array.size();
//serialize crc32, aka checksum
hsgr_output_stream.write((char*) &crc32OfNodeBasedEdgeList, sizeof(unsigned));
//serialize number f nodes
hsgr_output_stream.write((char*) &numberOfNodes, sizeof(unsigned));
//serialize number of nodes
hsgr_output_stream.write((char*) &node_array_size, sizeof(unsigned));
//serialize number of edges
hsgr_output_stream.write((char*) &position, sizeof(unsigned));
hsgr_output_stream.write((char*) &contracted_edge_count, sizeof(unsigned));
//serialize all nodes
hsgr_output_stream.write((char*) &_nodes[0], sizeof(StaticGraph<EdgeData>::_StrNode)*(numberOfNodes));
hsgr_output_stream.write((char*) &node_array[0], sizeof(StaticGraph<EdgeData>::_StrNode)*node_array_size);
//serialize all edges
--numberOfNodes;
SimpleLogger().Write() << "Building edge array";
edge = 0;
int usedEdgeCounter = 0;
SimpleLogger().Write() << "Building Node Array";
for(unsigned edge = 0; edge < contractedEdgeList.size(); ++edge)
{
SimpleLogger().Write(logDEBUG) << ">[" << edge << "] (" << contractedEdgeList[edge].source << "," << contractedEdgeList[edge].target << ")";
}
StaticGraph<EdgeData>::_StrEdge currentEdge;
for ( StaticGraph<EdgeData>::NodeIterator node = 0; node < numberOfNodes; ++node ) {
for ( StaticGraph<EdgeData>::EdgeIterator i = _nodes[node].firstEdge, e = _nodes[node+1].firstEdge; i != e; ++i ) {
assert(node != contractedEdgeList[edge].target);
for(unsigned edge = 0; edge < contractedEdgeList.size(); ++edge)
{
// for ( StaticGraph<EdgeData>::NodeIterator node = 0; node < max_used_node_id; ++node ) {
// for ( StaticGraph<EdgeData>::EdgeIterator i = node_array[node].firstEdge, e = node_array[node+1].firstEdge; i != e; ++i ) {
// BOOST_ASSERT(node == contractedEdgeList[edge].source)
// no eigen loops
BOOST_ASSERT(contractedEdgeList[edge].source != contractedEdgeList[edge].target);
currentEdge.target = contractedEdgeList[edge].target;
currentEdge.data = contractedEdgeList[edge].data;
// every target needs to be valid
BOOST_ASSERT(currentEdge.target < max_used_node_id);
if(currentEdge.data.distance <= 0) {
SimpleLogger().Write(logWARNING) <<
"Edge: " << i <<
"Edge: " << edge <<
",source: " << contractedEdgeList[edge].source <<
", target: " << contractedEdgeList[edge].target <<
", dist: " << currentEdge.data.distance;
SimpleLogger().Write(logWARNING) <<
"Failed at edges of node " << node <<
" of " << numberOfNodes;
"Failed at adjacency list of node " << contractedEdgeList[edge].source << "/" << node_array.size()-1;
return 1;
}
//Serialize edges
SimpleLogger().Write(logDEBUG) << "edge[" << edge << "], (" << contractedEdgeList[edge].source << "," << currentEdge.target << "), w: " << currentEdge.data.distance <<
"shortcut: " << (currentEdge.data.shortcut ? "y" : "n");
hsgr_output_stream.write((char*) &currentEdge, sizeof(StaticGraph<EdgeData>::_StrEdge));
++edge;
// ++edge;
++usedEdgeCounter;
}
}
// }
hsgr_output_stream.close();
SimpleLogger().Write() << "Preprocessing : " <<
(get_timestamp() - startupTime) << " seconds";
SimpleLogger().Write() << "Expansion : " <<
@ -417,11 +457,10 @@ int main (int argc, char *argv[]) {
(edgeBasedNodeNumber/contraction_duration) << " nodes/sec and " <<
usedEdgeCounter/contraction_duration << " edges/sec";
hsgr_output_stream.close();
//cleanedEdgeList.clear();
_nodes.clear();
node_array.clear();
SimpleLogger().Write() << "finished preprocessing";
} catch(boost::program_options::too_many_positional_options_error& e) {
} catch(boost::program_options::too_many_positional_options_error&) {
SimpleLogger().Write(logWARNING) << "Only one file can be specified";
return 1;
} catch(boost::program_options::error& e) {