Find components on edge-expanded graph

This commit is contained in:
Patrick Niklaus 2015-07-04 17:37:24 +02:00
parent c2f0e4f683
commit c80c2233c5
6 changed files with 66 additions and 47 deletions

View File

@ -72,11 +72,11 @@ template <typename GraphT> class TarjanSCC
std::vector<unsigned> components_index;
std::vector<NodeID> component_size_vector;
std::shared_ptr<GraphT> m_graph;
std::shared_ptr<const GraphT> m_graph;
std::size_t size_one_counter;
public:
TarjanSCC(std::shared_ptr<GraphT> graph)
TarjanSCC(std::shared_ptr<const GraphT> graph)
: components_index(graph->GetNumberOfNodes(), SPECIAL_NODEID), m_graph(graph),
size_one_counter(0)
{

View File

@ -26,7 +26,6 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include "edge_based_graph_factory.hpp"
#include "../algorithms/tiny_components.hpp"
#include "../data_structures/percent.hpp"
#include "../util/compute_angle.hpp"
#include "../util/integer_range.hpp"
@ -83,8 +82,7 @@ unsigned EdgeBasedGraphFactory::GetHighestEdgeID()
}
void EdgeBasedGraphFactory::InsertEdgeBasedNode(const NodeID node_u,
const NodeID node_v,
const unsigned component_id)
const NodeID node_v)
{
// merge edges together into one EdgeBasedNode
BOOST_ASSERT(node_u != SPECIAL_NODEID);
@ -164,7 +162,7 @@ void EdgeBasedGraphFactory::InsertEdgeBasedNode(const NodeID node_u,
forward_data.name_id, forward_geometry[i].second,
reverse_geometry[geometry_size - 1 - i].second, forward_dist_prefix_sum[i],
reverse_dist_prefix_sum[i], m_compressed_edge_container.GetPositionForID(edge_id_1),
component_id, i, forward_data.travel_mode, reverse_data.travel_mode);
INVALID_COMPONENTID, i, forward_data.travel_mode, reverse_data.travel_mode);
current_edge_source_coordinate_id = current_edge_target_coordinate_id;
BOOST_ASSERT(m_edge_based_node_list.back().IsCompressed());
@ -207,7 +205,7 @@ void EdgeBasedGraphFactory::InsertEdgeBasedNode(const NodeID node_u,
m_edge_based_node_list.emplace_back(
forward_data.edge_id, reverse_data.edge_id, node_u, node_v,
forward_data.name_id, forward_data.distance, reverse_data.distance, 0, 0, SPECIAL_EDGEID,
component_id, 0, forward_data.travel_mode, reverse_data.travel_mode);
INVALID_COMPONENTID, 0, forward_data.travel_mode, reverse_data.travel_mode);
BOOST_ASSERT(!m_edge_based_node_list.back().IsCompressed());
}
}
@ -279,21 +277,6 @@ unsigned EdgeBasedGraphFactory::RenumberEdges()
/// Creates the nodes in the edge expanded graph from edges in the node-based graph.
void EdgeBasedGraphFactory::GenerateEdgeExpandedNodes()
{
SimpleLogger().Write() << "Identifying components of the (compressed) road network";
// Run a BFS on the undirected graph and identify small components
TarjanSCC<NodeBasedDynamicGraph> component_explorer(m_node_based_graph);
component_explorer.run();
SimpleLogger().Write() << "identified: "
<< component_explorer.get_number_of_components()
<< " (compressed) components";
SimpleLogger().Write() << "identified "
<< component_explorer.get_size_one_count()
<< " (compressed) SCCs of size 1";
SimpleLogger().Write() << "generating edge-expanded nodes";
Percent progress(m_node_based_graph->GetNumberOfNodes());
// loop over all edges and generate new set of nodes
@ -318,34 +301,14 @@ void EdgeBasedGraphFactory::GenerateEdgeExpandedNodes()
BOOST_ASSERT(node_u < node_v);
// Note: edges that end on barrier nodes or on a turn restriction
// may actually be in two distinct components. We choose the smallest
const unsigned size_of_component =
std::min(component_explorer.get_component_size(node_u),
component_explorer.get_component_size(node_v));
const unsigned id_of_smaller_component = [node_u, node_v, &component_explorer]
{
if (component_explorer.get_component_size(node_u) <
component_explorer.get_component_size(node_v))
{
return component_explorer.get_component_id(node_u);
}
return component_explorer.get_component_id(node_v);
}();
const bool component_is_tiny = size_of_component < 1000;
// we only set edge_id for forward edges
// if we found a non-forward edge reverse and try again
if (edge_data.edge_id == SPECIAL_NODEID)
{
InsertEdgeBasedNode(node_v, node_u,
(component_is_tiny ? id_of_smaller_component + 1 : 0));
InsertEdgeBasedNode(node_v, node_u);
}
else
{
InsertEdgeBasedNode(node_u, node_v,
(component_is_tiny ? id_of_smaller_component + 1 : 0));
InsertEdgeBasedNode(node_u, node_v);
}
}
}

