Make edge metrics strongly typed (#6421)

This change takes the existing typedefs for weight, duration and
distance, and makes them proper types, using the existing Alias
functionality.

Primarily this is to prevent bugs where the metrics are switched,
but it also adds additional documentation. For example, it now
makes it clear (despite the naming of variables) that most of the
trip algorithm is running on the duration metric.

I've not made any changes to the casts performed between metrics
and numeric types, they now just more explicit.
This commit is contained in:
Michael Bell
2022-10-28 15:16:12 +01:00
committed by GitHub
parent 16685d0de9
commit 5d468f2897
69 changed files with 922 additions and 686 deletions
+14 -9
View File
@@ -90,7 +90,8 @@ Status TablePlugin::HandleRequest(const RoutingAlgorithmsInterface &algorithms,
std::vector<api::TableAPI::TableCellRef> estimated_pairs;
// Scan table for null results - if any exist, replace with distance estimates
if (params.fallback_speed != INVALID_FALLBACK_SPEED || params.scale_factor != 1)
if (params.fallback_speed != from_alias<double>(INVALID_FALLBACK_SPEED) ||
params.scale_factor != 1)
{
for (std::size_t row = 0; row < num_sources; row++)
{
@@ -98,7 +99,8 @@ Status TablePlugin::HandleRequest(const RoutingAlgorithmsInterface &algorithms,
{
const auto &table_index = row * num_destinations + column;
BOOST_ASSERT(table_index < result_tables_pair.first.size());
if (params.fallback_speed != INVALID_FALLBACK_SPEED && params.fallback_speed > 0 &&
if (params.fallback_speed != from_alias<double>(INVALID_FALLBACK_SPEED) &&
params.fallback_speed > 0 &&
result_tables_pair.first[table_index] == MAXIMAL_EDGE_DURATION)
{
const auto &source =
@@ -118,29 +120,32 @@ Status TablePlugin::HandleRequest(const RoutingAlgorithmsInterface &algorithms,
candidatesSnappedLocation(destination));
result_tables_pair.first[table_index] =
distance_estimate / (double)params.fallback_speed;
to_alias<EdgeDuration>(distance_estimate / params.fallback_speed);
if (!result_tables_pair.second.empty())
{
result_tables_pair.second[table_index] = distance_estimate;
result_tables_pair.second[table_index] =
to_alias<EdgeDistance>(distance_estimate);
}
estimated_pairs.emplace_back(row, column);
}
if (params.scale_factor > 0 && params.scale_factor != 1 &&
result_tables_pair.first[table_index] != MAXIMAL_EDGE_DURATION &&
result_tables_pair.first[table_index] != 0)
result_tables_pair.first[table_index] != EdgeDuration{0})
{
EdgeDuration diff =
MAXIMAL_EDGE_DURATION / result_tables_pair.first[table_index];
if (params.scale_factor >= diff)
if (params.scale_factor >= from_alias<double>(diff))
{
result_tables_pair.first[table_index] = MAXIMAL_EDGE_DURATION - 1;
result_tables_pair.first[table_index] =
MAXIMAL_EDGE_DURATION - EdgeDuration{1};
}
else
{
result_tables_pair.first[table_index] = std::lround(
result_tables_pair.first[table_index] * params.scale_factor);
result_tables_pair.first[table_index] = to_alias<EdgeDuration>(
std::lround(from_alias<double>(result_tables_pair.first[table_index]) *
params.scale_factor));
}
}
}
+16 -16
View File
@@ -497,17 +497,17 @@ void encodeVectorTile(const DataFacadeBase &facade,
auto name = facade.GetNameForID(name_id);
// If this is a valid forward edge, go ahead and add it to the tile
if (forward_duration != 0 && edge.forward_segment_id.enabled)
if (forward_duration != SegmentDuration{0} && edge.forward_segment_id.enabled)
{
// Calculate the speed for this line
std::uint32_t speed_kmh_idx =
static_cast<std::uint32_t>(round(length / forward_duration * 10 * 3.6));
std::uint32_t speed_kmh_idx = static_cast<std::uint32_t>(
round(length / from_alias<double>(forward_duration) * 10 * 3.6));
// Rate values are in meters per weight-unit - and similar to speeds, we
// present 1 decimal place of precision (these values are added as
// double/10) lower down
std::uint32_t forward_rate =
static_cast<std::uint32_t>(round(length / forward_weight * 10.));
std::uint32_t forward_rate = static_cast<std::uint32_t>(
round(length / from_alias<double>(forward_weight) * 10.));
auto tile_line = coordinatesToTileLine(a, b, tile_bbox);
if (!tile_line.empty())
@@ -519,8 +519,8 @@ void encodeVectorTile(const DataFacadeBase &facade,
fbuilder.set_is_small(component_id.is_tiny);
fbuilder.set_datasource(
facade.GetDatasourceName(forward_datasource_idx).to_string());
fbuilder.set_weight(forward_weight / 10.0);
fbuilder.set_duration(forward_duration / 10.0);
fbuilder.set_weight(from_alias<double>(forward_weight) / 10.0);
fbuilder.set_duration(from_alias<double>(forward_duration) / 10.0);
fbuilder.set_name(name);
fbuilder.set_rate(forward_rate / 10.0);
fbuilder.set_is_startpoint(is_startpoint);
@@ -531,17 +531,17 @@ void encodeVectorTile(const DataFacadeBase &facade,
// Repeat the above for the coordinates reversed and using the `reverse`
// properties
if (reverse_duration != 0 && edge.reverse_segment_id.enabled)
if (reverse_duration != SegmentDuration{0} && edge.reverse_segment_id.enabled)
{
// Calculate the speed for this line
std::uint32_t speed_kmh_idx =
static_cast<std::uint32_t>(round(length / reverse_duration * 10 * 3.6));
std::uint32_t speed_kmh_idx = static_cast<std::uint32_t>(
round(length / from_alias<double>(reverse_duration) * 10 * 3.6));
// Rate values are in meters per weight-unit - and similar to speeds, we
// present 1 decimal place of precision (these values are added as
// double/10) lower down
std::uint32_t reverse_rate =
static_cast<std::uint32_t>(round(length / reverse_weight * 10.));
std::uint32_t reverse_rate = static_cast<std::uint32_t>(
round(length / from_alias<double>(reverse_weight) * 10.));
auto tile_line = coordinatesToTileLine(b, a, tile_bbox);
if (!tile_line.empty())
@@ -553,8 +553,8 @@ void encodeVectorTile(const DataFacadeBase &facade,
fbuilder.set_is_small(component_id.is_tiny);
fbuilder.set_datasource(
facade.GetDatasourceName(reverse_datasource_idx).to_string());
fbuilder.set_weight(reverse_weight / 10.0);
fbuilder.set_duration(reverse_duration / 10.0);
fbuilder.set_weight(from_alias<double>(reverse_weight) / 10.0);
fbuilder.set_duration(from_alias<double>(reverse_duration) / 10.0);
fbuilder.set_name(name);
fbuilder.set_rate(reverse_rate / 10.0);
fbuilder.set_is_startpoint(is_startpoint);
@@ -582,8 +582,8 @@ void encodeVectorTile(const DataFacadeBase &facade,
fbuilder.set_bearing_in(turn_data.in_angle);
fbuilder.set_turn_angle(turn_data.turn_angle);
fbuilder.set_cost(turn_data.duration / 10.0);
fbuilder.set_weight(turn_data.weight / 10.0);
fbuilder.set_cost(from_alias<double>(turn_data.duration) / 10.0);
fbuilder.set_weight(from_alias<double>(turn_data.weight) / 10.0);
fbuilder.set_turn(turn_data.turn_instruction);
fbuilder.commit();
+12 -12
View File
@@ -20,9 +20,9 @@ namespace engine
namespace plugins
{
bool IsStronglyConnectedComponent(const util::DistTableWrapper<EdgeWeight> &result_table)
bool IsStronglyConnectedComponent(const util::DistTableWrapper<EdgeDuration> &result_table)
{
return std::find(std::begin(result_table), std::end(result_table), INVALID_EDGE_WEIGHT) ==
return std::find(std::begin(result_table), std::end(result_table), INVALID_EDGE_DURATION) ==
std::end(result_table);
}
@@ -68,7 +68,7 @@ TripPlugin::ComputeRoute(const RoutingAlgorithmsInterface &algorithms,
void ManipulateTableForFSE(const std::size_t source_id,
const std::size_t destination_id,
util::DistTableWrapper<EdgeWeight> &result_table)
util::DistTableWrapper<EdgeDuration> &result_table)
{
// ****************** Change Table *************************
// The following code manipulates the table and produces the new table for
@@ -94,7 +94,7 @@ void ManipulateTableForFSE(const std::size_t source_id,
{
if (i == source_id)
continue;
result_table.SetValue(i, source_id, INVALID_EDGE_WEIGHT);
result_table.SetValue(i, source_id, INVALID_EDGE_DURATION);
}
// change parameters.destination row
@@ -104,22 +104,22 @@ void ManipulateTableForFSE(const std::size_t source_id,
{
if (i == destination_id)
continue;
result_table.SetValue(destination_id, i, INVALID_EDGE_WEIGHT);
result_table.SetValue(destination_id, i, INVALID_EDGE_DURATION);
}
// set destination->source to zero so roundtrip treats source and
// destination as one location
result_table.SetValue(destination_id, source_id, 0);
result_table.SetValue(destination_id, source_id, {0});
// set source->destination as very high number so algorithm is forced
// to find another path to get to destination
result_table.SetValue(source_id, destination_id, INVALID_EDGE_WEIGHT);
result_table.SetValue(source_id, destination_id, INVALID_EDGE_DURATION);
//********* End of changes to table *************************************
}
void ManipulateTableForNonRoundtripFS(const std::size_t source_id,
util::DistTableWrapper<EdgeWeight> &result_table)
util::DistTableWrapper<EdgeDuration> &result_table)
{
// We can use the round-trip calculation to simulate non-round-trip fixed start
// by making all paths to the source location zero. Effectively finding an 'optimal'
@@ -127,12 +127,12 @@ void ManipulateTableForNonRoundtripFS(const std::size_t source_id,
// source.
for (const auto i : util::irange<size_t>(0, result_table.GetNumberOfNodes()))
{
result_table.SetValue(i, source_id, 0);
result_table.SetValue(i, source_id, {0});
}
}
void ManipulateTableForNonRoundtripFE(const std::size_t destination_id,
util::DistTableWrapper<EdgeWeight> &result_table)
util::DistTableWrapper<EdgeDuration> &result_table)
{
// We can use the round-trip calculation to simulate non-round-trip fixed end
// by making all paths from the destination to other locations zero.
@@ -140,7 +140,7 @@ void ManipulateTableForNonRoundtripFE(const std::size_t destination_id,
// from the destination to any source.
for (const auto i : util::irange<size_t>(0, result_table.GetNumberOfNodes()))
{
result_table.SetValue(destination_id, i, 0);
result_table.SetValue(destination_id, i, {0});
}
}
@@ -218,7 +218,7 @@ Status TripPlugin::HandleRequest(const RoutingAlgorithmsInterface &algorithms,
BOOST_ASSERT(snapped_phantoms.size() == number_of_locations);
// compute the duration table of all phantom nodes
auto result_duration_table = util::DistTableWrapper<EdgeWeight>(
auto result_duration_table = util::DistTableWrapper<EdgeDuration>(
algorithms.ManyToManySearch(snapped_phantoms, {}, {}, /*requestDistance*/ false).first,
number_of_locations);
@@ -44,7 +44,7 @@ struct RankedCandidateNode
bool operator<(const RankedCandidateNode &other) const
{
return (2 * weight + sharing) < (2 * other.weight + other.sharing);
return (EdgeWeight{2} * weight + sharing) < (EdgeWeight{2} * other.weight + other.sharing);
}
};
@@ -66,8 +66,8 @@ void alternativeRoutingStep(const DataFacade<Algorithm> &facade,
// toHeapNode is the same
const auto heapNode = forward_heap.DeleteMinGetHeapNode();
const auto scaled_weight =
static_cast<EdgeWeight>((heapNode.weight + min_edge_offset) / (1. + VIAPATH_EPSILON));
const auto scaled_weight = to_alias<EdgeWeight>(
from_alias<double>(heapNode.weight + min_edge_offset) / (1. + VIAPATH_EPSILON));
if ((INVALID_EDGE_WEIGHT != *upper_bound_to_shortest_path_weight) &&
(scaled_weight > *upper_bound_to_shortest_path_weight))
{
@@ -84,7 +84,7 @@ void alternativeRoutingStep(const DataFacade<Algorithm> &facade,
const EdgeWeight new_weight = reverseHeapNode->weight + heapNode.weight;
if (new_weight < *upper_bound_to_shortest_path_weight)
{
if (new_weight >= 0)
if (new_weight >= EdgeWeight{0})
{
*middle_node = heapNode.node;
*upper_bound_to_shortest_path_weight = new_weight;
@@ -92,7 +92,8 @@ void alternativeRoutingStep(const DataFacade<Algorithm> &facade,
else
{
// check whether there is a loop present at the node
const auto loop_weight = std::get<0>(getLoopWeight<false>(facade, heapNode.node));
const auto loop_weight =
std::get<0>(getLoopMetric<EdgeWeight>(facade, heapNode.node));
const EdgeWeight new_weight_with_loop = new_weight + loop_weight;
if (loop_weight != INVALID_EDGE_WEIGHT &&
new_weight_with_loop <= *upper_bound_to_shortest_path_weight)
@@ -112,7 +113,7 @@ void alternativeRoutingStep(const DataFacade<Algorithm> &facade,
const NodeID to = facade.GetTarget(edge);
const EdgeWeight edge_weight = data.weight;
BOOST_ASSERT(edge_weight > 0);
BOOST_ASSERT(edge_weight > EdgeWeight{0});
const EdgeWeight to_weight = heapNode.weight + edge_weight;
const auto toHeapNode = forward_heap.GetHeapNodeIfWasInserted(to);
@@ -180,7 +181,7 @@ void computeWeightAndSharingOfViaPath(SearchEngineData<Algorithm> &engine_workin
NodeID s_v_middle = SPECIAL_NODEID;
EdgeWeight upper_bound_s_v_path_weight = INVALID_EDGE_WEIGHT;
new_reverse_heap.Insert(via_node, 0, via_node);
new_reverse_heap.Insert(via_node, {0}, via_node);
// compute path <s,..,v> by reusing forward search from s
while (!new_reverse_heap.Empty())
{
@@ -196,7 +197,7 @@ void computeWeightAndSharingOfViaPath(SearchEngineData<Algorithm> &engine_workin
// compute path <v,..,t> by reusing backward search from node t
NodeID v_t_middle = SPECIAL_NODEID;
EdgeWeight upper_bound_of_v_t_path_weight = INVALID_EDGE_WEIGHT;
new_forward_heap.Insert(via_node, 0, via_node);
new_forward_heap.Insert(via_node, {0}, via_node);
while (!new_forward_heap.Empty())
{
routingStep<FORWARD_DIRECTION>(facade,
@@ -342,7 +343,7 @@ bool viaNodeCandidatePassesTTest(SearchEngineData<Algorithm> &engine_working_dat
*s_v_middle = SPECIAL_NODEID;
EdgeWeight upper_bound_s_v_path_weight = INVALID_EDGE_WEIGHT;
// compute path <s,..,v> by reusing forward search from s
new_reverse_heap.Insert(candidate.node, 0, candidate.node);
new_reverse_heap.Insert(candidate.node, {0}, candidate.node);
while (new_reverse_heap.Size() > 0)
{
routingStep<REVERSE_DIRECTION>(facade,
@@ -363,7 +364,7 @@ bool viaNodeCandidatePassesTTest(SearchEngineData<Algorithm> &engine_working_dat
// compute path <v,..,t> by reusing backward search from t
*v_t_middle = SPECIAL_NODEID;
EdgeWeight upper_bound_of_v_t_path_weight = INVALID_EDGE_WEIGHT;
new_forward_heap.Insert(candidate.node, 0, candidate.node);
new_forward_heap.Insert(candidate.node, {0}, candidate.node);
while (new_forward_heap.Size() > 0)
{
routingStep<FORWARD_DIRECTION>(facade,
@@ -400,8 +401,9 @@ bool viaNodeCandidatePassesTTest(SearchEngineData<Algorithm> &engine_working_dat
{
return false;
}
const EdgeWeight T_threshold = static_cast<EdgeWeight>(VIAPATH_ALPHA * weight_of_shortest_path);
EdgeWeight unpacked_until_weight = 0;
const EdgeWeight T_threshold =
to_alias<EdgeWeight>(VIAPATH_ALPHA * from_alias<double>(weight_of_shortest_path));
EdgeWeight unpacked_until_weight = {0};
std::stack<SearchSpaceEdge> unpack_stack;
// Traverse path s-->v
@@ -463,7 +465,7 @@ bool viaNodeCandidatePassesTTest(SearchEngineData<Algorithm> &engine_working_dat
}
EdgeWeight t_test_path_weight = unpacked_until_weight;
unpacked_until_weight = 0;
unpacked_until_weight = {0};
// Traverse path s-->v
BOOST_ASSERT(!packed_v_t_path.empty());
for (unsigned i = 0, packed_path_length = static_cast<unsigned>(packed_v_t_path.size() - 1);
@@ -532,8 +534,8 @@ bool viaNodeCandidatePassesTTest(SearchEngineData<Algorithm> &engine_working_dat
EdgeWeight upper_bound = INVALID_EDGE_WEIGHT;
NodeID middle = SPECIAL_NODEID;
forward_heap3.Insert(s_P, 0, s_P);
reverse_heap3.Insert(t_P, 0, t_P);
forward_heap3.Insert(s_P, {0}, s_P);
reverse_heap3.Insert(t_P, {0}, t_P);
// exploration from s and t until deletemin/(1+epsilon) > _lengt_oO_sShortest_path
while ((forward_heap3.Size() + reverse_heap3.Size()) > 0)
{
@@ -580,10 +582,11 @@ InternalManyRoutesResult alternativePathSearch(SearchEngineData<Algorithm> &engi
insertNodesInHeaps(forward_heap1, reverse_heap1, endpoint_candidates);
// get offset to account for offsets on phantom nodes on compressed edges
EdgeWeight min_edge_offset = forward_heap1.Empty() ? 0 : std::min(0, forward_heap1.MinKey());
BOOST_ASSERT(min_edge_offset <= 0);
EdgeWeight min_edge_offset =
forward_heap1.Empty() ? EdgeWeight{0} : std::min<EdgeWeight>({0}, forward_heap1.MinKey());
BOOST_ASSERT(min_edge_offset <= EdgeWeight{0});
// we only every insert negative offsets for nodes in the forward heap
BOOST_ASSERT(reverse_heap1.Empty() || reverse_heap1.MinKey() >= 0);
BOOST_ASSERT(reverse_heap1.Empty() || reverse_heap1.MinKey() >= EdgeWeight{0});
// search from s and t till new_min/(1+epsilon) > weight_of_shortest_path
while (0 < (forward_heap1.Size() + reverse_heap1.Size()))
@@ -701,22 +704,27 @@ InternalManyRoutesResult alternativePathSearch(SearchEngineData<Algorithm> &engi
if (node == middle_node)
continue;
const auto fwd_iterator = approximated_forward_sharing.find(node);
const EdgeWeight fwd_sharing =
(fwd_iterator != approximated_forward_sharing.end()) ? fwd_iterator->second : 0;
const EdgeWeight fwd_sharing = (fwd_iterator != approximated_forward_sharing.end())
? fwd_iterator->second
: EdgeWeight{0};
const auto rev_iterator = approximated_reverse_sharing.find(node);
const EdgeWeight rev_sharing =
(rev_iterator != approximated_reverse_sharing.end()) ? rev_iterator->second : 0;
const EdgeWeight rev_sharing = (rev_iterator != approximated_reverse_sharing.end())
? rev_iterator->second
: EdgeWeight{0};
const EdgeWeight approximated_sharing = fwd_sharing + rev_sharing;
const EdgeWeight approximated_weight =
forward_heap1.GetKey(node) + reverse_heap1.GetKey(node);
const bool weight_passes =
(approximated_weight < upper_bound_to_shortest_path_weight * (1 + VIAPATH_EPSILON));
(from_alias<double>(approximated_weight) <
from_alias<double>(upper_bound_to_shortest_path_weight) * (1 + VIAPATH_EPSILON));
const bool sharing_passes =
(approximated_sharing <= upper_bound_to_shortest_path_weight * VIAPATH_GAMMA);
(from_alias<double>(approximated_sharing) <=
from_alias<double>(upper_bound_to_shortest_path_weight) * VIAPATH_GAMMA);
const bool stretch_passes =
(approximated_weight - approximated_sharing) <
((1. + VIAPATH_EPSILON) * (upper_bound_to_shortest_path_weight - approximated_sharing));
from_alias<double>(approximated_weight - approximated_sharing) <
((1. + VIAPATH_EPSILON) *
from_alias<double>(upper_bound_to_shortest_path_weight - approximated_sharing));
if (weight_passes && sharing_passes && stretch_passes)
{
@@ -737,7 +745,7 @@ InternalManyRoutesResult alternativePathSearch(SearchEngineData<Algorithm> &engi
// prioritizing via nodes for deep inspection
for (const NodeID node : preselected_node_list)
{
EdgeWeight weight_of_via_path = 0, sharing_of_via_path = 0;
EdgeWeight weight_of_via_path = {0}, sharing_of_via_path = {0};
computeWeightAndSharingOfViaPath(engine_working_data,
facade,
node,
@@ -745,10 +753,11 @@ InternalManyRoutesResult alternativePathSearch(SearchEngineData<Algorithm> &engi
&sharing_of_via_path,
packed_shortest_path,
min_edge_offset);
const EdgeWeight maximum_allowed_sharing =
static_cast<EdgeWeight>(upper_bound_to_shortest_path_weight * VIAPATH_GAMMA);
const EdgeWeight maximum_allowed_sharing = to_alias<EdgeWeight>(
from_alias<double>(upper_bound_to_shortest_path_weight) * VIAPATH_GAMMA);
if (sharing_of_via_path <= maximum_allowed_sharing &&
weight_of_via_path <= upper_bound_to_shortest_path_weight * (1 + VIAPATH_EPSILON))
from_alias<double>(weight_of_via_path) <=
from_alias<double>(upper_bound_to_shortest_path_weight) * (1 + VIAPATH_EPSILON))
{
ranked_candidates_list.emplace_back(node, weight_of_via_path, sharing_of_via_path);
}
@@ -85,9 +85,9 @@ struct WeightedViaNodeUnpackedPath
// Scale the maximum allowed weight increase based on its magnitude:
// - Shortest path 10 minutes, alternative 13 minutes => Factor of 0.30 ok
// - Shortest path 10 hours, alternative 13 hours => Factor of 0.30 unreasonable
double getLongerByFactorBasedOnDuration(const EdgeWeight duration)
double getLongerByFactorBasedOnDuration(const EdgeDuration duration)
{
BOOST_ASSERT(duration != INVALID_EDGE_WEIGHT);
BOOST_ASSERT(duration != INVALID_EDGE_DURATION);
// We only have generic weights here and no durations without unpacking.
// We also have restricted way penalties which are huge and will screw scaling here.
@@ -118,19 +118,20 @@ double getLongerByFactorBasedOnDuration(const EdgeWeight duration)
const constexpr auto c = 2.45437877e+09;
const constexpr auto d = -2.07944571e+03;
if (duration < EdgeWeight(5 * 60))
if (duration < EdgeDuration{5 * 60})
{
return 1.0;
}
else if (duration > EdgeWeight(10 * 60 * 60))
else if (duration > EdgeDuration{10 * 60 * 60})
{
return 0.20;
}
// Bigger than 10 minutes but smaller than 10 hours
BOOST_ASSERT(duration >= 5 * 60 && duration <= 10 * 60 * 60);
BOOST_ASSERT(duration >= EdgeDuration{5 * 60} && duration <= EdgeDuration{10 * 60 * 60});
return a + b / (duration - d) + c / std::pow(duration - d, 3);
return a + b / (from_alias<double>(duration) - d) +
c / std::pow(from_alias<double>(duration) - d, 3);
}
Parameters parametersFromRequest(const PhantomEndpointCandidates &endpoint_candidates)
@@ -223,10 +224,11 @@ RandIt filterViaCandidatesByStretch(RandIt first,
// Assumes weight roughly corresponds to duration-ish. If this is not the case e.g.
// because users are setting weight to be distance in the profiles, then we might
// either generate more candidates than we have to or not enough. But is okay.
const auto stretch_weight_limit = (1. + parameters.kAtMostLongerBy) * weight;
const auto stretch_weight_limit =
(1. + parameters.kAtMostLongerBy) * from_alias<double>(weight);
const auto over_weight_limit = [=](const auto via) {
return via.weight > stretch_weight_limit;
return from_alias<double>(via.weight) > stretch_weight_limit;
};
return std::remove_if(first, last, over_weight_limit);
@@ -444,7 +446,8 @@ RandIt filterPackedPathsByLocalOptimality(const WeightedViaNodePackedPath &path,
const auto detour_length = forward_heap.GetKey(via) - forward_heap.GetKey(a) +
reverse_heap.GetKey(via) - reverse_heap.GetKey(b);
return plateaux_length < parameters.kAtLeastOptimalAroundViaBy * detour_length;
return from_alias<double>(plateaux_length) <
parameters.kAtLeastOptimalAroundViaBy * from_alias<double>(detour_length);
};
return std::remove_if(first, last, is_not_locally_optimal);
@@ -482,8 +485,8 @@ RandIt filterUnpackedPathsBySharing(RandIt first,
return false;
}
EdgeWeight total_duration = 0;
const auto add_if_seen = [&](const EdgeWeight duration, const NodeID node) {
EdgeDuration total_duration = {0};
const auto add_if_seen = [&](const EdgeDuration duration, const NodeID node) {
auto node_duration = facade.GetNodeDuration(node);
total_duration += node_duration;
if (nodes.count(node) > 0)
@@ -496,7 +499,7 @@ RandIt filterUnpackedPathsBySharing(RandIt first,
const auto shared_duration = std::accumulate(
begin(unpacked.nodes), end(unpacked.nodes), EdgeDuration{0}, add_if_seen);
unpacked.sharing = shared_duration / static_cast<double>(total_duration);
unpacked.sharing = from_alias<double>(shared_duration) / from_alias<double>(total_duration);
BOOST_ASSERT(unpacked.sharing >= 0.);
BOOST_ASSERT(unpacked.sharing <= 1.);
@@ -531,10 +534,11 @@ RandIt filterAnnotatedRoutesByStretch(RandIt first,
BOOST_ASSERT(shortest_route.is_valid());
const auto shortest_route_duration = shortest_route.duration();
const auto stretch_duration_limit = (1. + parameters.kAtMostLongerBy) * shortest_route_duration;
const auto stretch_duration_limit =
(1. + parameters.kAtMostLongerBy) * from_alias<double>(shortest_route_duration);
const auto over_duration_limit = [=](const auto &route) {
return route.duration() > stretch_duration_limit;
return from_alias<double>(route.duration()) > stretch_duration_limit;
};
return std::remove_if(first, last, over_duration_limit);
@@ -610,8 +614,8 @@ void unpackPackedPaths(InputIt first,
// Here heaps can be reused, let's go deeper!
forward_heap.Clear();
reverse_heap.Clear();
forward_heap.Insert(source, 0, {source});
reverse_heap.Insert(target, 0, {target});
forward_heap.Insert(source, {0}, {source});
reverse_heap.Insert(target, {0}, {target});
BOOST_ASSERT(!facade.ExcludeNode(source));
BOOST_ASSERT(!facade.ExcludeNode(target));
@@ -694,7 +698,8 @@ makeCandidateVias(SearchEngineData<Algorithm> &search_engine_data,
while (forward_heap.Size() + reverse_heap.Size() > 0)
{
if (shortest_path_weight != INVALID_EDGE_WEIGHT)
overlap_weight = shortest_path_weight * parameters.kSearchSpaceOverlapFactor;
overlap_weight = to_alias<EdgeWeight>(from_alias<double>(shortest_path_weight) *
parameters.kSearchSpaceOverlapFactor);
// Termination criteria - when we have a shortest path this will guarantee for our overlap.
const bool keep_going = forward_heap_min + reverse_heap_min < overlap_weight;
@@ -820,8 +825,10 @@ InternalManyRoutesResult alternativePathSearch(SearchEngineData<Algorithm> &sear
NodeID shortest_path_via = shortest_path_via_it->node;
EdgeWeight shortest_path_weight = shortest_path_via_it->weight;
const double duration_estimation = shortest_path_weight / facade.GetWeightMultiplier();
parameters.kAtMostLongerBy = getLongerByFactorBasedOnDuration(duration_estimation);
const double duration_estimation =
from_alias<double>(shortest_path_weight) / facade.GetWeightMultiplier();
parameters.kAtMostLongerBy =
getLongerByFactorBasedOnDuration(to_alias<EdgeDuration>(duration_estimation));
// Filters via candidate nodes with heuristics
@@ -24,16 +24,16 @@ inline bool addLoopWeight(const DataFacade<ch::Algorithm> &facade,
EdgeDuration &duration,
EdgeDistance &distance)
{ // Special case for CH when contractor creates a loop edge node->node
BOOST_ASSERT(weight < 0);
BOOST_ASSERT(weight < EdgeWeight{0});
const auto loop_weight = ch::getLoopWeight<false>(facade, node);
const auto loop_weight = ch::getLoopMetric<EdgeWeight>(facade, node);
if (std::get<0>(loop_weight) != INVALID_EDGE_WEIGHT)
{
const auto new_weight_with_loop = weight + std::get<0>(loop_weight);
if (new_weight_with_loop >= 0)
if (new_weight_with_loop >= EdgeWeight{0})
{
weight = new_weight_with_loop;
auto result = ch::getLoopWeight<true>(facade, node);
auto result = ch::getLoopMetric<EdgeDuration>(facade, node);
duration += std::get<0>(result);
distance += std::get<1>(result);
return true;
@@ -67,9 +67,9 @@ void relaxOutgoingEdges(
const auto edge_duration = data.duration;
const auto edge_distance = data.distance;
BOOST_ASSERT_MSG(edge_weight > 0, "edge_weight invalid");
BOOST_ASSERT_MSG(edge_weight > EdgeWeight{0}, "edge_weight invalid");
const auto to_weight = heapNode.weight + edge_weight;
const auto to_duration = heapNode.data.duration + edge_duration;
const auto to_duration = heapNode.data.duration + to_alias<EdgeDuration>(edge_duration);
const auto to_distance = heapNode.data.distance + edge_distance;
const auto toHeapNode = query_heap.GetHeapNodeIfWasInserted(to);
@@ -120,7 +120,7 @@ void forwardRoutingStep(const DataFacade<Algorithm> &facade,
auto &current_weight = weights_table[row_index * number_of_targets + column_index];
EdgeDistance nulldistance = 0;
EdgeDistance nulldistance = {0};
auto &current_duration = durations_table[row_index * number_of_targets + column_index];
auto &current_distance =
@@ -132,7 +132,7 @@ void forwardRoutingStep(const DataFacade<Algorithm> &facade,
auto new_duration = heapNode.data.duration + target_duration;
auto new_distance = heapNode.data.distance + target_distance;
if (new_weight < 0)
if (new_weight < EdgeWeight{0})
{
if (addLoopWeight(facade, heapNode.node, new_weight, new_duration, new_distance))
{
@@ -62,10 +62,13 @@ void relaxBorderEdges(const DataFacade<mld::Algorithm> &facade,
const auto node_weight = facade.GetNodeWeight(node_id);
const auto node_duration = facade.GetNodeDuration(node_id);
const auto node_distance = facade.GetNodeDistance(node_id);
const auto turn_weight = node_weight + facade.GetWeightPenaltyForEdgeID(turn_id);
const auto turn_duration = node_duration + facade.GetDurationPenaltyForEdgeID(turn_id);
const auto turn_weight =
node_weight + alias_cast<EdgeWeight>(facade.GetWeightPenaltyForEdgeID(turn_id));
const auto turn_duration =
node_duration +
alias_cast<EdgeDuration>(facade.GetDurationPenaltyForEdgeID(turn_id));
BOOST_ASSERT_MSG(node_weight + turn_weight > 0, "edge weight is invalid");
BOOST_ASSERT_MSG(node_weight + turn_weight > EdgeWeight{0}, "edge weight is invalid");
const auto to_weight = weight + turn_weight;
const auto to_duration = duration + turn_duration;
const auto to_distance = distance + node_distance;
@@ -259,17 +262,17 @@ oneToManySearch(SearchEngineData<Algorithm> &engine_working_data,
target_nodes_index.insert(
{phantom_node.forward_segment_id.id,
std::make_tuple(index,
-phantom_node.GetForwardWeightPlusOffset(),
-phantom_node.GetForwardDuration(),
-phantom_node.GetForwardDistance())});
EdgeWeight{0} - phantom_node.GetForwardWeightPlusOffset(),
EdgeDuration{0} - phantom_node.GetForwardDuration(),
EdgeDistance{0} - phantom_node.GetForwardDistance())});
if (phantom_node.IsValidReverseSource())
target_nodes_index.insert(
{phantom_node.reverse_segment_id.id,
std::make_tuple(index,
-phantom_node.GetReverseWeightPlusOffset(),
-phantom_node.GetReverseDuration(),
-phantom_node.GetReverseDistance())});
EdgeWeight{0} - phantom_node.GetReverseWeightPlusOffset(),
EdgeDuration{0} - phantom_node.GetReverseDuration(),
EdgeDistance{0} - phantom_node.GetReverseDistance())});
}
}
}
@@ -292,12 +295,12 @@ oneToManySearch(SearchEngineData<Algorithm> &engine_working_data,
std::tie(index, target_weight, target_duration, target_distance) = it->second;
const auto path_weight = weight + target_weight;
if (path_weight >= 0)
if (path_weight >= EdgeWeight{0})
{
const auto path_duration = duration + target_duration;
const auto path_distance = distance + target_distance;
EdgeDistance nulldistance = 0;
EdgeDistance nulldistance = {0};
auto &current_distance =
distances_table.empty() ? nulldistance : distances_table[index];
@@ -350,17 +353,17 @@ oneToManySearch(SearchEngineData<Algorithm> &engine_working_data,
if (phantom_node.IsValidForwardSource())
{
insert_node(phantom_node.forward_segment_id.id,
-phantom_node.GetForwardWeightPlusOffset(),
-phantom_node.GetForwardDuration(),
-phantom_node.GetForwardDistance());
EdgeWeight{0} - phantom_node.GetForwardWeightPlusOffset(),
EdgeDuration{0} - phantom_node.GetForwardDuration(),
EdgeDistance{0} - phantom_node.GetForwardDistance());
}
if (phantom_node.IsValidReverseSource())
{
insert_node(phantom_node.reverse_segment_id.id,
-phantom_node.GetReverseWeightPlusOffset(),
-phantom_node.GetReverseDuration(),
-phantom_node.GetReverseDistance());
EdgeWeight{0} - phantom_node.GetReverseWeightPlusOffset(),
EdgeDuration{0} - phantom_node.GetReverseDuration(),
EdgeDistance{0} - phantom_node.GetReverseDistance());
}
}
else if (DIRECTION == REVERSE_DIRECTION)
@@ -444,7 +447,7 @@ void forwardRoutingStep(const DataFacade<Algorithm> &facade,
auto &current_weight = weights_table[location];
auto &current_duration = durations_table[location];
EdgeDistance nulldistance = 0;
EdgeDistance nulldistance = {0};
auto &current_distance = distances_table.empty() ? nulldistance : distances_table[location];
// Check if new weight is better
@@ -452,8 +455,9 @@ void forwardRoutingStep(const DataFacade<Algorithm> &facade,
auto new_duration = heapNode.data.duration + target_duration;
auto new_distance = heapNode.data.distance + target_distance;
if (new_weight >= 0 && std::tie(new_weight, new_duration, new_distance) <
std::tie(current_weight, current_duration, current_distance))
if (new_weight >= EdgeWeight{0} &&
std::tie(new_weight, new_duration, new_distance) <
std::tie(current_weight, current_duration, current_distance))
{
current_weight = new_weight;
current_duration = new_duration;
@@ -217,8 +217,8 @@ SubMatchingList mapMatching(SearchEngineData<Algorithm> &engine_working_data,
const auto haversine_distance = util::coordinate_calculation::greatCircleDistance(
prev_coordinate, current_coordinate);
// assumes minumum of 4 m/s
const EdgeWeight weight_upper_bound =
((haversine_distance + max_distance_delta) / 4.) * facade.GetWeightMultiplier();
const EdgeWeight weight_upper_bound = to_alias<EdgeWeight>(
((haversine_distance + max_distance_delta) / 4.) * facade.GetWeightMultiplier());
// compute d_t for this timestamp and the next one
for (const auto s : util::irange<std::size_t>(0UL, prev_viterbi.size()))
@@ -109,10 +109,10 @@ void search(SearchEngineData<Algorithm> & /*engine_working_data*/,
weight = weight_upper_bound;
// get offset to account for offsets on phantom nodes on compressed edges
const auto min_edge_offset = std::min(0, forward_heap.MinKey());
BOOST_ASSERT(min_edge_offset <= 0);
const auto min_edge_offset = std::min<EdgeWeight>({0}, forward_heap.MinKey());
BOOST_ASSERT(min_edge_offset <= EdgeWeight{0});
// we only every insert negative offsets for nodes in the forward heap
BOOST_ASSERT(reverse_heap.MinKey() >= 0);
BOOST_ASSERT(reverse_heap.MinKey() >= EdgeWeight{0});
// run two-Target Dijkstra routing step.
while (0 < (forward_heap.Size() + reverse_heap.Size()))
+2 -2
View File
@@ -182,8 +182,8 @@ std::vector<TurnData> generateTurns(const datafacade &facade,
all_turn_data.push_back(TurnData{coord_via,
angle_in,
turn_angle,
turn_weight,
turn_duration,
alias_cast<EdgeWeight>(turn_weight),
alias_cast<EdgeDuration>(turn_duration),
turn_instruction});
}
}