osrm-backend/include/customizer/cell_customizer.hpp

240 lines
9.0 KiB
C++
Raw Permalink Normal View History

2017-02-20 08:20:22 -05:00
#ifndef OSRM_CELLS_CUSTOMIZER_HPP
#define OSRM_CELLS_CUSTOMIZER_HPP
#include "partitioner/cell_storage.hpp"
#include "partitioner/multi_level_partition.hpp"
2017-05-02 07:12:28 -04:00
#include "util/query_heap.hpp"
2017-02-20 08:20:22 -05:00
2017-04-04 07:38:48 -04:00
#include <tbb/enumerable_thread_specific.h>
#include <tbb/parallel_for.h>
2017-04-04 07:38:48 -04:00
2017-02-20 08:20:22 -05:00
#include <unordered_set>
namespace osrm::customizer
2017-02-20 08:20:22 -05:00
{
class CellCustomizer
{
2017-04-04 07:38:48 -04:00
private:
struct HeapData
{
bool from_clique;
2017-06-28 18:20:04 -04:00
EdgeDuration duration;
EdgeDistance distance;
2017-04-04 07:38:48 -04:00
};
2017-04-04 13:20:36 -04:00
public:
2017-04-05 06:23:53 -04:00
using Heap =
2024-07-11 15:06:03 -04:00
util::QueryHeap<NodeID, NodeID, EdgeWeight, HeapData, util::ArrayStorage<NodeID, int>>;
2017-04-04 07:38:48 -04:00
using HeapPtr = tbb::enumerable_thread_specific<Heap>;
2017-02-20 08:20:22 -05:00
CellCustomizer(const partitioner::MultiLevelPartition &partition) : partition(partition) {}
2017-02-20 08:20:22 -05:00
template <typename GraphT>
2017-07-28 05:49:49 -04:00
void Customize(const GraphT &graph,
Heap &heap,
const partitioner::CellStorage &cells,
2017-07-28 05:49:49 -04:00
const std::vector<bool> &allowed_nodes,
CellMetric &metric,
LevelID level,
2017-08-18 18:00:18 -04:00
CellID id) const
2017-02-20 08:20:22 -05:00
{
auto cell = cells.GetCell(metric, level, id);
2017-02-20 08:20:22 -05:00
auto destinations = cell.GetDestinationNodes();
// for each source do forward search
for (auto source : cell.GetSourceNodes())
{
2017-07-28 05:49:49 -04:00
if (!allowed_nodes[source])
{
continue;
}
std::unordered_set<NodeID> destinations_set;
for (const auto destination : destinations)
{
if (allowed_nodes[destination])
{
destinations_set.insert(destination);
}
}
2017-04-04 07:38:48 -04:00
heap.Clear();
heap.Insert(source, {0}, {false, {0}, {0}});
2017-02-20 08:20:22 -05:00
// explore search space
while (!heap.Empty() && !destinations_set.empty())
{
const NodeID node = heap.DeleteMin();
const EdgeWeight weight = heap.GetKey(node);
2017-06-28 18:20:04 -04:00
const EdgeDuration duration = heap.GetData(node).duration;
const EdgeDistance distance = heap.GetData(node).distance;
RelaxNode(graph,
cells,
allowed_nodes,
metric,
heap,
level,
node,
weight,
duration,
distance);
2017-02-20 08:20:22 -05:00
destinations_set.erase(node);
}
// fill a map of destination nodes to placeholder pointers
2017-06-28 18:20:04 -04:00
auto weights = cell.GetOutWeight(source);
auto durations = cell.GetOutDuration(source);
auto distances = cell.GetOutDistance(source);
2017-06-28 18:20:04 -04:00
for (auto &destination : destinations)
2017-02-20 08:20:22 -05:00
{
2017-06-28 18:20:04 -04:00
BOOST_ASSERT(!weights.empty());
BOOST_ASSERT(!durations.empty());
BOOST_ASSERT(!distances.empty());
2017-06-28 18:20:04 -04:00
const bool inserted = heap.WasInserted(destination);
weights.front() = inserted ? heap.GetKey(destination) : INVALID_EDGE_WEIGHT;
durations.front() =
inserted ? heap.GetData(destination).duration : MAXIMAL_EDGE_DURATION;
distances.front() =
inserted ? heap.GetData(destination).distance : INVALID_EDGE_DISTANCE;
2017-06-28 18:20:04 -04:00
weights.advance_begin(1);
durations.advance_begin(1);
distances.advance_begin(1);
2017-02-20 08:20:22 -05:00
}
2017-06-28 18:20:04 -04:00
BOOST_ASSERT(weights.empty());
BOOST_ASSERT(durations.empty());
BOOST_ASSERT(distances.empty());
2017-02-20 08:20:22 -05:00
}
}
2017-07-28 05:49:49 -04:00
template <typename GraphT>
void Customize(const GraphT &graph,
const partitioner::CellStorage &cells,
2017-07-28 05:49:49 -04:00
const std::vector<bool> &allowed_nodes,
2017-08-18 18:00:18 -04:00
CellMetric &metric) const
2017-02-20 08:20:22 -05:00
{
2024-07-11 15:40:00 -04:00
const auto number_of_nodes = graph.GetNumberOfNodes();
2024-07-12 14:13:40 -04:00
HeapPtr heaps([number_of_nodes] { return Heap{number_of_nodes}; });
2017-04-04 07:38:48 -04:00
2017-02-20 08:20:22 -05:00
for (std::size_t level = 1; level < partition.GetNumberOfLevels(); ++level)
{
tbb::parallel_for(tbb::blocked_range<std::size_t>(0, partition.GetNumberOfCells(level)),
[&](const tbb::blocked_range<std::size_t> &range)
{
2024-07-11 15:40:00 -04:00
auto &heap = heaps.local();
2017-02-20 08:20:22 -05:00
for (auto id = range.begin(), end = range.end(); id != end; ++id)
{
2017-07-28 05:49:49 -04:00
Customize(
graph, heap, cells, allowed_nodes, metric, level, id);
2017-02-20 08:20:22 -05:00
}
});
}
}
private:
template <typename GraphT>
2017-02-20 08:20:22 -05:00
void RelaxNode(const GraphT &graph,
const partitioner::CellStorage &cells,
2017-07-28 05:49:49 -04:00
const std::vector<bool> &allowed_nodes,
const CellMetric &metric,
2017-02-20 08:20:22 -05:00
Heap &heap,
LevelID level,
2017-02-20 08:20:22 -05:00
NodeID node,
2017-06-28 18:20:04 -04:00
EdgeWeight weight,
EdgeDuration duration,
EdgeDistance distance) const
2017-02-20 08:20:22 -05:00
{
auto first_level = level == 1;
2017-04-04 07:04:30 -04:00
BOOST_ASSERT(heap.WasInserted(node));
2017-02-20 08:20:22 -05:00
if (!first_level)
{
2017-04-04 07:04:30 -04:00
// if we reaches this node from a clique arc we don't need to scan
// the clique arcs again because of the triangle inequality
//
// d(parent, node) + d(node, v) >= d(parent, v)
//
// And if there is a path (parent, node, v) there must also be a
// clique arc (parent, v) with d(parent, v).
if (!heap.GetData(node).from_clique)
2017-02-20 08:20:22 -05:00
{
2017-04-04 07:04:30 -04:00
// Relax sub-cell nodes
auto subcell_id = partition.GetCell(level - 1, node);
auto subcell = cells.GetCell(metric, level - 1, subcell_id);
2017-04-04 07:04:30 -04:00
auto subcell_destination = subcell.GetDestinationNodes().begin();
2017-06-28 18:20:04 -04:00
auto subcell_duration = subcell.GetOutDuration(node).begin();
auto subcell_distance = subcell.GetOutDistance(node).begin();
2017-04-04 07:04:30 -04:00
for (auto subcell_weight : subcell.GetOutWeight(node))
2017-02-20 08:20:22 -05:00
{
2017-04-04 07:04:30 -04:00
if (subcell_weight != INVALID_EDGE_WEIGHT)
2017-02-20 08:20:22 -05:00
{
2017-04-04 07:04:30 -04:00
const NodeID to = *subcell_destination;
2017-07-28 05:49:49 -04:00
if (!allowed_nodes[to])
{
continue;
}
2017-06-28 18:20:04 -04:00
const EdgeWeight to_weight = weight + subcell_weight;
const EdgeDuration to_duration = duration + *subcell_duration;
const EdgeDistance to_distance = distance + *subcell_distance;
2017-04-04 07:04:30 -04:00
if (!heap.WasInserted(to))
{
heap.Insert(to, to_weight, {true, to_duration, to_distance});
2017-04-04 07:04:30 -04:00
}
else if (std::tie(to_weight, to_duration, to_distance) <
std::tie(heap.GetKey(to),
heap.GetData(to).duration,
heap.GetData(to).distance))
2017-04-04 07:04:30 -04:00
{
heap.DecreaseKey(to, to_weight);
heap.GetData(to) = {true, to_duration, to_distance};
2017-04-04 07:04:30 -04:00
}
2017-02-20 08:20:22 -05:00
}
2017-04-04 07:04:30 -04:00
++subcell_destination;
2017-06-28 18:20:04 -04:00
++subcell_duration;
++subcell_distance;
2017-04-04 07:04:30 -04:00
}
2017-02-20 08:20:22 -05:00
}
}
// Relax base graph edges if a sub-cell border edge
for (auto edge : graph.GetInternalEdgeRange(level, node))
2017-02-20 08:20:22 -05:00
{
const NodeID to = graph.GetTarget(edge);
2017-07-28 05:49:49 -04:00
if (!allowed_nodes[to])
{
continue;
}
2017-02-20 08:20:22 -05:00
const auto &data = graph.GetEdgeData(edge);
if (data.forward && (first_level || partition.GetCell(level - 1, node) !=
partition.GetCell(level - 1, to)))
2017-02-20 08:20:22 -05:00
{
2017-06-28 18:20:04 -04:00
const EdgeWeight to_weight = weight + data.weight;
const EdgeDuration to_duration = duration + to_alias<EdgeDuration>(data.duration);
const EdgeDistance to_distance = distance + data.distance;
2017-02-20 08:20:22 -05:00
if (!heap.WasInserted(to))
{
heap.Insert(to, to_weight, {false, to_duration, to_distance});
2017-02-20 08:20:22 -05:00
}
else if (std::tie(to_weight, to_duration, to_distance) <
std::tie(
heap.GetKey(to), heap.GetData(to).duration, heap.GetData(to).distance))
2017-02-20 08:20:22 -05:00
{
heap.DecreaseKey(to, to_weight);
heap.GetData(to) = {false, to_duration, to_distance};
2017-02-20 08:20:22 -05:00
}
}
}
}
const partitioner::MultiLevelPartition &partition;
2017-02-20 08:20:22 -05:00
};
2022-12-20 12:00:11 -05:00
} // namespace osrm::customizer
2017-02-20 08:20:22 -05:00
#endif // OSRM_CELLS_CUSTOMIZER_HPP