Precompute accumulated segment data
This commit is contained in:
parent
864543b023
commit
4684a498c4
@ -345,12 +345,6 @@ updateSegmentData(const UpdaterConfig &config,
|
||||
}
|
||||
}
|
||||
|
||||
tbb::parallel_sort(updated_segments.begin(),
|
||||
updated_segments.end(),
|
||||
[](const GeometryID lhs, const GeometryID rhs) {
|
||||
return std::tie(lhs.id, lhs.forward) < std::tie(rhs.id, rhs.forward);
|
||||
});
|
||||
|
||||
return updated_segments;
|
||||
}
|
||||
|
||||
@ -543,17 +537,78 @@ Updater::LoadAndUpdateEdgeExpandedGraph(std::vector<extractor::EdgeBasedEdge> &e
|
||||
util::Log() << "Updating segment data took " << TIMER_MSEC(segment) << "ms.";
|
||||
}
|
||||
|
||||
std::vector<std::uint64_t> updated_turn_penalties;
|
||||
if (update_turn_penalties)
|
||||
{
|
||||
auto turn_penalty_lookup = csv::readTurnValues(config.turn_penalty_lookup_paths);
|
||||
updated_turn_penalties = updateTurnPenalties(config,
|
||||
profile_properties,
|
||||
turn_penalty_lookup,
|
||||
turn_weight_penalties,
|
||||
turn_duration_penalties);
|
||||
auto updated_turn_penalties = updateTurnPenalties(config,
|
||||
profile_properties,
|
||||
turn_penalty_lookup,
|
||||
turn_weight_penalties,
|
||||
turn_duration_penalties);
|
||||
// we need to re-compute all edges that have updated turn penalties.
|
||||
// this marks it for re-computation
|
||||
std::transform(updated_turn_penalties.begin(),
|
||||
updated_turn_penalties.end(),
|
||||
std::back_inserter(updated_segments),
|
||||
[&edge_data](const std::uint64_t edge_index) {
|
||||
return edge_data[edge_index].via_geometry;
|
||||
});
|
||||
}
|
||||
|
||||
tbb::parallel_sort(updated_segments.begin(),
|
||||
updated_segments.end(),
|
||||
[](const GeometryID lhs, const GeometryID rhs) {
|
||||
return std::tie(lhs.id, lhs.forward) < std::tie(rhs.id, rhs.forward);
|
||||
});
|
||||
|
||||
using WeightAndDuration = std::tuple<EdgeWeight, EdgeWeight>;
|
||||
const auto compute_new_weight_and_duration =
|
||||
[&](const GeometryID geometry_id) -> WeightAndDuration {
|
||||
EdgeWeight new_weight = 0;
|
||||
EdgeWeight new_duration = 0;
|
||||
if (geometry_id.forward)
|
||||
{
|
||||
const auto weights = segment_data.GetForwardWeights(geometry_id.id);
|
||||
for (const auto weight : weights)
|
||||
{
|
||||
if (weight == INVALID_EDGE_WEIGHT)
|
||||
{
|
||||
new_weight = INVALID_EDGE_WEIGHT;
|
||||
break;
|
||||
}
|
||||
new_weight += weight;
|
||||
}
|
||||
const auto durations = segment_data.GetForwardDurations(geometry_id.id);
|
||||
new_duration = std::accumulate(durations.begin(), durations.end(), 0);
|
||||
}
|
||||
else
|
||||
{
|
||||
const auto weights = segment_data.GetReverseWeights(geometry_id.id);
|
||||
for (const auto weight : weights)
|
||||
{
|
||||
if (weight == INVALID_EDGE_WEIGHT)
|
||||
{
|
||||
new_weight = INVALID_EDGE_WEIGHT;
|
||||
break;
|
||||
}
|
||||
new_weight += weight;
|
||||
}
|
||||
const auto durations = segment_data.GetReverseDurations(geometry_id.id);
|
||||
new_duration = std::accumulate(durations.begin(), durations.end(), 0);
|
||||
}
|
||||
return std::make_tuple(new_weight, new_duration);
|
||||
};
|
||||
|
||||
std::vector<WeightAndDuration> accumulated_segment_data(updated_segments.size());
|
||||
tbb::parallel_for(tbb::blocked_range<std::size_t>(0, updated_segments.size()),
|
||||
[&](const tbb::blocked_range<std::size_t> &range) {
|
||||
for (auto index = range.begin(); index < range.end(); ++index)
|
||||
{
|
||||
accumulated_segment_data[index] =
|
||||
compute_new_weight_and_duration(updated_segments[index]);
|
||||
}
|
||||
});
|
||||
|
||||
// Mapped file pointers for edge-based graph edges
|
||||
auto edge_based_edge_ptr = reinterpret_cast<const extractor::EdgeBasedEdge *>(
|
||||
reinterpret_cast<char *>(edge_based_graph_region.get_address()) +
|
||||
@ -564,9 +619,8 @@ Updater::LoadAndUpdateEdgeExpandedGraph(std::vector<extractor::EdgeBasedEdge> &e
|
||||
{
|
||||
// Make a copy of the data from the memory map
|
||||
extractor::EdgeBasedEdge inbuffer = edge_based_edge_ptr[edge_index];
|
||||
bool needs_update = update_turn_penalties;
|
||||
|
||||
if (update_edge_weights)
|
||||
if (updated_segments.size() > 0)
|
||||
{
|
||||
const auto geometry_id = edge_data[edge_index].via_geometry;
|
||||
auto updated_iter = std::lower_bound(updated_segments.begin(),
|
||||
@ -576,91 +630,51 @@ Updater::LoadAndUpdateEdgeExpandedGraph(std::vector<extractor::EdgeBasedEdge> &e
|
||||
return std::tie(lhs.id, lhs.forward) <
|
||||
std::tie(rhs.id, rhs.forward);
|
||||
});
|
||||
if (updated_iter == updated_segments.end() || updated_iter->id != geometry_id.id ||
|
||||
updated_iter->forward != geometry_id.forward)
|
||||
if (updated_iter != updated_segments.end() && updated_iter->id == geometry_id.id &&
|
||||
updated_iter->forward == geometry_id.forward)
|
||||
{
|
||||
needs_update = update_turn_penalties;
|
||||
}
|
||||
else
|
||||
{
|
||||
needs_update = true;
|
||||
}
|
||||
}
|
||||
// Find a segment with zero speed and simultaneously compute the new edge weight
|
||||
EdgeWeight new_weight;
|
||||
EdgeWeight new_duration;
|
||||
std::tie(new_weight, new_duration) =
|
||||
accumulated_segment_data[updated_iter - updated_segments.begin()];
|
||||
|
||||
if (needs_update)
|
||||
{
|
||||
// Find a segment with zero speed and simultaneously compute the new edge weight
|
||||
EdgeWeight new_weight = 0;
|
||||
EdgeWeight new_duration = 0;
|
||||
bool skip_edge = false;
|
||||
// Update the node-weight cache. This is the weight of the edge-based-node only,
|
||||
// it doesn't include the turn. We may visit the same node multiple times, but
|
||||
// we should always assign the same value here.
|
||||
if (node_weights.size() > 0)
|
||||
node_weights[inbuffer.source] = new_weight;
|
||||
|
||||
const auto geometry_id = edge_data[edge_index].via_geometry;
|
||||
if (geometry_id.forward)
|
||||
{
|
||||
const auto weights = segment_data.GetForwardWeights(geometry_id.id);
|
||||
for (const auto weight : weights)
|
||||
// We found a zero-speed edge, so we'll skip this whole edge-based-edge which
|
||||
// effectively removes it from the routing network.
|
||||
if (new_weight == INVALID_EDGE_WEIGHT)
|
||||
continue;
|
||||
|
||||
// Get the turn penalty and update to the new value if required
|
||||
auto turn_weight_penalty = turn_weight_penalties[edge_index];
|
||||
auto turn_duration_penalty = turn_duration_penalties[edge_index];
|
||||
const auto num_nodes = segment_data.GetForwardGeometry(geometry_id.id).size();
|
||||
const auto weight_min_value = static_cast<EdgeWeight>(num_nodes);
|
||||
if (turn_weight_penalty + new_weight < weight_min_value)
|
||||
{
|
||||
if (weight == INVALID_EDGE_WEIGHT)
|
||||
if (turn_weight_penalty < 0)
|
||||
{
|
||||
skip_edge = true;
|
||||
break;
|
||||
util::Log(logWARNING) << "turn penalty " << turn_weight_penalty
|
||||
<< " is too negative: clamping turn weight to "
|
||||
<< weight_min_value;
|
||||
turn_weight_penalty = weight_min_value - new_weight;
|
||||
turn_weight_penalties[edge_index] = turn_weight_penalty;
|
||||
}
|
||||
new_weight += weight;
|
||||
}
|
||||
const auto durations = segment_data.GetForwardDurations(geometry_id.id);
|
||||
new_duration = std::accumulate(durations.begin(), durations.end(), 0);
|
||||
}
|
||||
else
|
||||
{
|
||||
const auto weights = segment_data.GetReverseWeights(geometry_id.id);
|
||||
for (const auto weight : weights)
|
||||
{
|
||||
if (weight == INVALID_EDGE_WEIGHT)
|
||||
else
|
||||
{
|
||||
skip_edge = true;
|
||||
break;
|
||||
new_weight = weight_min_value;
|
||||
}
|
||||
new_weight += weight;
|
||||
}
|
||||
const auto durations = segment_data.GetReverseDurations(geometry_id.id);
|
||||
new_duration = std::accumulate(durations.begin(), durations.end(), 0);
|
||||
|
||||
// Update edge weight
|
||||
inbuffer.data.weight = new_weight + turn_weight_penalty;
|
||||
inbuffer.data.duration = new_duration + turn_duration_penalty;
|
||||
}
|
||||
|
||||
// Update the node-weight cache. This is the weight of the edge-based-node only,
|
||||
// it doesn't include the turn. We may visit the same node multiple times, but
|
||||
// we should always assign the same value here.
|
||||
if (node_weights.size() > 0)
|
||||
node_weights[inbuffer.source] = new_weight;
|
||||
|
||||
// We found a zero-speed edge, so we'll skip this whole edge-based-edge which
|
||||
// effectively removes it from the routing network.
|
||||
if (skip_edge)
|
||||
continue;
|
||||
|
||||
// Get the turn penalty and update to the new value if required
|
||||
auto turn_weight_penalty = turn_weight_penalties[edge_index];
|
||||
auto turn_duration_penalty = turn_duration_penalties[edge_index];
|
||||
const auto num_nodes = segment_data.GetForwardGeometry(geometry_id.id).size();
|
||||
const auto weight_min_value = static_cast<EdgeWeight>(num_nodes);
|
||||
if (turn_weight_penalty + new_weight < weight_min_value)
|
||||
{
|
||||
if (turn_weight_penalty < 0)
|
||||
{
|
||||
util::Log(logWARNING) << "turn penalty " << turn_weight_penalty
|
||||
<< " is too negative: clamping turn weight to "
|
||||
<< weight_min_value;
|
||||
turn_weight_penalty = weight_min_value - new_weight;
|
||||
turn_weight_penalties[edge_index] = turn_weight_penalty;
|
||||
}
|
||||
else
|
||||
{
|
||||
new_weight = weight_min_value;
|
||||
}
|
||||
}
|
||||
|
||||
// Update edge weight
|
||||
inbuffer.data.weight = new_weight + turn_weight_penalty;
|
||||
inbuffer.data.duration = new_duration + turn_duration_penalty;
|
||||
}
|
||||
|
||||
edge_based_edge_list.emplace_back(std::move(inbuffer));
|
||||
|
Loading…
Reference in New Issue
Block a user