use restriction map in tiny components

This commit is contained in:
Dennis Luxen 2014-12-23 11:47:19 +01:00
parent df0c1106ce
commit 47f65ccba6
3 changed files with 67 additions and 121 deletions

View File

@ -122,38 +122,38 @@ template <typename GraphT> class BFSComponentExplorer
const NodeID u = current_queue_item.second; // parent const NodeID u = current_queue_item.second; // parent
// increment size counter of current component // increment size counter of current component
++current_component_size; ++current_component_size;
const bool is_barrier_node = (m_barrier_nodes.find(v) != m_barrier_nodes.end()); if (m_barrier_nodes.find(v) != m_barrier_nodes.end())
if (!is_barrier_node)
{ {
const NodeID to_node_of_only_restriction = continue;
m_restriction_map.CheckForEmanatingIsOnlyTurn(u, v); }
const NodeID to_node_of_only_restriction =
m_restriction_map.CheckForEmanatingIsOnlyTurn(u, v);
for (auto e2 : m_graph.GetAdjacentEdgeRange(v)) for (auto e2 : m_graph.GetAdjacentEdgeRange(v))
{
const NodeID w = m_graph.GetTarget(e2);
if (to_node_of_only_restriction != std::numeric_limits<unsigned>::max() &&
w != to_node_of_only_restriction)
{ {
const NodeID w = m_graph.GetTarget(e2); // At an only_-restriction but not at the right turn
continue;
}
if (to_node_of_only_restriction != std::numeric_limits<unsigned>::max() && if (u != w)
w != to_node_of_only_restriction) {
// only add an edge if turn is not a U-turn except
// when it is at the end of a dead-end street.
if (!m_restriction_map.CheckIfTurnIsRestricted(u, v, w))
{ {
// At an only_-restriction but not at the right turn // only add an edge if turn is not prohibited
continue; if (std::numeric_limits<unsigned>::max() == m_component_index_list[w])
}
if (u != w)
{
// only add an edge if turn is not a U-turn except
// when it is at the end of a dead-end street.
if (!m_restriction_map.CheckIfTurnIsRestricted(u, v, w))
{ {
// only add an edge if turn is not prohibited // insert next (node, parent) only if w has
if (std::numeric_limits<unsigned>::max() == m_component_index_list[w]) // not yet been explored
{ // mark node as read
// insert next (node, parent) only if w has m_component_index_list[w] = current_component;
// not yet been explored bfs_queue.emplace(w, v);
// mark node as read
m_component_index_list[w] = current_component;
bfs_queue.emplace(w, v);
}
} }
} }
} }

View File

@ -34,6 +34,7 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include "../data_structures/query_node.hpp" #include "../data_structures/query_node.hpp"
#include "../data_structures/percent.hpp" #include "../data_structures/percent.hpp"
#include "../data_structures/restriction.hpp" #include "../data_structures/restriction.hpp"
#include "../data_structures/restriction_map.hpp"
#include "../data_structures/turn_instructions.hpp" #include "../data_structures/turn_instructions.hpp"
#include "../Util/integer_range.hpp" #include "../Util/integer_range.hpp"
@ -75,64 +76,23 @@ class TarjanSCC
bool on_stack; bool on_stack;
}; };
using RestrictionSource = std::pair<NodeID, NodeID>;
using RestrictionTarget = std::pair<NodeID, bool>;
using EmanatingRestrictionsVector = std::vector<RestrictionTarget>;
using RestrictionMap = std::unordered_map<RestrictionSource, unsigned>;
std::vector<EmanatingRestrictionsVector> m_restriction_bucket_list;
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_node_based_graph; std::shared_ptr<GraphT> m_node_based_graph;
std::unordered_set<NodeID> barrier_node_list; std::unordered_set<NodeID> barrier_node_set;
unsigned size_one_counter;
RestrictionMap m_restriction_map; RestrictionMap m_restriction_map;
unsigned size_one_counter;
public: public:
TarjanSCC(std::shared_ptr<GraphT> graph, TarjanSCC(std::shared_ptr<GraphT> graph,
std::vector<NodeID> &bn, const RestrictionMap &restrictions,
std::vector<TurnRestriction> &irs) const std::vector<NodeID> &barrier_node_list)
: components_index(graph->GetNumberOfNodes(), SPECIAL_NODEID), : components_index(graph->GetNumberOfNodes(), SPECIAL_NODEID),
m_node_based_graph(graph), m_node_based_graph(graph), m_restriction_map(restrictions),
size_one_counter(0) size_one_counter(0)
{ {
barrier_node_set.insert(std::begin(barrier_node_list), std::end(barrier_node_list));
TIMER_START(SCC_LOAD); BOOST_ASSERT(m_node_based_graph->GetNumberOfNodes() > 0);
for (const TurnRestriction &restriction : irs)
{
std::pair<NodeID, NodeID> restriction_source = {restriction.from.node,
restriction.via.node};
unsigned index = 0;
const auto restriction_iterator = m_restriction_map.find(restriction_source);
if (restriction_iterator == m_restriction_map.end())
{
index = m_restriction_bucket_list.size();
m_restriction_bucket_list.resize(index + 1);
m_restriction_map.emplace(restriction_source, index);
}
else
{
index = restriction_iterator->second;
// Map already contains an is_only_*-restriction
if (m_restriction_bucket_list.at(index).begin()->second)
{
continue;
}
else if (restriction.flags.is_only)
{
// We are going to insert an is_only_*-restriction. There can be only one.
m_restriction_bucket_list.at(index).clear();
}
}
m_restriction_bucket_list.at(index)
.emplace_back(restriction.to.node, restriction.flags.is_only);
}
barrier_node_list.insert(bn.begin(), bn.end());
TIMER_STOP(SCC_LOAD);
SimpleLogger().Write() << "Loading data into SCC took " << TIMER_MSEC(SCC_LOAD)/1000. << "s";
} }
void Run() void Run()
@ -158,8 +118,10 @@ class TarjanSCC
while (!recursion_stack.empty()) while (!recursion_stack.empty())
{ {
TarjanStackFrame currentFrame = recursion_stack.top(); TarjanStackFrame currentFrame = recursion_stack.top();
const NodeID u = currentFrame.parent;
const NodeID v = currentFrame.v; const NodeID v = currentFrame.v;
recursion_stack.pop(); recursion_stack.pop();
const bool before_recursion = processing_node_before_recursion[v]; const bool before_recursion = processing_node_before_recursion[v];
if (before_recursion && tarjan_node_list[v].index != UINT_MAX) if (before_recursion && tarjan_node_list[v].index != UINT_MAX)
@ -181,9 +143,29 @@ class TarjanSCC
++index; ++index;
// Traverse outgoing edges // Traverse outgoing edges
if (barrier_node_set.find(v) != barrier_node_set.end())
{
continue;
}
const NodeID to_node_of_only_restriction =
m_restriction_map.CheckForEmanatingIsOnlyTurn(u, v);
for (const auto current_edge : m_node_based_graph->GetAdjacentEdgeRange(v)) for (const auto current_edge : m_node_based_graph->GetAdjacentEdgeRange(v))
{ {
const auto vprime = m_node_based_graph->GetTarget(current_edge); const auto vprime = m_node_based_graph->GetTarget(current_edge);
if (to_node_of_only_restriction != std::numeric_limits<unsigned>::max() &&
vprime == to_node_of_only_restriction)
{
// At an only_-restriction but not at the right turn
// continue;
}
if (m_restriction_map.CheckIfTurnIsRestricted(u, v, vprime))
{
// continue;
}
if (SPECIAL_NODEID == tarjan_node_list[vprime].index) if (SPECIAL_NODEID == tarjan_node_list[vprime].index)
{ {
recursion_stack.emplace(TarjanStackFrame(vprime, v)); recursion_stack.emplace(TarjanStackFrame(vprime, v));
@ -253,44 +235,6 @@ class TarjanSCC
{ {
return component_size_vector[components_index[node]]; return component_size_vector[components_index[node]];
} }
private:
unsigned CheckForEmanatingIsOnlyTurn(const NodeID u, const NodeID v) const
{
std::pair<NodeID, NodeID> restriction_source = {u, v};
const auto restriction_iterator = m_restriction_map.find(restriction_source);
if (restriction_iterator != m_restriction_map.end())
{
const unsigned index = restriction_iterator->second;
for (const RestrictionSource &restriction_target : m_restriction_bucket_list.at(index))
{
if (restriction_target.second)
{
return restriction_target.first;
}
}
}
return SPECIAL_NODEID;
}
bool CheckIfTurnIsRestricted(const NodeID u, const NodeID v, const NodeID w) const
{
// only add an edge if turn is not a U-turn except it is the end of dead-end street.
std::pair<NodeID, NodeID> restriction_source = {u, v};
const auto restriction_iterator = m_restriction_map.find(restriction_source);
if (restriction_iterator != m_restriction_map.end())
{
const unsigned index = restriction_iterator->second;
for (const RestrictionTarget &restriction_target : m_restriction_bucket_list.at(index))
{
if (w == restriction_target.first)
{
return true;
}
}
}
return false;
}
}; };
#endif /* TINY_COMPONENTS_HPP */ #endif /* TINY_COMPONENTS_HPP */

View File

@ -52,7 +52,7 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include <vector> #include <vector>
std::vector<QueryNode> coordinate_list; std::vector<QueryNode> coordinate_list;
std::vector<TurnRestriction> restrictions_vector; std::vector<TurnRestriction> restriction_list;
std::vector<NodeID> bollard_node_list; std::vector<NodeID> bollard_node_list;
std::vector<NodeID> traffic_lights_list; std::vector<NodeID> traffic_lights_list;
@ -107,12 +107,12 @@ int main(int argc, char *argv[])
} }
uint32_t usable_restrictions = 0; uint32_t usable_restrictions = 0;
restriction_ifstream.read((char *)&usable_restrictions, sizeof(uint32_t)); restriction_ifstream.read((char *)&usable_restrictions, sizeof(uint32_t));
restrictions_vector.resize(usable_restrictions); restriction_list.resize(usable_restrictions);
// load restrictions // load restrictions
if (usable_restrictions > 0) if (usable_restrictions > 0)
{ {
restriction_ifstream.read((char *)&(restrictions_vector[0]), restriction_ifstream.read((char *)&(restriction_list[0]),
usable_restrictions * sizeof(TurnRestriction)); usable_restrictions * sizeof(TurnRestriction));
} }
restriction_ifstream.close(); restriction_ifstream.close();
@ -130,14 +130,14 @@ int main(int argc, char *argv[])
bollard_node_list, bollard_node_list,
traffic_lights_list, traffic_lights_list,
&coordinate_list, &coordinate_list,
restrictions_vector); restriction_list);
input_stream.close(); input_stream.close();
BOOST_ASSERT_MSG(restrictions_vector.size() == usable_restrictions, BOOST_ASSERT_MSG(restriction_list.size() == usable_restrictions,
"size of restrictions_vector changed"); "size of restriction_list changed");
SimpleLogger().Write() << restrictions_vector.size() << " restrictions, " SimpleLogger().Write() << restriction_list.size() << " restrictions, "
<< bollard_node_list.size() << " bollard nodes, " << bollard_node_list.size() << " bollard nodes, "
<< traffic_lights_list.size() << " traffic lights"; << traffic_lights_list.size() << " traffic lights";
@ -179,9 +179,11 @@ int main(int argc, char *argv[])
edge_list.shrink_to_fit(); edge_list.shrink_to_fit();
SimpleLogger().Write() << "Starting SCC graph traversal"; SimpleLogger().Write() << "Starting SCC graph traversal";
RestrictionMap restriction_map(restriction_list);
auto tarjan = osrm::make_unique<TarjanSCC<TarjanDynamicGraph>>(graph, auto tarjan = osrm::make_unique<TarjanSCC<TarjanDynamicGraph>>(graph,
bollard_node_list, restriction_map,
restrictions_vector); bollard_node_list);
tarjan->Run(); tarjan->Run();
// output // output