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 -11
View File
@@ -133,7 +133,8 @@ class TableAPI final : public BaseAPI
}
bool have_speed_cells =
parameters.fallback_speed != INVALID_FALLBACK_SPEED && parameters.fallback_speed > 0;
parameters.fallback_speed != from_alias<double>(INVALID_FALLBACK_SPEED) &&
parameters.fallback_speed > 0;
flatbuffers::Offset<flatbuffers::Vector<uint32_t>> speed_cells;
if (have_speed_cells)
{
@@ -223,7 +224,8 @@ class TableAPI final : public BaseAPI
MakeDistanceTable(tables.second, number_of_sources, number_of_destinations);
}
if (parameters.fallback_speed != INVALID_FALLBACK_SPEED && parameters.fallback_speed > 0)
if (parameters.fallback_speed != from_alias<double>(INVALID_FALLBACK_SPEED) &&
parameters.fallback_speed > 0)
{
response.values["fallback_speed_cells"] = MakeEstimatesTable(fallback_speed_cells);
}
@@ -272,17 +274,17 @@ class TableAPI final : public BaseAPI
virtual flatbuffers::Offset<flatbuffers::Vector<float>>
MakeDurationTable(flatbuffers::FlatBufferBuilder &builder,
const std::vector<EdgeWeight> &values) const
const std::vector<EdgeDuration> &values) const
{
std::vector<float> distance_table;
distance_table.resize(values.size());
std::transform(
values.begin(), values.end(), distance_table.begin(), [](const EdgeWeight duration) {
values.begin(), values.end(), distance_table.begin(), [](const EdgeDuration duration) {
if (duration == MAXIMAL_EDGE_DURATION)
{
return 0.;
}
return duration / 10.;
return from_alias<double>(duration) / 10.;
});
return builder.CreateVector(distance_table);
}
@@ -299,7 +301,7 @@ class TableAPI final : public BaseAPI
{
return 0.;
}
return std::round(distance * 10) / 10.;
return std::round(from_alias<double>(distance) * 10) / 10.;
});
return builder.CreateVector(duration_table);
}
@@ -347,7 +349,7 @@ class TableAPI final : public BaseAPI
return json_waypoints;
}
virtual util::json::Array MakeDurationTable(const std::vector<EdgeWeight> &values,
virtual util::json::Array MakeDurationTable(const std::vector<EdgeDuration> &values,
std::size_t number_of_rows,
std::size_t number_of_columns) const
{
@@ -361,13 +363,14 @@ class TableAPI final : public BaseAPI
std::transform(row_begin_iterator,
row_end_iterator,
json_row.values.begin(),
[](const EdgeWeight duration) {
[](const EdgeDuration duration) {
if (duration == MAXIMAL_EDGE_DURATION)
{
return util::json::Value(util::json::Null());
}
// division by 10 because the duration is in deciseconds (10s)
return util::json::Value(util::json::Number(duration / 10.));
return util::json::Value(
util::json::Number(from_alias<double>(duration) / 10.));
});
json_table.values.push_back(std::move(json_row));
}
@@ -394,8 +397,8 @@ class TableAPI final : public BaseAPI
return util::json::Value(util::json::Null());
}
// round to single decimal place
return util::json::Value(
util::json::Number(std::round(distance * 10) / 10.));
return util::json::Value(util::json::Number(
std::round(from_alias<double>(distance) * 10) / 10.));
});
json_table.values.push_back(std::move(json_row));
}
+1 -1
View File
@@ -59,7 +59,7 @@ struct TableParameters : public BaseParameters
{
std::vector<std::size_t> sources;
std::vector<std::size_t> destinations;
double fallback_speed = INVALID_FALLBACK_SPEED;
double fallback_speed = from_alias<double>(INVALID_FALLBACK_SPEED);
enum class FallbackCoordinateType
{
@@ -83,7 +83,7 @@ template <> class AlgorithmDataFacade<MLD>
virtual EdgeWeight GetNodeWeight(const NodeID edge_based_node_id) const = 0;
virtual EdgeWeight
virtual EdgeDuration
GetNodeDuration(const NodeID edge_based_node_id) const = 0; // TODO: to be removed
virtual EdgeDistance GetNodeDistance(const NodeID edge_based_node_id) const = 0;
+43 -34
View File
@@ -320,75 +320,84 @@ template <typename RTreeT, typename DataFacadeT> class GeospatialQuery
const auto forward_weight_offset =
// NOLINTNEXTLINE(bugprone-fold-init-type)
std::accumulate(forward_weights.begin(),
forward_weights.begin() + data.fwd_segment_position,
EdgeWeight{0});
alias_cast<EdgeWeight>(
std::accumulate(forward_weights.begin(),
forward_weights.begin() + data.fwd_segment_position,
SegmentWeight{0}));
const auto forward_duration_offset =
// NOLINTNEXTLINE(bugprone-fold-init-type)
std::accumulate(forward_durations.begin(),
forward_durations.begin() + data.fwd_segment_position,
EdgeDuration{0});
alias_cast<EdgeDuration>(
std::accumulate(forward_durations.begin(),
forward_durations.begin() + data.fwd_segment_position,
SegmentDuration{0}));
EdgeDistance forward_distance_offset = 0;
EdgeDistance forward_distance_offset = {0};
// Sum up the distance from the start to the fwd_segment_position
for (auto current = forward_geometry.begin();
current < forward_geometry.begin() + data.fwd_segment_position;
++current)
{
forward_distance_offset += util::coordinate_calculation::greatCircleDistance(
datafacade.GetCoordinateOfNode(*current),
datafacade.GetCoordinateOfNode(*std::next(current)));
forward_distance_offset +=
to_alias<EdgeDistance>(util::coordinate_calculation::greatCircleDistance(
datafacade.GetCoordinateOfNode(*current),
datafacade.GetCoordinateOfNode(*std::next(current))));
}
BOOST_ASSERT(data.fwd_segment_position <
std::distance(forward_durations.begin(), forward_durations.end()));
EdgeWeight forward_weight = forward_weights[data.fwd_segment_position];
EdgeDuration forward_duration = forward_durations[data.fwd_segment_position];
EdgeDistance forward_distance = util::coordinate_calculation::greatCircleDistance(
datafacade.GetCoordinateOfNode(forward_geometry(data.fwd_segment_position)),
point_on_segment);
EdgeWeight forward_weight =
alias_cast<EdgeWeight>(forward_weights[data.fwd_segment_position]);
EdgeDuration forward_duration =
alias_cast<EdgeDuration>(forward_durations[data.fwd_segment_position]);
EdgeDistance forward_distance =
to_alias<EdgeDistance>(util::coordinate_calculation::greatCircleDistance(
datafacade.GetCoordinateOfNode(forward_geometry(data.fwd_segment_position)),
point_on_segment));
const auto reverse_weight_offset =
const auto reverse_weight_offset = alias_cast<EdgeWeight>(
std::accumulate(reverse_weights.begin(),
reverse_weights.end() - data.fwd_segment_position - 1,
EdgeWeight{0});
SegmentWeight{0}));
const auto reverse_duration_offset =
const auto reverse_duration_offset = alias_cast<EdgeDuration>(
std::accumulate(reverse_durations.begin(),
reverse_durations.end() - data.fwd_segment_position - 1,
EdgeDuration{0});
SegmentDuration{0}));
EdgeDistance reverse_distance_offset = 0;
EdgeDistance reverse_distance_offset = {0};
// Sum up the distance from just after the fwd_segment_position to the end
for (auto current = forward_geometry.begin() + data.fwd_segment_position + 1;
current != std::prev(forward_geometry.end());
++current)
{
reverse_distance_offset += util::coordinate_calculation::greatCircleDistance(
datafacade.GetCoordinateOfNode(*current),
datafacade.GetCoordinateOfNode(*std::next(current)));
reverse_distance_offset +=
to_alias<EdgeDistance>(util::coordinate_calculation::greatCircleDistance(
datafacade.GetCoordinateOfNode(*current),
datafacade.GetCoordinateOfNode(*std::next(current))));
}
EdgeWeight reverse_weight =
reverse_weights[reverse_weights.size() - data.fwd_segment_position - 1];
EdgeDuration reverse_duration =
reverse_durations[reverse_durations.size() - data.fwd_segment_position - 1];
EdgeDistance reverse_distance = util::coordinate_calculation::greatCircleDistance(
point_on_segment,
datafacade.GetCoordinateOfNode(forward_geometry(data.fwd_segment_position + 1)));
EdgeWeight reverse_weight = alias_cast<EdgeWeight>(
reverse_weights[reverse_weights.size() - data.fwd_segment_position - 1]);
EdgeDuration reverse_duration = alias_cast<EdgeDuration>(
reverse_durations[reverse_durations.size() - data.fwd_segment_position - 1]);
EdgeDistance reverse_distance =
to_alias<EdgeDistance>(util::coordinate_calculation::greatCircleDistance(
point_on_segment,
datafacade.GetCoordinateOfNode(forward_geometry(data.fwd_segment_position + 1))));
ratio = std::min(1.0, std::max(0.0, ratio));
if (data.forward_segment_id.id != SPECIAL_SEGMENTID)
{
forward_weight = static_cast<EdgeWeight>(forward_weight * ratio);
forward_duration = static_cast<EdgeDuration>(forward_duration * ratio);
forward_weight = to_alias<EdgeWeight>(from_alias<double>(forward_weight) * ratio);
forward_duration = to_alias<EdgeDuration>(from_alias<double>(forward_duration) * ratio);
}
if (data.reverse_segment_id.id != SPECIAL_SEGMENTID)
{
reverse_weight -= static_cast<EdgeWeight>(reverse_weight * ratio);
reverse_duration -= static_cast<EdgeDuration>(reverse_duration * ratio);
reverse_weight -= to_alias<EdgeWeight>(from_alias<double>(reverse_weight) * ratio);
reverse_duration -=
to_alias<EdgeDuration>(from_alias<double>(reverse_duration) * ratio);
}
// check phantom node segments validity
+13 -8
View File
@@ -95,8 +95,9 @@ inline LegGeometry assembleGeometry(const datafacade::BaseDataFacade &facade,
// the duration_of_turn/weight_of_turn value, which is 0 for
// non-preceeding-turn segments, but contains the turn value
// for segments before a turn.
(path_point.duration_until_turn - path_point.duration_of_turn) / 10.,
(path_point.weight_until_turn - path_point.weight_of_turn) /
from_alias<double>(path_point.duration_until_turn - path_point.duration_of_turn) /
10.,
from_alias<double>(path_point.weight_until_turn - path_point.weight_of_turn) /
facade.GetWeightMultiplier(),
path_point.datasource_id});
geometry.locations.push_back(coordinate);
@@ -121,14 +122,15 @@ inline LegGeometry assembleGeometry(const datafacade::BaseDataFacade &facade,
if (geometry.annotations.empty())
{
auto duration =
std::abs(
std::abs(from_alias<EdgeDuration::value_type>(
(reversed_target ? target_node.reverse_duration : target_node.forward_duration) -
(reversed_source ? source_node.reverse_duration : source_node.forward_duration)) /
(reversed_source ? source_node.reverse_duration : source_node.forward_duration))) /
10.;
BOOST_ASSERT(duration >= 0);
auto weight =
std::abs((reversed_target ? target_node.reverse_weight : target_node.forward_weight) -
(reversed_source ? source_node.reverse_weight : source_node.forward_weight)) /
std::abs(from_alias<EdgeWeight::value_type>(
(reversed_target ? target_node.reverse_weight : target_node.forward_weight) -
(reversed_source ? source_node.reverse_weight : source_node.forward_weight))) /
facade.GetWeightMultiplier();
BOOST_ASSERT(weight >= 0);
@@ -142,8 +144,11 @@ inline LegGeometry assembleGeometry(const datafacade::BaseDataFacade &facade,
{
geometry.annotations.emplace_back(LegGeometry::Annotation{
current_distance,
(reversed_target ? target_node.reverse_duration : target_node.forward_duration) / 10.,
(reversed_target ? target_node.reverse_weight : target_node.forward_weight) /
from_alias<double>(reversed_target ? target_node.reverse_duration
: target_node.forward_duration) /
10.,
from_alias<double>(reversed_target ? target_node.reverse_weight
: target_node.forward_weight) /
facade.GetWeightMultiplier(),
forward_datasources(target_node.fwd_segment_position)});
}
+10 -10
View File
@@ -34,7 +34,7 @@ namespace detail
const constexpr std::size_t MAX_USED_SEGMENTS = 2;
struct NamedSegment
{
EdgeWeight duration;
EdgeDuration duration;
std::uint32_t position;
std::uint32_t name_id;
};
@@ -88,7 +88,7 @@ std::array<std::uint32_t, SegmentNumber> summarizeRoute(const datafacade::BaseDa
target_traversed_in_reverse ? target_node.reverse_duration : target_node.forward_duration;
const auto target_node_id = target_traversed_in_reverse ? target_node.reverse_segment_id.id
: target_node.forward_segment_id.id;
if (target_duration > 1)
if (target_duration > EdgeDuration{1})
segments.push_back({target_duration, index++, facade.GetNameIndex(target_node_id)});
// this makes sure that the segment with the lowest position comes first
std::sort(
@@ -184,11 +184,11 @@ inline RouteLeg assembleLeg(const datafacade::BaseDataFacade &facade,
auto duration = std::accumulate(
route_data.begin(), route_data.end(), 0, [](const double sum, const PathData &data) {
return sum + data.duration_until_turn;
return sum + from_alias<double>(data.duration_until_turn);
});
auto weight = std::accumulate(
route_data.begin(), route_data.end(), 0, [](const double sum, const PathData &data) {
return sum + data.weight_until_turn;
return sum + from_alias<double>(data.weight_until_turn);
});
// s
@@ -212,14 +212,14 @@ inline RouteLeg assembleLeg(const datafacade::BaseDataFacade &facade,
// caputed by the phantom node. So we need to add the target duration here.
// On local segments, the target duration is already part of the duration, however.
duration = duration + target_duration;
weight = weight + target_weight;
duration = duration + from_alias<double>(target_duration);
weight = weight + from_alias<double>(target_weight);
if (route_data.empty())
{
weight -=
(target_traversed_in_reverse ? source_node.reverse_weight : source_node.forward_weight);
duration -= (target_traversed_in_reverse ? source_node.reverse_duration
: source_node.forward_duration);
weight -= from_alias<double>(target_traversed_in_reverse ? source_node.reverse_weight
: source_node.forward_weight);
duration -= from_alias<double>(target_traversed_in_reverse ? source_node.reverse_duration
: source_node.forward_duration);
// use rectified linear unit function to avoid negative duration values
// due to flooring errors in phantom snapping
duration = std::max(0, duration);
+18 -17
View File
@@ -52,7 +52,7 @@ inline std::vector<RouteStep> assembleSteps(const datafacade::BaseDataFacade &fa
const constexpr char *NO_ROTARY_NAME = "";
const EdgeWeight source_weight =
source_traversed_in_reverse ? source_node.reverse_weight : source_node.forward_weight;
const EdgeWeight source_duration =
const EdgeDuration source_duration =
source_traversed_in_reverse ? source_node.reverse_duration : source_node.forward_duration;
const auto source_node_id = source_traversed_in_reverse ? source_node.reverse_segment_id.id
: source_node.forward_segment_id.id;
@@ -61,7 +61,7 @@ inline std::vector<RouteStep> assembleSteps(const datafacade::BaseDataFacade &fa
const auto source_mode = facade.GetTravelMode(source_node_id);
auto source_classes = facade.GetClasses(facade.GetClassData(source_node_id));
const EdgeWeight target_duration =
const EdgeDuration target_duration =
target_traversed_in_reverse ? target_node.reverse_duration : target_node.forward_duration;
const EdgeWeight target_weight =
target_traversed_in_reverse ? target_node.reverse_weight : target_node.forward_weight;
@@ -103,8 +103,8 @@ inline std::vector<RouteStep> assembleSteps(const datafacade::BaseDataFacade &fa
// but a RouteStep is with regard to the segment after the turn.
// We need to skip the first segment because it is already covered by the
// initial start of a route
EdgeWeight segment_duration = 0;
EdgeWeight segment_weight = 0;
EdgeDuration segment_duration = {0};
EdgeWeight segment_weight = {0};
// some name changes are not announced in our processing. For these, we have to keep the
// first name on the segment
@@ -121,7 +121,7 @@ inline std::vector<RouteStep> assembleSteps(const datafacade::BaseDataFacade &fa
: osrm::guidance::TurnInstruction::NO_TURN();
if (turn_instruction.type != osrm::guidance::TurnType::NoTurn)
{
BOOST_ASSERT(segment_weight >= 0);
BOOST_ASSERT(segment_weight >= EdgeWeight{0});
const auto name = facade.GetNameForID(step_name_id);
const auto ref = facade.GetRefForID(step_name_id);
const auto pronunciation = facade.GetPronunciationForID(step_name_id);
@@ -147,9 +147,9 @@ inline std::vector<RouteStep> assembleSteps(const datafacade::BaseDataFacade &fa
exits.to_string(),
NO_ROTARY_NAME,
NO_ROTARY_NAME,
segment_duration / 10.,
from_alias<double>(segment_duration) / 10.,
distance,
segment_weight / weight_multiplier,
from_alias<double>(segment_weight) / weight_multiplier,
travel_mode,
maneuver,
leg_geometry.FrontIndex(segment_index),
@@ -228,16 +228,16 @@ inline std::vector<RouteStep> assembleSteps(const datafacade::BaseDataFacade &fa
WaypointType::None,
0};
segment_index++;
segment_duration = 0;
segment_weight = 0;
segment_duration = {0};
segment_weight = {0};
}
}
const auto distance = leg_geometry.segment_distances[segment_index];
const EdgeWeight duration = segment_duration + target_duration;
const EdgeDuration duration = segment_duration + target_duration;
const EdgeWeight weight = segment_weight + target_weight;
// intersections contain the classes of exiting road
intersection.classes = facade.GetClasses(facade.GetClassData(target_node_id));
BOOST_ASSERT(duration >= 0);
BOOST_ASSERT(duration >= EdgeDuration{0});
steps.push_back(RouteStep{leg_data[leg_data.size() - 1].from_edge_based_node,
step_name_id,
is_segregated,
@@ -248,9 +248,9 @@ inline std::vector<RouteStep> assembleSteps(const datafacade::BaseDataFacade &fa
facade.GetExitsForID(step_name_id).to_string(),
NO_ROTARY_NAME,
NO_ROTARY_NAME,
duration / 10.,
from_alias<double>(duration) / 10.,
distance,
weight / weight_multiplier,
from_alias<double>(weight) / weight_multiplier,
target_mode,
maneuver,
leg_geometry.FrontIndex(segment_index),
@@ -280,8 +280,9 @@ inline std::vector<RouteStep> assembleSteps(const datafacade::BaseDataFacade &fa
// use rectified linear unit function to avoid negative duration values
// due to flooring errors in phantom snapping
BOOST_ASSERT(target_duration >= source_duration || weight == 0);
const EdgeWeight duration = std::max(0, target_duration - source_duration);
BOOST_ASSERT(target_duration >= source_duration || weight == EdgeWeight{0});
const EdgeDuration duration =
std::max<EdgeDuration>({0}, target_duration - source_duration);
steps.push_back(RouteStep{source_node_id,
source_name_id,
@@ -293,9 +294,9 @@ inline std::vector<RouteStep> assembleSteps(const datafacade::BaseDataFacade &fa
facade.GetExitsForID(source_name_id).to_string(),
NO_ROTARY_NAME,
NO_ROTARY_NAME,
duration / 10.,
from_alias<double>(duration) / 10.,
leg_geometry.segment_distances[segment_index],
weight / weight_multiplier,
from_alias<double>(weight) / weight_multiplier,
source_mode,
maneuver,
leg_geometry.FrontIndex(segment_index),
+4 -4
View File
@@ -37,10 +37,10 @@ struct PathData
EdgeWeight weight_of_turn;
// duration that is traveled on the segment until the turn is reached,
// including a turn if the segment precedes one.
EdgeWeight duration_until_turn;
EdgeDuration duration_until_turn;
// If this segment immediately precedes a turn, then duration_of_turn
// will contain the duration of the turn. Otherwise it will be 0.
EdgeWeight duration_of_turn;
EdgeDuration duration_of_turn;
// Source of the speed value on this road segment
DatasourceID datasource_id;
// If segment precedes a turn, ID of the turn itself
@@ -63,9 +63,9 @@ struct InternalRouteResult
}
// Note: includes duration for turns, except for at start and end node.
EdgeWeight duration() const
EdgeDuration duration() const
{
EdgeWeight ret{0};
EdgeDuration ret{0};
for (const auto &leg : unpacked_path_segments)
for (const auto &segment : leg)
+14 -14
View File
@@ -48,12 +48,12 @@ struct PhantomNode
PhantomNode()
: forward_segment_id{SPECIAL_SEGMENTID, false}, reverse_segment_id{SPECIAL_SEGMENTID,
false},
forward_weight(INVALID_EDGE_WEIGHT), reverse_weight(INVALID_EDGE_WEIGHT),
forward_weight_offset(0), reverse_weight_offset(0),
forward_weight(INVALID_EDGE_WEIGHT),
reverse_weight(INVALID_EDGE_WEIGHT), forward_weight_offset{0}, reverse_weight_offset{0},
forward_distance(INVALID_EDGE_DISTANCE), reverse_distance(INVALID_EDGE_DISTANCE),
forward_distance_offset(0), reverse_distance_offset(0),
forward_distance_offset{0}, reverse_distance_offset{0},
forward_duration(MAXIMAL_EDGE_DURATION), reverse_duration(MAXIMAL_EDGE_DURATION),
forward_duration_offset(0), reverse_duration_offset(0),
forward_duration_offset{0}, reverse_duration_offset{0},
component({INVALID_COMPONENTID, 0}),
fwd_segment_position(0), is_valid_forward_source{false}, is_valid_forward_target{false},
is_valid_reverse_source{false}, is_valid_reverse_target{false}, bearing(0)
@@ -73,13 +73,13 @@ struct PhantomNode
return reverse_weight_offset + reverse_weight;
}
EdgeWeight GetForwardDuration() const
EdgeDuration GetForwardDuration() const
{
BOOST_ASSERT(forward_segment_id.enabled);
return forward_duration + forward_duration_offset;
}
EdgeWeight GetReverseDuration() const
EdgeDuration GetReverseDuration() const
{
BOOST_ASSERT(reverse_segment_id.enabled);
return reverse_duration + reverse_duration_offset;
@@ -168,10 +168,10 @@ struct PhantomNode
EdgeDistance reverse_distance,
EdgeDistance forward_distance_offset,
EdgeDistance reverse_distance_offset,
EdgeWeight forward_duration,
EdgeWeight reverse_duration,
EdgeWeight forward_duration_offset,
EdgeWeight reverse_duration_offset,
EdgeDuration forward_duration,
EdgeDuration reverse_duration,
EdgeDuration forward_duration_offset,
EdgeDuration reverse_duration_offset,
bool is_valid_forward_source,
bool is_valid_forward_target,
bool is_valid_reverse_source,
@@ -206,10 +206,10 @@ struct PhantomNode
EdgeDistance reverse_distance;
EdgeDistance forward_distance_offset; // TODO: try to remove -> requires path unpacking changes
EdgeDistance reverse_distance_offset; // TODO: try to remove -> requires path unpacking changes
EdgeWeight forward_duration;
EdgeWeight reverse_duration;
EdgeWeight forward_duration_offset; // TODO: try to remove -> requires path unpacking changes
EdgeWeight reverse_duration_offset; // TODO: try to remove -> requires path unpacking changes
EdgeDuration forward_duration;
EdgeDuration reverse_duration;
EdgeDuration forward_duration_offset; // TODO: try to remove -> requires path unpacking changes
EdgeDuration reverse_duration_offset; // TODO: try to remove -> requires path unpacking changes
ComponentID component;
util::Coordinate location; // this is the coordinate of x
@@ -43,14 +43,14 @@ void insertSourceInForwardHeap(Heap &forward_heap, const PhantomNode &source)
if (source.IsValidForwardSource())
{
forward_heap.Insert(source.forward_segment_id.id,
-source.GetForwardWeightPlusOffset(),
EdgeWeight{0} - source.GetForwardWeightPlusOffset(),
source.forward_segment_id.id);
}
if (source.IsValidReverseSource())
{
forward_heap.Insert(source.reverse_segment_id.id,
-source.GetReverseWeightPlusOffset(),
EdgeWeight{0} - source.GetReverseWeightPlusOffset(),
source.reverse_segment_id.id);
}
}
@@ -127,18 +127,18 @@ void insertSourceInHeap(ManyToManyQueryHeap &heap, const PhantomNodeCandidates &
if (phantom_node.IsValidForwardSource())
{
heap.Insert(phantom_node.forward_segment_id.id,
-phantom_node.GetForwardWeightPlusOffset(),
EdgeWeight{0} - phantom_node.GetForwardWeightPlusOffset(),
{phantom_node.forward_segment_id.id,
-phantom_node.GetForwardDuration(),
-phantom_node.GetForwardDistance()});
EdgeDuration{0} - phantom_node.GetForwardDuration(),
EdgeDistance{0} - phantom_node.GetForwardDistance()});
}
if (phantom_node.IsValidReverseSource())
{
heap.Insert(phantom_node.reverse_segment_id.id,
-phantom_node.GetReverseWeightPlusOffset(),
EdgeWeight{0} - phantom_node.GetReverseWeightPlusOffset(),
{phantom_node.reverse_segment_id.id,
-phantom_node.GetReverseDuration(),
-phantom_node.GetReverseDistance()});
EdgeDuration{0} - phantom_node.GetReverseDuration(),
EdgeDistance{0} - phantom_node.GetReverseDistance()});
}
}
}
@@ -251,25 +251,24 @@ void annotatePath(const FacadeT &facade,
BOOST_ASSERT(start_index < end_index);
for (std::size_t segment_idx = start_index; segment_idx < end_index; ++segment_idx)
{
unpacked_path.push_back(
PathData{node_id,
id_vector[segment_idx + 1],
static_cast<EdgeWeight>(weight_vector[segment_idx]),
0,
static_cast<EdgeDuration>(duration_vector[segment_idx]),
0,
datasource_vector[segment_idx],
boost::none});
unpacked_path.push_back(PathData{node_id,
id_vector[segment_idx + 1],
alias_cast<EdgeWeight>(weight_vector[segment_idx]),
{0},
alias_cast<EdgeDuration>(duration_vector[segment_idx]),
{0},
datasource_vector[segment_idx],
boost::none});
}
BOOST_ASSERT(!unpacked_path.empty());
const auto turn_duration = facade.GetDurationPenaltyForEdgeID(turn_id);
const auto turn_weight = facade.GetWeightPenaltyForEdgeID(turn_id);
unpacked_path.back().duration_until_turn += turn_duration;
unpacked_path.back().duration_of_turn = turn_duration;
unpacked_path.back().weight_until_turn += turn_weight;
unpacked_path.back().weight_of_turn = turn_weight;
unpacked_path.back().duration_until_turn += alias_cast<EdgeDuration>(turn_duration);
unpacked_path.back().duration_of_turn = alias_cast<EdgeDuration>(turn_duration);
unpacked_path.back().weight_until_turn += alias_cast<EdgeWeight>(turn_weight);
unpacked_path.back().weight_of_turn = alias_cast<EdgeWeight>(turn_weight);
unpacked_path.back().turn_edge = turn_id;
}
@@ -311,10 +310,10 @@ void annotatePath(const FacadeT &facade,
unpacked_path.push_back(
PathData{target_node_id,
id_vector[start_index < end_index ? segment_idx + 1 : segment_idx - 1],
static_cast<EdgeWeight>(weight_vector[segment_idx]),
0,
static_cast<EdgeDuration>(duration_vector[segment_idx]),
0,
alias_cast<EdgeWeight>(weight_vector[segment_idx]),
{0},
alias_cast<EdgeDuration>(duration_vector[segment_idx]),
{0},
datasource_vector[segment_idx],
boost::none});
}
@@ -341,9 +340,9 @@ void annotatePath(const FacadeT &facade,
// node to the first turn would be the same as from end to end of a segment,
// which is obviously incorrect and not ideal...
unpacked_path.front().weight_until_turn =
std::max(unpacked_path.front().weight_until_turn - source_weight, 0);
std::max(unpacked_path.front().weight_until_turn - source_weight, {0});
unpacked_path.front().duration_until_turn =
std::max(unpacked_path.front().duration_until_turn - source_duration, 0);
std::max(unpacked_path.front().duration_until_turn - source_duration, {0});
}
}
@@ -410,7 +409,7 @@ template <typename FacadeT> EdgeDistance computeEdgeDistance(const FacadeT &faca
{
const auto geometry_index = facade.GetGeometryIndex(node_id);
EdgeDistance total_distance = 0.0;
EdgeDistance total_distance = {0};
auto geometry_range = facade.GetUncompressedForwardGeometry(geometry_index.id);
for (auto current = geometry_range.begin(); current < geometry_range.end() - 1; ++current)
@@ -34,7 +34,7 @@ bool stallAtNode(const DataFacade<Algorithm> &facade,
{
const NodeID to = facade.GetTarget(edge);
const EdgeWeight edge_weight = data.weight;
BOOST_ASSERT_MSG(edge_weight > 0, "edge_weight invalid");
BOOST_ASSERT_MSG(edge_weight > EdgeWeight{0}, "edge_weight invalid");
const auto toHeapNode = query_heap.GetHeapNodeIfWasInserted(to);
if (toHeapNode)
{
@@ -61,7 +61,7 @@ void relaxOutgoingEdges(const DataFacade<Algorithm> &facade,
const NodeID to = facade.GetTarget(edge);
const EdgeWeight edge_weight = data.weight;
BOOST_ASSERT_MSG(edge_weight > 0, "edge_weight invalid");
BOOST_ASSERT_MSG(edge_weight > EdgeWeight{0}, "edge_weight invalid");
const EdgeWeight to_weight = heapNode.weight + edge_weight;
const auto toHeapNode = heap.GetHeapNodeIfWasInserted(to);
@@ -135,7 +135,7 @@ void routingStep(const DataFacade<Algorithm> &facade,
force_loop(force_loop_reverse_nodes, heapNode) ||
// in this case we are looking at a bi-directional way where the source
// and target phantom are on the same edge based node
new_weight < 0)
new_weight < EdgeWeight{0})
{
// check whether there is a loop present at the node
for (const auto edge : facade.GetAdjacentEdgeRange(heapNode.node))
@@ -148,7 +148,7 @@ void routingStep(const DataFacade<Algorithm> &facade,
{
const EdgeWeight edge_weight = data.weight;
const EdgeWeight loop_weight = new_weight + edge_weight;
if (loop_weight >= 0 && loop_weight < upper_bound)
if (loop_weight >= EdgeWeight{0} && loop_weight < upper_bound)
{
middle_node_id = heapNode.node;
upper_bound = loop_weight;
@@ -159,7 +159,7 @@ void routingStep(const DataFacade<Algorithm> &facade,
}
else
{
BOOST_ASSERT(new_weight >= 0);
BOOST_ASSERT(new_weight >= EdgeWeight{0});
middle_node_id = heapNode.node;
upper_bound = new_weight;
@@ -169,7 +169,7 @@ void routingStep(const DataFacade<Algorithm> &facade,
// make sure we don't terminate too early if we initialize the weight
// for the nodes in the forward heap with the forward/reverse offset
BOOST_ASSERT(min_edge_offset <= 0);
BOOST_ASSERT(min_edge_offset <= EdgeWeight{0});
if (heapNode.weight + min_edge_offset > upper_bound)
{
forward_heap.DeleteAll();
@@ -185,31 +185,6 @@ void routingStep(const DataFacade<Algorithm> &facade,
relaxOutgoingEdges<DIRECTION>(facade, heapNode, forward_heap);
}
template <bool UseDuration>
std::tuple<EdgeWeight, EdgeDistance> getLoopWeight(const DataFacade<Algorithm> &facade, NodeID node)
{
EdgeWeight loop_weight = UseDuration ? MAXIMAL_EDGE_DURATION : INVALID_EDGE_WEIGHT;
EdgeDistance loop_distance = MAXIMAL_EDGE_DISTANCE;
for (auto edge : facade.GetAdjacentEdgeRange(node))
{
const auto &data = facade.GetEdgeData(edge);
if (data.forward)
{
const NodeID to = facade.GetTarget(edge);
if (to == node)
{
const auto value = UseDuration ? data.duration : data.weight;
if (value < loop_weight)
{
loop_weight = value;
loop_distance = data.distance;
}
}
}
}
return std::make_tuple(loop_weight, loop_distance);
}
/**
* Given a sequence of connected `NodeID`s in the CH graph, performs a depth-first unpacking of
* the shortcut
@@ -301,7 +276,7 @@ EdgeDistance calculateEBGNodeAnnotations(const DataFacade<Algorithm> &facade,
// Make sure we have at least something to unpack
if (packed_path_begin == packed_path_end ||
std::distance(packed_path_begin, packed_path_end) <= 1)
return 0;
return {0};
std::stack<std::tuple<NodeID, NodeID, bool>> recursion_stack;
std::stack<EdgeDistance> distance_stack;
@@ -383,7 +358,7 @@ EdgeDistance calculateEBGNodeAnnotations(const DataFacade<Algorithm> &facade,
}
}
EdgeDistance total_distance = 0;
EdgeDistance total_distance = {0};
while (!distance_stack.empty())
{
total_distance += distance_stack.top();
@@ -505,8 +480,48 @@ double getNetworkDistance(SearchEngineData<Algorithm> &engine_working_data,
SearchEngineData<Algorithm>::QueryHeap &reverse_heap,
const PhantomNode &source_phantom,
const PhantomNode &target_phantom,
int duration_upper_bound = INVALID_EDGE_WEIGHT);
EdgeWeight duration_upper_bound = INVALID_EDGE_WEIGHT);
template <typename EdgeMetric>
std::tuple<EdgeMetric, EdgeDistance> getLoopMetric(const DataFacade<Algorithm> &facade, NodeID node)
{
EdgeMetric loop_metric;
if constexpr (std::is_same<EdgeMetric, EdgeDuration>::value)
{
loop_metric = INVALID_EDGE_DURATION;
}
else
{
loop_metric = INVALID_EDGE_WEIGHT;
}
EdgeDistance loop_distance = MAXIMAL_EDGE_DISTANCE;
for (auto edge : facade.GetAdjacentEdgeRange(node))
{
const auto &data = facade.GetEdgeData(edge);
if (data.forward)
{
const NodeID to = facade.GetTarget(edge);
if (to == node)
{
EdgeMetric value;
if constexpr (std::is_same<EdgeMetric, EdgeDuration>::value)
{
value = to_alias<EdgeDuration>(data.duration);
}
else
{
value = data.weight;
}
if (value < loop_metric)
{
loop_metric = value;
loop_distance = data.distance;
}
}
}
}
return std::make_tuple(loop_metric, loop_distance);
}
} // namespace ch
} // namespace routing_algorithms
} // namespace engine
@@ -363,7 +363,8 @@ void relaxOutgoingEdges(const DataFacade<Algorithm> &facade,
// TODO: BOOST_ASSERT(edge_data.weight == node_weight + turn_penalty);
const EdgeWeight to_weight = heapNode.weight + node_weight + turn_penalty;
const EdgeWeight to_weight =
heapNode.weight + node_weight + alias_cast<EdgeWeight>(turn_penalty);
const auto toHeapNode = forward_heap.GetHeapNodeIfWasInserted(to);
if (!toHeapNode)
@@ -410,7 +411,7 @@ void routingStep(const DataFacade<Algorithm> &facade,
// MLD uses loops forcing only to prune single node paths in forward and/or
// backward direction (there is no need to force loops in MLD but in CH)
if (!force_loop(force_loop_forward_nodes, heapNode) &&
!force_loop(force_loop_reverse_nodes, heapNode) && (path_weight >= 0) &&
!force_loop(force_loop_reverse_nodes, heapNode) && (path_weight >= EdgeWeight{0}) &&
(path_weight < path_upper_bound))
{
middle_node = heapNode.node;
@@ -529,8 +530,8 @@ UnpackedPath search(SearchEngineData<Algorithm> &engine_working_data,
// 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});
// TODO: when structured bindings will be allowed change to
// auto [subpath_weight, subpath_source, subpath_target, subpath] = ...
@@ -292,7 +292,7 @@ shortestPathWithWaypointUTurns(SearchEngineData<Algorithm> &engine_working_data,
const std::vector<PhantomNodeCandidates> &waypoint_candidates)
{
EdgeWeight total_weight = 0;
EdgeWeight total_weight = {0};
std::vector<NodeID> total_packed_path;
std::vector<std::size_t> packed_leg_begin;
@@ -467,8 +467,8 @@ struct route_state
route_state(const PhantomNodeCandidates &init_candidates)
: current_leg(0), previous_leg_path_offset(0)
{
last.total_weight_to_forward.resize(init_candidates.size(), 0);
last.total_weight_to_reverse.resize(init_candidates.size(), 0);
last.total_weight_to_forward.resize(init_candidates.size(), {0});
last.total_weight_to_reverse.resize(init_candidates.size(), {0});
// Initialize routability from source validity.
std::transform(
init_candidates.begin(),
@@ -23,7 +23,7 @@ struct TurnData final
const int in_angle;
const int turn_angle;
const EdgeWeight weight;
const EdgeWeight duration;
const EdgeDuration duration;
const guidance::TurnInstruction turn_instruction;
};
+5 -5
View File
@@ -29,9 +29,9 @@ struct HeapData
struct ManyToManyHeapData : HeapData
{
EdgeWeight duration;
EdgeDuration duration;
EdgeDistance distance;
ManyToManyHeapData(NodeID p, EdgeWeight duration, EdgeDistance distance)
ManyToManyHeapData(NodeID p, EdgeDuration duration, EdgeDistance distance)
: HeapData(p), duration(duration), distance(distance)
{
}
@@ -78,15 +78,15 @@ struct MultiLayerDijkstraHeapData
struct ManyToManyMultiLayerDijkstraHeapData : MultiLayerDijkstraHeapData
{
EdgeWeight duration;
EdgeDuration duration;
EdgeDistance distance;
ManyToManyMultiLayerDijkstraHeapData(NodeID p, EdgeWeight duration, EdgeDistance distance)
ManyToManyMultiLayerDijkstraHeapData(NodeID p, EdgeDuration duration, EdgeDistance distance)
: MultiLayerDijkstraHeapData(p), duration(duration), distance(distance)
{
}
ManyToManyMultiLayerDijkstraHeapData(NodeID p,
bool from,
EdgeWeight duration,
EdgeDuration duration,
EdgeDistance distance)
: MultiLayerDijkstraHeapData(p, from), duration(duration), distance(distance)
{
+14 -13
View File
@@ -23,12 +23,12 @@ namespace trip
{
// computes the distance of a given permutation
inline EdgeWeight ReturnDistance(const util::DistTableWrapper<EdgeWeight> &dist_table,
const std::vector<NodeID> &location_order,
const EdgeWeight min_route_dist,
const std::size_t number_of_locations)
inline EdgeDuration ReturnDistance(const util::DistTableWrapper<EdgeDuration> &dist_table,
const std::vector<NodeID> &location_order,
const EdgeDuration min_route_dist,
const std::size_t number_of_locations)
{
EdgeWeight route_dist = 0;
EdgeDuration route_dist = {0};
std::size_t current_index = 0;
while (current_index < location_order.size() && (route_dist < min_route_dist))
{
@@ -36,12 +36,13 @@ inline EdgeWeight ReturnDistance(const util::DistTableWrapper<EdgeWeight> &dist_
std::size_t next_index = (current_index + 1) % number_of_locations;
auto edge_weight = dist_table(location_order[current_index], location_order[next_index]);
// If the edge_weight is very large (INVALID_EDGE_WEIGHT) then the algorithm will not choose
// this edge in final minimal path. So instead of computing all the permutations after this
// large edge, discard this edge right here and don't consider the path after this edge.
if (edge_weight == INVALID_EDGE_WEIGHT)
// If the edge_weight is very large (INVALID_EDGE_DURATION) then the algorithm will not
// choose this edge in final minimal path. So instead of computing all the permutations
// after this large edge, discard this edge right here and don't consider the path after
// this edge.
if (edge_weight == INVALID_EDGE_DURATION)
{
return INVALID_EDGE_WEIGHT;
return INVALID_EDGE_DURATION;
}
else
{
@@ -50,7 +51,7 @@ inline EdgeWeight ReturnDistance(const util::DistTableWrapper<EdgeWeight> &dist_
// This boost assert should not be reached if TFSE table
BOOST_ASSERT_MSG(dist_table(location_order[current_index], location_order[next_index]) !=
INVALID_EDGE_WEIGHT,
INVALID_EDGE_DURATION,
"invalid route found");
++current_index;
}
@@ -60,14 +61,14 @@ inline EdgeWeight ReturnDistance(const util::DistTableWrapper<EdgeWeight> &dist_
// computes the route by computing all permutations and selecting the shortest
inline std::vector<NodeID> BruteForceTrip(const std::size_t number_of_locations,
const util::DistTableWrapper<EdgeWeight> &dist_table)
const util::DistTableWrapper<EdgeDuration> &dist_table)
{
// set initial order in which nodes are visited to 0, 1, 2, 3, ...
std::vector<NodeID> node_order(number_of_locations);
std::iota(std::begin(node_order), std::end(node_order), 0);
std::vector<NodeID> route = node_order;
EdgeWeight min_route_dist = INVALID_EDGE_WEIGHT;
EdgeDuration min_route_dist = INVALID_EDGE_DURATION;
// check length of all possible permutation of the component ids
BOOST_ASSERT_MSG(node_order.size() > 0, "no order permutation given");
+13 -12
View File
@@ -23,15 +23,15 @@ namespace trip
// given a route and a new location, find the best place of insertion and
// check the distance of roundtrip when the new location is additionally visited
using NodeIDIter = std::vector<NodeID>::iterator;
inline std::pair<EdgeWeight, NodeIDIter>
inline std::pair<EdgeDuration, NodeIDIter>
GetShortestRoundTrip(const NodeID new_loc,
const util::DistTableWrapper<EdgeWeight> &dist_table,
const util::DistTableWrapper<EdgeDuration> &dist_table,
const std::size_t number_of_locations,
std::vector<NodeID> &route)
{
(void)number_of_locations; // unused
auto min_trip_distance = INVALID_EDGE_WEIGHT;
auto min_trip_distance = INVALID_EDGE_DURATION;
NodeIDIter next_insert_point_candidate;
// for all nodes in the current trip find the best insertion resulting in the shortest path
@@ -48,10 +48,11 @@ GetShortestRoundTrip(const NodeID new_loc,
const auto dist_from = dist_table(*from_node, new_loc);
const auto dist_to = dist_table(new_loc, *to_node);
// If the edge_weight is very large (INVALID_EDGE_WEIGHT) then the algorithm will not choose
// this edge in final minimal path. So instead of computing all the permutations after this
// large edge, discard this edge right here and don't consider the path after this edge.
if (dist_from == INVALID_EDGE_WEIGHT || dist_to == INVALID_EDGE_WEIGHT)
// If the edge_weight is very large (INVALID_EDGE_DURATION) then the algorithm will not
// choose this edge in final minimal path. So instead of computing all the permutations
// after this large edge, discard this edge right here and don't consider the path after
// this edge.
if (dist_from == INVALID_EDGE_DURATION || dist_to == INVALID_EDGE_DURATION)
continue;
const auto trip_dist = dist_from + dist_to - dist_table(*from_node, *to_node);
@@ -71,14 +72,14 @@ GetShortestRoundTrip(const NodeID new_loc,
next_insert_point_candidate = to_node;
}
}
BOOST_ASSERT_MSG(min_trip_distance != INVALID_EDGE_WEIGHT, "trip has invalid edge weight");
BOOST_ASSERT_MSG(min_trip_distance != INVALID_EDGE_DURATION, "trip has invalid edge weight");
return std::make_pair(min_trip_distance, next_insert_point_candidate);
}
// given two initial start nodes, find a roundtrip route using the farthest insertion algorithm
inline std::vector<NodeID> FindRoute(const std::size_t &number_of_locations,
const util::DistTableWrapper<EdgeWeight> &dist_table,
const util::DistTableWrapper<EdgeDuration> &dist_table,
const NodeID &start1,
const NodeID &start2)
{
@@ -99,7 +100,7 @@ inline std::vector<NodeID> FindRoute(const std::size_t &number_of_locations,
// two nodes are already in the initial start trip, so we need to add all other nodes
for (std::size_t added_nodes = 2; added_nodes < number_of_locations; ++added_nodes)
{
auto farthest_distance = std::numeric_limits<int>::min();
auto farthest_distance = EdgeDuration{std::numeric_limits<EdgeDuration::value_type>::min()};
auto next_node = -1;
NodeIDIter next_insert_point;
@@ -112,7 +113,7 @@ inline std::vector<NodeID> FindRoute(const std::size_t &number_of_locations,
const auto insert_candidate =
GetShortestRoundTrip(id, dist_table, number_of_locations, route);
BOOST_ASSERT_MSG(insert_candidate.first != INVALID_EDGE_WEIGHT,
BOOST_ASSERT_MSG(insert_candidate.first != INVALID_EDGE_DURATION,
"shortest round trip is invalid");
// add the location to the current trip such that it results in the shortest total
@@ -137,7 +138,7 @@ inline std::vector<NodeID> FindRoute(const std::size_t &number_of_locations,
inline std::vector<NodeID>
FarthestInsertionTrip(const std::size_t number_of_locations,
const util::DistTableWrapper<EdgeWeight> &dist_table)
const util::DistTableWrapper<EdgeDuration> &dist_table)
{
//////////////////////////////////////////////////////////////////////////////////////////////////
// START FARTHEST INSERTION HERE