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<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)
|
||||
{
|
||||
|
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -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;
|
||||
|
@ -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)
|
||||
|
@ -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:
|
||||
|
@ -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 */
|
||||
|
Loading…
Reference in New Issue
Block a user