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:
@@ -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));
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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)});
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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),
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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;
|
||||
};
|
||||
|
||||
|
||||
@@ -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)
|
||||
{
|
||||
|
||||
@@ -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");
|
||||
|
||||
@@ -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
|
||||
|
||||
Reference in New Issue
Block a user