View File

@ -103,7 +103,7 @@ class EdgeBasedGraphFactory
void GenerateEdgeExpandedEdges(const std::string &original_edge_data_filename,
lua_State *lua_state);
void InsertEdgeBasedNode(const NodeID u, const NodeID v, const unsigned component_id);
void InsertEdgeBasedNode(const NodeID u, const NodeID v);
void FlushVectorToStream(std::ofstream &edge_data_file,
std::vector<OriginalEdgeData> &original_edge_data_vector) const;

View File

@ -29,7 +29,7 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include "contractor.hpp"
#include "../algorithms/graph_compressor.hpp"
#include "../algorithms/tiny_components.hpp"
#include "../algorithms/crc32_processor.hpp"
#include "../data_structures/compressed_edge_container.hpp"
#include "../data_structures/deallocating_vector.hpp"
@ -94,6 +94,8 @@ int Prepare::Run()
SimpleLogger().Write() << "building r-tree ...";
TIMER_START(rtree);
FindComponents(max_edge_id, edge_based_edge_list, *node_based_edge_list);
BuildRTree(*node_based_edge_list, *internal_to_external_node_map);
TIMER_STOP(rtree);
@ -131,6 +133,58 @@ int Prepare::Run()
return 0;
}
void Prepare::FindComponents(unsigned max_edge_id, const DeallocatingVector<EdgeBasedEdge>& input_edge_list,
std::vector<EdgeBasedNode>& input_nodes) const
{
struct UncontractedEdgeData { };
using InputEdge = StaticGraph<UncontractedEdgeData>::InputEdge;
using UncontractedGraph = StaticGraph<UncontractedEdgeData>;
std::vector<InputEdge> edges;
edges.reserve(input_edge_list.size() * 2);
for (const auto& edge : input_edge_list)
{
BOOST_ASSERT_MSG(static_cast<unsigned int>(std::max(edge.weight, 1)) > 0,
"edge distance < 1");
if (edge.forward)
{
edges.emplace_back(edge.source, edge.target);
}
if (edge.backward)
{
edges.emplace_back(edge.target, edge.source);
}
}
// connect forward and backward nodes of each edge
for (const auto& node : input_nodes)
{
if (node.reverse_edge_based_node_id != SPECIAL_NODEID)
{
edges.emplace_back(node.forward_edge_based_node_id, node.reverse_edge_based_node_id);
edges.emplace_back(node.reverse_edge_based_node_id, node.forward_edge_based_node_id);
}
}
tbb::parallel_sort(edges.begin(), edges.end());
auto uncontractor_graph = std::make_shared<UncontractedGraph>(max_edge_id+1, edges);
TarjanSCC<UncontractedGraph> component_search(std::const_pointer_cast<const UncontractedGraph>(uncontractor_graph));
component_search.run();
for (auto& node : input_nodes)
{
auto forward_component = component_search.get_component_id(node.forward_edge_based_node_id);
BOOST_ASSERT(node.reverse_edge_based_node_id == SPECIAL_EDGEID ||
forward_component == component_search.get_component_id(node.reverse_edge_based_node_id));
const unsigned component_size = component_search.get_component_size(forward_component);
const bool is_tiny_component = component_size < 1000;
node.component_id = is_tiny_component ? (1 + forward_component) : 0;
}
}
std::size_t Prepare::WriteContractedGraph(unsigned max_node_id,
std::unique_ptr<std::vector<EdgeBasedNode>> node_based_edge_list,
std::unique_ptr<DeallocatingVector<QueryEdge>> contracted_edge_list)

View File

@ -78,6 +78,7 @@ class Prepare
std::vector<EdgeBasedNode> &node_based_edge_list,
DeallocatingVector<EdgeBasedEdge> &edge_based_edge_list);
void WriteNodeMapping(std::unique_ptr<std::vector<QueryNode>> internal_to_external_node_map);
void FindComponents(unsigned max_edge_id, const DeallocatingVector<EdgeBasedEdge>& edges, std::vector<EdgeBasedNode>& nodes) const;
void BuildRTree(const std::vector<EdgeBasedNode> &node_based_edge_list,
const std::vector<QueryNode> &internal_to_external_node_map);
private:

View File

@ -45,6 +45,7 @@ using EdgeWeight = int;
static const NodeID SPECIAL_NODEID = std::numeric_limits<unsigned>::max();
static const EdgeID SPECIAL_EDGEID = std::numeric_limits<unsigned>::max();
static const unsigned INVALID_NAMEID = std::numeric_limits<unsigned>::max();
static const unsigned INVALID_COMPONENTID = std::numeric_limits<unsigned>::max();
static const EdgeWeight INVALID_EDGE_WEIGHT = std::numeric_limits<int>::max();
#endif /* TYPEDEFS_H */