mirror of
https://codeberg.org/comaps/comaps
synced 2025-12-20 21:33:59 +00:00
[routing] Faster IndexGraph
Signed-off-by: x7z4w <x7z4w@noreply.codeberg.org>
This commit is contained in:
@@ -11,6 +11,7 @@
|
|||||||
#include "base/assert.hpp"
|
#include "base/assert.hpp"
|
||||||
#include "base/buffer_vector.hpp"
|
#include "base/buffer_vector.hpp"
|
||||||
|
|
||||||
|
#include <execution>
|
||||||
#include <string>
|
#include <string>
|
||||||
#include <unordered_map>
|
#include <unordered_map>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
@@ -117,27 +118,31 @@ public:
|
|||||||
template <class FnT>
|
template <class FnT>
|
||||||
void ForEachEnter(FnT && fn) const
|
void ForEachEnter(FnT && fn) const
|
||||||
{
|
{
|
||||||
for (auto const & [key, transit] : m_transitions)
|
std::for_each(std::execution::par_unseq, m_transitions.begin(), m_transitions.end(), [&](auto const & pair)
|
||||||
{
|
{
|
||||||
|
auto const & [key, transit] = pair;
|
||||||
|
|
||||||
if (transit.m_forwardIsEnter)
|
if (transit.m_forwardIsEnter)
|
||||||
fn(transit.m_enterIdx, Segment(m_mwmId, key.m_featureId, key.m_segmentIdx, true));
|
fn(transit.m_enterIdx, Segment(m_mwmId, key.m_featureId, key.m_segmentIdx, true));
|
||||||
|
|
||||||
if (!transit.m_oneWay && !transit.m_forwardIsEnter)
|
if (!transit.m_oneWay && !transit.m_forwardIsEnter)
|
||||||
fn(transit.m_enterIdx, Segment(m_mwmId, key.m_featureId, key.m_segmentIdx, false));
|
fn(transit.m_enterIdx, Segment(m_mwmId, key.m_featureId, key.m_segmentIdx, false));
|
||||||
}
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
template <class FnT>
|
template <class FnT>
|
||||||
void ForEachExit(FnT && fn) const
|
void ForEachExit(FnT && fn) const
|
||||||
{
|
{
|
||||||
for (auto const & [key, transit] : m_transitions)
|
std::for_each(std::execution::par_unseq, m_transitions.begin(), m_transitions.end(), [&](auto const & pair)
|
||||||
{
|
{
|
||||||
|
auto const & [key, transit] = pair;
|
||||||
|
|
||||||
if (!transit.m_forwardIsEnter)
|
if (!transit.m_forwardIsEnter)
|
||||||
fn(transit.m_exitIdx, Segment(m_mwmId, key.m_featureId, key.m_segmentIdx, true));
|
fn(transit.m_exitIdx, Segment(m_mwmId, key.m_featureId, key.m_segmentIdx, true));
|
||||||
|
|
||||||
if (!transit.m_oneWay && transit.m_forwardIsEnter)
|
if (!transit.m_oneWay && transit.m_forwardIsEnter)
|
||||||
fn(transit.m_exitIdx, Segment(m_mwmId, key.m_featureId, key.m_segmentIdx, false));
|
fn(transit.m_exitIdx, Segment(m_mwmId, key.m_featureId, key.m_segmentIdx, false));
|
||||||
}
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
void GetOutgoingEdgeList(Segment const & segment, EdgeListT & edges) const
|
void GetOutgoingEdgeList(Segment const & segment, EdgeListT & edges) const
|
||||||
|
|||||||
@@ -4,16 +4,14 @@
|
|||||||
#include "routing/routing_options.hpp"
|
#include "routing/routing_options.hpp"
|
||||||
#include "routing/world_graph.hpp"
|
#include "routing/world_graph.hpp"
|
||||||
|
|
||||||
#include "platform/settings.hpp"
|
|
||||||
|
|
||||||
#include "base/assert.hpp"
|
#include "base/assert.hpp"
|
||||||
#include "base/checked_cast.hpp"
|
#include "base/checked_cast.hpp"
|
||||||
#include "base/exception.hpp"
|
|
||||||
#include "base/timer.hpp"
|
#include "base/timer.hpp"
|
||||||
|
|
||||||
#include "geometry/distance_on_sphere.hpp"
|
#include "geometry/distance_on_sphere.hpp"
|
||||||
|
|
||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
|
#include <execution>
|
||||||
#include <limits>
|
#include <limits>
|
||||||
#include <utility>
|
#include <utility>
|
||||||
|
|
||||||
@@ -321,7 +319,9 @@ void IndexGraph::ReconstructJointSegment(astar::VertexData<JointSegment, RouteWe
|
|||||||
|
|
||||||
auto const & weightTimeToParent = parentVertexData.m_realDistance;
|
auto const & weightTimeToParent = parentVertexData.m_realDistance;
|
||||||
auto const & parentJoint = parentVertexData.m_vertex;
|
auto const & parentJoint = parentVertexData.m_vertex;
|
||||||
for (size_t i = 0; i < firstChildren.size(); ++i)
|
|
||||||
|
auto const range = std::ranges::views::iota(0uz, firstChildren.size());
|
||||||
|
std::for_each(std::execution::par_unseq, range.begin(), range.end(), [&, this](auto const i)
|
||||||
{
|
{
|
||||||
auto const & firstChild = firstChildren[i];
|
auto const & firstChild = firstChildren[i];
|
||||||
auto const lastPointId = lastPointIds[i];
|
auto const lastPointId = lastPointIds[i];
|
||||||
@@ -335,22 +335,21 @@ void IndexGraph::ReconstructJointSegment(astar::VertexData<JointSegment, RouteWe
|
|||||||
{ return currentPointId < lastPointId ? pointId + 1 : pointId - 1; };
|
{ return currentPointId < lastPointId ? pointId + 1 : pointId - 1; };
|
||||||
|
|
||||||
if (IsAccessNoForSure(firstChild.GetFeatureId(), weightTimeToParent, true /* useAccessConditional */))
|
if (IsAccessNoForSure(firstChild.GetFeatureId(), weightTimeToParent, true /* useAccessConditional */))
|
||||||
continue;
|
return;
|
||||||
|
|
||||||
if (IsAccessNoForSure(parent.GetRoadPoint(isOutgoing), weightTimeToParent, true /* useAccessConditional */))
|
if (IsAccessNoForSure(parent.GetRoadPoint(isOutgoing), weightTimeToParent, true /* useAccessConditional */))
|
||||||
continue;
|
return;
|
||||||
|
|
||||||
if (IsUTurn(parent, firstChild) && IsUTurnAndRestricted(parent, firstChild, isOutgoing))
|
if (IsUTurn(parent, firstChild) && IsUTurnAndRestricted(parent, firstChild, isOutgoing))
|
||||||
continue;
|
return;
|
||||||
|
|
||||||
if (IsRestricted(parentJoint, parent.GetFeatureId(), firstChild.GetFeatureId(), isOutgoing, parents))
|
if (IsRestricted(parentJoint, parent.GetFeatureId(), firstChild.GetFeatureId(), isOutgoing, parents))
|
||||||
continue;
|
return;
|
||||||
|
|
||||||
RouteWeight summaryWeight;
|
RouteWeight summaryWeight;
|
||||||
// Check current JointSegment for bad road access between segments.
|
// Check current JointSegment for bad road access between segments.
|
||||||
RoadPoint rp = firstChild.GetRoadPoint(isOutgoing);
|
RoadPoint rp = firstChild.GetRoadPoint(isOutgoing);
|
||||||
uint32_t start = currentPointId;
|
uint32_t start = currentPointId;
|
||||||
bool noRoadAccess = false;
|
|
||||||
do
|
do
|
||||||
{
|
{
|
||||||
// This is optimization: we calculate accesses of road points before calculating weight of
|
// This is optimization: we calculate accesses of road points before calculating weight of
|
||||||
@@ -360,19 +359,13 @@ void IndexGraph::ReconstructJointSegment(astar::VertexData<JointSegment, RouteWe
|
|||||||
// until this |rp|. But we assume that segments have small length and inaccuracy will not
|
// until this |rp|. But we assume that segments have small length and inaccuracy will not
|
||||||
// affect user.
|
// affect user.
|
||||||
if (IsAccessNoForSure(rp, weightTimeToParent, true /* useAccessConditional */))
|
if (IsAccessNoForSure(rp, weightTimeToParent, true /* useAccessConditional */))
|
||||||
{
|
return;
|
||||||
noRoadAccess = true;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
start = increment(start);
|
start = increment(start);
|
||||||
rp.SetPointId(start);
|
rp.SetPointId(start);
|
||||||
}
|
}
|
||||||
while (start != lastPointId);
|
while (start != lastPointId);
|
||||||
|
|
||||||
if (noRoadAccess)
|
|
||||||
continue;
|
|
||||||
|
|
||||||
bool forward = currentPointId < lastPointId;
|
bool forward = currentPointId < lastPointId;
|
||||||
Segment current = firstChild;
|
Segment current = firstChild;
|
||||||
Segment prev = parent;
|
Segment prev = parent;
|
||||||
@@ -396,7 +389,7 @@ void IndexGraph::ReconstructJointSegment(astar::VertexData<JointSegment, RouteWe
|
|||||||
|
|
||||||
jointEdges.emplace_back(isOutgoing ? JointSegment(firstChild, prev) : JointSegment(prev, firstChild),
|
jointEdges.emplace_back(isOutgoing ? JointSegment(firstChild, prev) : JointSegment(prev, firstChild),
|
||||||
summaryWeight);
|
summaryWeight);
|
||||||
}
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
void IndexGraph::GetNeighboringEdge(astar::VertexData<Segment, RouteWeight> const & fromVertexData, Segment const & to,
|
void IndexGraph::GetNeighboringEdge(astar::VertexData<Segment, RouteWeight> const & fromVertexData, Segment const & to,
|
||||||
|
|||||||
@@ -18,8 +18,6 @@
|
|||||||
|
|
||||||
#include "indexer/feature_meta.hpp"
|
#include "indexer/feature_meta.hpp"
|
||||||
|
|
||||||
#include "geometry/point2d.hpp"
|
|
||||||
|
|
||||||
#include <memory>
|
#include <memory>
|
||||||
#include <optional>
|
#include <optional>
|
||||||
#include <unordered_map>
|
#include <unordered_map>
|
||||||
|
|||||||
@@ -13,6 +13,7 @@
|
|||||||
#include "3party/skarupke/bytell_hash_map.hpp" // needed despite of IDE warning
|
#include "3party/skarupke/bytell_hash_map.hpp" // needed despite of IDE warning
|
||||||
|
|
||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
|
#include <execution>
|
||||||
#include <map>
|
#include <map>
|
||||||
#include <optional>
|
#include <optional>
|
||||||
#include <queue>
|
#include <queue>
|
||||||
@@ -474,7 +475,8 @@ void IndexGraphStarterJoints<Graph>::GetEdgeList(astar::VertexData<Vertex, Weigh
|
|||||||
CHECK(it != m_savedWeight.cend(), ("Can not find weight for:", vertex));
|
CHECK(it != m_savedWeight.cend(), ("Can not find weight for:", vertex));
|
||||||
|
|
||||||
Weight const weight = it->second;
|
Weight const weight = it->second;
|
||||||
for (size_t i = 0; i < edges.size(); ++i)
|
auto const range = std::ranges::views::iota(0uz, edges.size());
|
||||||
|
std::for_each(std::execution::par_unseq, range.begin(), range.end(), [&, this](auto const i)
|
||||||
{
|
{
|
||||||
// Saving weight of current edges for returning in the next iterations.
|
// Saving weight of current edges for returning in the next iterations.
|
||||||
auto & w = edges[i].GetWeight();
|
auto & w = edges[i].GetWeight();
|
||||||
@@ -490,7 +492,7 @@ void IndexGraphStarterJoints<Graph>::GetEdgeList(astar::VertexData<Vertex, Weigh
|
|||||||
// |parentWeights[]|. So the weight of an ith edge is a cached "weight of parent JointSegment" +
|
// |parentWeights[]|. So the weight of an ith edge is a cached "weight of parent JointSegment" +
|
||||||
// "parentWeight[i]".
|
// "parentWeight[i]".
|
||||||
w = weight + parentWeights[i];
|
w = weight + parentWeights[i];
|
||||||
}
|
});
|
||||||
|
|
||||||
// Delete useless weight of parent JointSegment.
|
// Delete useless weight of parent JointSegment.
|
||||||
m_savedWeight.erase(vertex);
|
m_savedWeight.erase(vertex);
|
||||||
@@ -498,8 +500,9 @@ void IndexGraphStarterJoints<Graph>::GetEdgeList(astar::VertexData<Vertex, Weigh
|
|||||||
else
|
else
|
||||||
{
|
{
|
||||||
// This needs for correct weights calculation of FakeJointSegments during forward A* search.
|
// This needs for correct weights calculation of FakeJointSegments during forward A* search.
|
||||||
for (size_t i = firstFakeId; i < edges.size(); ++i)
|
auto const range = std::ranges::views::iota(firstFakeId, edges.size());
|
||||||
edges[i].GetWeight() += parentWeights[i];
|
std::for_each(std::execution::par_unseq, range.begin(), range.end(),
|
||||||
|
[&edges, &parentWeights](auto const i) { edges[i].GetWeight() += parentWeights[i]; });
|
||||||
}
|
}
|
||||||
|
|
||||||
auto const vertexMwmId = vertex.GetMwmId();
|
auto const vertexMwmId = vertex.GetMwmId();
|
||||||
@@ -510,12 +513,12 @@ void IndexGraphStarterJoints<Graph>::GetEdgeList(astar::VertexData<Vertex, Weigh
|
|||||||
/// a weight of v1->v2 transition moving backward (v2 ingoing). This is impossible in current (m_savedWeight)
|
/// a weight of v1->v2 transition moving backward (v2 ingoing). This is impossible in current (m_savedWeight)
|
||||||
/// logic, so I moved Cross-MWM penalty into separate block here after _all_ weights calculations.
|
/// logic, so I moved Cross-MWM penalty into separate block here after _all_ weights calculations.
|
||||||
|
|
||||||
for (auto & e : edges)
|
std::for_each(std::execution::par_unseq, edges.begin(), edges.end(), [&, this](auto & e)
|
||||||
{
|
{
|
||||||
auto const targetMwmId = e.GetTarget().GetMwmId();
|
auto const targetMwmId = e.GetTarget().GetMwmId();
|
||||||
if (targetMwmId != kFakeNumMwmId && vertexMwmId != targetMwmId)
|
if (targetMwmId != kFakeNumMwmId && vertexMwmId != targetMwmId)
|
||||||
e.GetWeight() += m_graph.GetCrossBorderPenalty(vertexMwmId, targetMwmId);
|
e.GetWeight() += m_graph.GetCrossBorderPenalty(vertexMwmId, targetMwmId);
|
||||||
}
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user