Find components on edge-expanded graph
This commit is contained in:
parent
c2f0e4f683
commit
c80c2233c5
@ -72,11 +72,11 @@ template <typename GraphT> class TarjanSCC
|
|||||||
|
|
||||||
std::vector<unsigned> components_index;
|
std::vector<unsigned> components_index;
|
||||||
std::vector<NodeID> component_size_vector;
|
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;
|
std::size_t size_one_counter;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
TarjanSCC(std::shared_ptr<GraphT> graph)
|
TarjanSCC(std::shared_ptr<const GraphT> graph)
|
||||||
: components_index(graph->GetNumberOfNodes(), SPECIAL_NODEID), m_graph(graph),
|
: components_index(graph->GetNumberOfNodes(), SPECIAL_NODEID), m_graph(graph),
|
||||||
size_one_counter(0)
|
size_one_counter(0)
|
||||||
{
|
{
|
||||||
|
@ -26,7 +26,6 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
#include "edge_based_graph_factory.hpp"
|
#include "edge_based_graph_factory.hpp"
|
||||||
#include "../algorithms/tiny_components.hpp"
|
|
||||||
#include "../data_structures/percent.hpp"
|
#include "../data_structures/percent.hpp"
|
||||||
#include "../util/compute_angle.hpp"
|
#include "../util/compute_angle.hpp"
|
||||||
#include "../util/integer_range.hpp"
|
#include "../util/integer_range.hpp"
|
||||||
@ -83,8 +82,7 @@ unsigned EdgeBasedGraphFactory::GetHighestEdgeID()
|
|||||||
}
|
}
|
||||||
|
|
||||||
void EdgeBasedGraphFactory::InsertEdgeBasedNode(const NodeID node_u,
|
void EdgeBasedGraphFactory::InsertEdgeBasedNode(const NodeID node_u,
|
||||||
const NodeID node_v,
|
const NodeID node_v)
|
||||||
const unsigned component_id)
|
|
||||||
{
|
{
|
||||||
// merge edges together into one EdgeBasedNode
|
// merge edges together into one EdgeBasedNode
|
||||||
BOOST_ASSERT(node_u != SPECIAL_NODEID);
|
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,
|
forward_data.name_id, forward_geometry[i].second,
|
||||||
reverse_geometry[geometry_size - 1 - i].second, forward_dist_prefix_sum[i],
|
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),
|
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;
|
current_edge_source_coordinate_id = current_edge_target_coordinate_id;
|
||||||
|
|
||||||
BOOST_ASSERT(m_edge_based_node_list.back().IsCompressed());
|
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(
|
m_edge_based_node_list.emplace_back(
|
||||||
forward_data.edge_id, reverse_data.edge_id, node_u, node_v,
|
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,
|
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());
|
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.
|
/// Creates the nodes in the edge expanded graph from edges in the node-based graph.
|
||||||
void EdgeBasedGraphFactory::GenerateEdgeExpandedNodes()
|
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());
|
Percent progress(m_node_based_graph->GetNumberOfNodes());
|
||||||
|
|
||||||
// loop over all edges and generate new set of nodes
|
// loop over all edges and generate new set of nodes
|
||||||
@ -318,34 +301,14 @@ void EdgeBasedGraphFactory::GenerateEdgeExpandedNodes()
|
|||||||
|
|
||||||
BOOST_ASSERT(node_u < node_v);
|
BOOST_ASSERT(node_u < node_v);
|
||||||
|
|
||||||
// Note: edges that end on barrier nodes or on a turn restriction
|
// if we found a non-forward edge reverse and try again
|
||||||
// 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 (edge_data.edge_id == SPECIAL_NODEID)
|
if (edge_data.edge_id == SPECIAL_NODEID)
|
||||||
{
|
{
|
||||||
InsertEdgeBasedNode(node_v, node_u,
|
InsertEdgeBasedNode(node_v, node_u);
|
||||||
(component_is_tiny ? id_of_smaller_component + 1 : 0));
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
InsertEdgeBasedNode(node_u, node_v,
|
InsertEdgeBasedNode(node_u, node_v);
|
||||||
(component_is_tiny ? id_of_smaller_component + 1 : 0));
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -103,7 +103,7 @@ class EdgeBasedGraphFactory
|
|||||||
void GenerateEdgeExpandedEdges(const std::string &original_edge_data_filename,
|
void GenerateEdgeExpandedEdges(const std::string &original_edge_data_filename,
|
||||||
lua_State *lua_state);
|
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,
|
void FlushVectorToStream(std::ofstream &edge_data_file,
|
||||||
std::vector<OriginalEdgeData> &original_edge_data_vector) const;
|
std::vector<OriginalEdgeData> &original_edge_data_vector) const;
|
||||||
|
@ -29,7 +29,7 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|||||||
|
|
||||||
#include "contractor.hpp"
|
#include "contractor.hpp"
|
||||||
#include "../algorithms/graph_compressor.hpp"
|
#include "../algorithms/graph_compressor.hpp"
|
||||||
|
#include "../algorithms/tiny_components.hpp"
|
||||||
#include "../algorithms/crc32_processor.hpp"
|
#include "../algorithms/crc32_processor.hpp"
|
||||||
#include "../data_structures/compressed_edge_container.hpp"
|
#include "../data_structures/compressed_edge_container.hpp"
|
||||||
#include "../data_structures/deallocating_vector.hpp"
|
#include "../data_structures/deallocating_vector.hpp"
|
||||||
@ -94,6 +94,8 @@ int Prepare::Run()
|
|||||||
SimpleLogger().Write() << "building r-tree ...";
|
SimpleLogger().Write() << "building r-tree ...";
|
||||||
TIMER_START(rtree);
|
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);
|
BuildRTree(*node_based_edge_list, *internal_to_external_node_map);
|
||||||
|
|
||||||
TIMER_STOP(rtree);
|
TIMER_STOP(rtree);
|
||||||
@ -131,6 +133,58 @@ int Prepare::Run()
|
|||||||
return 0;
|
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::size_t Prepare::WriteContractedGraph(unsigned max_node_id,
|
||||||
std::unique_ptr<std::vector<EdgeBasedNode>> node_based_edge_list,
|
std::unique_ptr<std::vector<EdgeBasedNode>> node_based_edge_list,
|
||||||
std::unique_ptr<DeallocatingVector<QueryEdge>> contracted_edge_list)
|
std::unique_ptr<DeallocatingVector<QueryEdge>> contracted_edge_list)
|
||||||
|
@ -78,6 +78,7 @@ class Prepare
|
|||||||
std::vector<EdgeBasedNode> &node_based_edge_list,
|
std::vector<EdgeBasedNode> &node_based_edge_list,
|
||||||
DeallocatingVector<EdgeBasedEdge> &edge_based_edge_list);
|
DeallocatingVector<EdgeBasedEdge> &edge_based_edge_list);
|
||||||
void WriteNodeMapping(std::unique_ptr<std::vector<QueryNode>> internal_to_external_node_map);
|
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,
|
void BuildRTree(const std::vector<EdgeBasedNode> &node_based_edge_list,
|
||||||
const std::vector<QueryNode> &internal_to_external_node_map);
|
const std::vector<QueryNode> &internal_to_external_node_map);
|
||||||
private:
|
private:
|
||||||
|
@ -45,6 +45,7 @@ using EdgeWeight = int;
|
|||||||
static const NodeID SPECIAL_NODEID = std::numeric_limits<unsigned>::max();
|
static const NodeID SPECIAL_NODEID = std::numeric_limits<unsigned>::max();
|
||||||
static const EdgeID SPECIAL_EDGEID = 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_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();
|
static const EdgeWeight INVALID_EDGE_WEIGHT = std::numeric_limits<int>::max();
|
||||||
|
|
||||||
#endif /* TYPEDEFS_H */
|
#endif /* TYPEDEFS_H */
|
||||||
|
Loading…
Reference in New Issue
Block a user