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:
@@ -78,7 +78,8 @@ int Contractor::Run()
|
||||
// Convert node weights for oneway streets to INVALID_EDGE_WEIGHT
|
||||
for (auto &weight : node_weights)
|
||||
{
|
||||
weight = (weight & 0x80000000) ? INVALID_EDGE_WEIGHT : weight;
|
||||
weight = (from_alias<EdgeWeight::value_type>(weight) & 0x80000000) ? INVALID_EDGE_WEIGHT
|
||||
: weight;
|
||||
}
|
||||
|
||||
// Contracting the edge-expanded graph
|
||||
|
||||
@@ -170,8 +170,8 @@ void ContractNode(ContractorThreadData *data,
|
||||
}
|
||||
|
||||
heap.Clear();
|
||||
heap.Insert(source, 0, ContractorHeapData{});
|
||||
EdgeWeight max_weight = 0;
|
||||
heap.Insert(source, {0}, ContractorHeapData{});
|
||||
EdgeWeight max_weight = {0};
|
||||
unsigned number_of_targets = 0;
|
||||
|
||||
for (auto out_edge : graph.GetAdjacentEdgeRange(node))
|
||||
@@ -199,7 +199,7 @@ void ContractNode(ContractorThreadData *data,
|
||||
// CAREFUL: This only works due to the independent node-setting. This
|
||||
// guarantees that source is not connected to another node that is
|
||||
// contracted
|
||||
node_weights[source] = path_weight + 1;
|
||||
node_weights[source] = path_weight + EdgeWeight{1};
|
||||
BOOST_ASSERT(stats != nullptr);
|
||||
stats->edges_added_count += 2;
|
||||
stats->original_edges_added_count +=
|
||||
|
||||
@@ -133,7 +133,8 @@ int Customizer::Run(const CustomizationConfig &config)
|
||||
auto graph = LoadAndUpdateEdgeExpandedGraph(
|
||||
config, mlp, node_weights, node_durations, node_distances, connectivity_checksum);
|
||||
BOOST_ASSERT(graph.GetNumberOfNodes() == node_weights.size());
|
||||
std::for_each(node_weights.begin(), node_weights.end(), [](auto &w) { w &= 0x7fffffff; });
|
||||
std::for_each(
|
||||
node_weights.begin(), node_weights.end(), [](auto &w) { w &= EdgeWeight{0x7fffffff}; });
|
||||
util::Log() << "Loaded edge based graph: " << graph.GetNumberOfEdges() << " edges, "
|
||||
<< graph.GetNumberOfNodes() << " nodes";
|
||||
|
||||
|
||||
@@ -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
@@ -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
@@ -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 ¤t_weight = weights_table[row_index * number_of_targets + column_index];
|
||||
|
||||
EdgeDistance nulldistance = 0;
|
||||
EdgeDistance nulldistance = {0};
|
||||
|
||||
auto ¤t_duration = durations_table[row_index * number_of_targets + column_index];
|
||||
auto ¤t_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 ¤t_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 ¤t_weight = weights_table[location];
|
||||
auto ¤t_duration = durations_table[location];
|
||||
|
||||
EdgeDistance nulldistance = 0;
|
||||
EdgeDistance nulldistance = {0};
|
||||
auto ¤t_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()))
|
||||
|
||||
@@ -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});
|
||||
}
|
||||
}
|
||||
|
||||
@@ -74,24 +74,26 @@ unsigned CompressedEdgeContainer::GetZippedPositionForReverseID(const EdgeID edg
|
||||
return map_iterator->second;
|
||||
}
|
||||
|
||||
SegmentWeight CompressedEdgeContainer::ClipWeight(const SegmentWeight weight)
|
||||
SegmentWeight CompressedEdgeContainer::ClipWeight(const EdgeWeight weight)
|
||||
{
|
||||
if (weight >= INVALID_SEGMENT_WEIGHT)
|
||||
SegmentWeight seg_weight = alias_cast<SegmentWeight>(weight);
|
||||
if (seg_weight >= INVALID_SEGMENT_WEIGHT)
|
||||
{
|
||||
clipped_weights++;
|
||||
return MAX_SEGMENT_WEIGHT;
|
||||
}
|
||||
return weight;
|
||||
return seg_weight;
|
||||
}
|
||||
|
||||
SegmentDuration CompressedEdgeContainer::ClipDuration(const SegmentDuration duration)
|
||||
SegmentDuration CompressedEdgeContainer::ClipDuration(const EdgeDuration duration)
|
||||
{
|
||||
if (duration >= INVALID_SEGMENT_DURATION)
|
||||
SegmentDuration seg_duration = alias_cast<SegmentDuration>(duration);
|
||||
if (seg_duration >= INVALID_SEGMENT_DURATION)
|
||||
{
|
||||
clipped_weights++;
|
||||
return MAX_SEGMENT_DURATION;
|
||||
}
|
||||
return duration;
|
||||
return seg_duration;
|
||||
}
|
||||
|
||||
// Adds info for a compressed edge to the container. edge_id_2
|
||||
@@ -119,8 +121,8 @@ void CompressedEdgeContainer::CompressEdge(const EdgeID edge_id_1,
|
||||
BOOST_ASSERT(SPECIAL_EDGEID != edge_id_2);
|
||||
BOOST_ASSERT(SPECIAL_NODEID != via_node_id);
|
||||
BOOST_ASSERT(SPECIAL_NODEID != target_node_id);
|
||||
BOOST_ASSERT(INVALID_SEGMENT_WEIGHT != weight1);
|
||||
BOOST_ASSERT(INVALID_SEGMENT_WEIGHT != weight2);
|
||||
BOOST_ASSERT(INVALID_EDGE_WEIGHT != weight1);
|
||||
BOOST_ASSERT(INVALID_EDGE_WEIGHT != weight2);
|
||||
|
||||
// append list of removed edge_id plus via node to surviving edge id:
|
||||
// <surv_1, .. , surv_n, via_node_id, rem_1, .. rem_n
|
||||
@@ -207,13 +209,14 @@ void CompressedEdgeContainer::CompressEdge(const EdgeID edge_id_1,
|
||||
|
||||
void CompressedEdgeContainer::AddUncompressedEdge(const EdgeID edge_id,
|
||||
const NodeID target_node_id,
|
||||
const SegmentWeight weight,
|
||||
const SegmentDuration duration)
|
||||
const EdgeWeight weight,
|
||||
const EdgeDuration duration)
|
||||
{
|
||||
// remove super-trivial geometries
|
||||
BOOST_ASSERT(SPECIAL_EDGEID != edge_id);
|
||||
BOOST_ASSERT(SPECIAL_NODEID != target_node_id);
|
||||
BOOST_ASSERT(INVALID_EDGE_WEIGHT != weight);
|
||||
BOOST_ASSERT(INVALID_EDGE_DURATION != duration);
|
||||
|
||||
// Add via node id. List is created if it does not exist
|
||||
if (!HasEntryForID(edge_id))
|
||||
@@ -336,12 +339,12 @@ void CompressedEdgeContainer::PrintStatistics() const
|
||||
if (clipped_weights > 0)
|
||||
{
|
||||
util::Log(logWARNING) << "Clipped " << clipped_weights << " segment weights to "
|
||||
<< (INVALID_SEGMENT_WEIGHT - 1);
|
||||
<< MAX_SEGMENT_WEIGHT;
|
||||
}
|
||||
if (clipped_durations > 0)
|
||||
{
|
||||
util::Log(logWARNING) << "Clipped " << clipped_durations << " segment durations to "
|
||||
<< (INVALID_SEGMENT_DURATION - 1);
|
||||
<< MAX_SEGMENT_DURATION;
|
||||
}
|
||||
|
||||
util::Log() << "Geometry successfully removed:"
|
||||
|
||||
@@ -94,7 +94,7 @@ void EdgeBasedGraphFactory::GetEdgeBasedNodeWeights(std::vector<EdgeWeight> &out
|
||||
}
|
||||
|
||||
void EdgeBasedGraphFactory::GetEdgeBasedNodeDurations(
|
||||
std::vector<EdgeWeight> &output_node_durations)
|
||||
std::vector<EdgeDuration> &output_node_durations)
|
||||
{
|
||||
using std::swap; // Koenig swap
|
||||
swap(m_edge_based_node_durations, output_node_durations);
|
||||
@@ -147,7 +147,8 @@ NBGToEBG EdgeBasedGraphFactory::InsertEdgeBasedNode(const NodeID node_u, const N
|
||||
// * in other cases node weights must be masked with 0x7fffffff to clear MSB
|
||||
if (nbe_to_ebn_mapping[edge_id_1] != SPECIAL_NODEID &&
|
||||
nbe_to_ebn_mapping[edge_id_2] == SPECIAL_NODEID)
|
||||
m_edge_based_node_weights[nbe_to_ebn_mapping[edge_id_1]] |= 0x80000000;
|
||||
m_edge_based_node_weights[nbe_to_ebn_mapping[edge_id_1]] |=
|
||||
EdgeWeight{static_cast<EdgeWeight::value_type>(0x80000000)};
|
||||
|
||||
BOOST_ASSERT(m_compressed_edge_container.HasEntryForID(edge_id_1) ==
|
||||
m_compressed_edge_container.HasEntryForID(edge_id_2));
|
||||
@@ -400,7 +401,7 @@ EdgeBasedGraphFactory::GenerateEdgeExpandedNodes(const WayRestrictionMap &way_re
|
||||
segregated_edges.count(eid) > 0;
|
||||
|
||||
const auto ebn_weight = m_edge_based_node_weights[nbe_to_ebn_mapping[eid]];
|
||||
BOOST_ASSERT((ebn_weight & 0x7fffffff) == edge_data.weight);
|
||||
BOOST_ASSERT((ebn_weight & EdgeWeight{0x7fffffff}) == edge_data.weight);
|
||||
m_edge_based_node_weights.push_back(ebn_weight);
|
||||
m_edge_based_node_durations.push_back(
|
||||
m_edge_based_node_durations[nbe_to_ebn_mapping[eid]]);
|
||||
@@ -663,7 +664,7 @@ void EdgeBasedGraphFactory::GenerateEdgeExpandedEdges(
|
||||
edge_data1.flags.highway_turn_classification,
|
||||
edge_data1.flags.access_turn_classification,
|
||||
((double)intersection::findEdgeLength(edge_geometries, node_based_edge_from) /
|
||||
edge_data1.duration) *
|
||||
from_alias<double>(edge_data1.duration)) *
|
||||
36,
|
||||
edge_data1.flags.road_classification.GetPriority(),
|
||||
// target info
|
||||
@@ -675,7 +676,7 @@ void EdgeBasedGraphFactory::GenerateEdgeExpandedEdges(
|
||||
edge_data2.flags.highway_turn_classification,
|
||||
edge_data2.flags.access_turn_classification,
|
||||
((double)intersection::findEdgeLength(edge_geometries, node_based_edge_to) /
|
||||
edge_data2.duration) *
|
||||
from_alias<double>(edge_data2.duration)) *
|
||||
36,
|
||||
edge_data2.flags.road_classification.GetPriority(),
|
||||
// connected roads
|
||||
@@ -686,17 +687,18 @@ void EdgeBasedGraphFactory::GenerateEdgeExpandedEdges(
|
||||
|
||||
// turn penalties are limited to [-2^15, 2^15) which roughly translates to 54 minutes
|
||||
// and fits signed 16bit deci-seconds
|
||||
auto weight_penalty =
|
||||
boost::numeric_cast<TurnPenalty>(extracted_turn.weight * weight_multiplier);
|
||||
auto duration_penalty = boost::numeric_cast<TurnPenalty>(extracted_turn.duration * 10.);
|
||||
auto weight_penalty = TurnPenalty{boost::numeric_cast<TurnPenalty::value_type>(
|
||||
extracted_turn.weight * weight_multiplier)};
|
||||
auto duration_penalty = TurnPenalty{
|
||||
boost::numeric_cast<TurnPenalty::value_type>(extracted_turn.duration * 10.)};
|
||||
|
||||
BOOST_ASSERT(SPECIAL_NODEID != nbe_to_ebn_mapping[node_based_edge_from]);
|
||||
BOOST_ASSERT(SPECIAL_NODEID != nbe_to_ebn_mapping[node_based_edge_to]);
|
||||
|
||||
// auto turn_id = m_edge_based_edge_list.size();
|
||||
auto weight = boost::numeric_cast<EdgeWeight>(edge_data1.weight + weight_penalty);
|
||||
auto duration = boost::numeric_cast<EdgeWeight>(edge_data1.duration + duration_penalty);
|
||||
auto distance = boost::numeric_cast<EdgeDistance>(edge_data1.distance);
|
||||
auto weight = edge_data1.weight + alias_cast<EdgeWeight>(weight_penalty);
|
||||
auto duration = edge_data1.duration + alias_cast<EdgeDuration>(duration_penalty);
|
||||
auto distance = edge_data1.distance;
|
||||
|
||||
EdgeBasedEdge edge_based_edge = {edge_based_node_from,
|
||||
edge_based_node_to,
|
||||
@@ -860,7 +862,7 @@ void EdgeBasedGraphFactory::GenerateEdgeExpandedEdges(
|
||||
edge_data.flags.access_turn_classification,
|
||||
((double)intersection::findEdgeLength(edge_geometries,
|
||||
connected_edge.eid) /
|
||||
edge_data.duration) *
|
||||
from_alias<double>(edge_data.duration)) *
|
||||
36,
|
||||
edge_data.flags.road_classification.GetPriority(),
|
||||
is_incoming,
|
||||
|
||||
@@ -712,9 +712,11 @@ void ExtractionContainers::PrepareEdges(ScriptingEnvironment &scripting_environm
|
||||
scripting_environment.ProcessSegment(segment);
|
||||
|
||||
auto &edge = edge_iterator->result;
|
||||
edge.weight = std::max<EdgeWeight>(1, std::round(segment.weight * weight_multiplier));
|
||||
edge.duration = std::max<EdgeWeight>(1, std::round(segment.duration * 10.));
|
||||
edge.distance = static_cast<float>(accurate_distance);
|
||||
edge.weight = std::max<EdgeWeight>(
|
||||
{1}, to_alias<EdgeWeight>(std::round(segment.weight * weight_multiplier)));
|
||||
edge.duration = std::max<EdgeDuration>(
|
||||
{1}, to_alias<EdgeDuration>(std::round(segment.duration * 10.)));
|
||||
edge.distance = to_alias<EdgeDistance>(accurate_distance);
|
||||
|
||||
// assign new node id
|
||||
const auto node_id = mapExternalToInternalNodeID(
|
||||
@@ -779,10 +781,8 @@ void ExtractionContainers::PrepareEdges(ScriptingEnvironment &scripting_environm
|
||||
NodeID source = all_edges_list[i].result.source;
|
||||
NodeID target = all_edges_list[i].result.target;
|
||||
|
||||
auto min_forward = std::make_pair(std::numeric_limits<EdgeWeight>::max(),
|
||||
std::numeric_limits<EdgeWeight>::max());
|
||||
auto min_backward = std::make_pair(std::numeric_limits<EdgeWeight>::max(),
|
||||
std::numeric_limits<EdgeWeight>::max());
|
||||
auto min_forward = std::make_pair(MAXIMAL_EDGE_WEIGHT, MAXIMAL_EDGE_DURATION);
|
||||
auto min_backward = std::make_pair(MAXIMAL_EDGE_WEIGHT, MAXIMAL_EDGE_DURATION);
|
||||
std::size_t min_forward_idx = std::numeric_limits<std::size_t>::max();
|
||||
std::size_t min_backward_idx = std::numeric_limits<std::size_t>::max();
|
||||
|
||||
|
||||
@@ -668,7 +668,7 @@ void Extractor::FindComponents(unsigned number_of_edge_based_nodes,
|
||||
|
||||
for (const auto &edge : input_edge_list)
|
||||
{
|
||||
BOOST_ASSERT_MSG(static_cast<unsigned int>(std::max(edge.data.weight, 1)) > 0,
|
||||
BOOST_ASSERT_MSG((std::max(edge.data.weight, EdgeWeight{1})) > EdgeWeight{0},
|
||||
"edge distance < 1");
|
||||
BOOST_ASSERT(edge.source < number_of_edge_based_nodes);
|
||||
BOOST_ASSERT(edge.target < number_of_edge_based_nodes);
|
||||
|
||||
@@ -425,10 +425,10 @@ void ExtractorCallbacks::ProcessWay(const osmium::Way &input_way, const Extracti
|
||||
NodeBasedEdgeWithOSM edge = {
|
||||
OSMNodeID{static_cast<std::uint64_t>(first_node.ref())},
|
||||
OSMNodeID{static_cast<std::uint64_t>(last_node.ref())},
|
||||
0, // weight
|
||||
0, // duration
|
||||
0, // distance
|
||||
{}, // geometry id
|
||||
{0}, // weight
|
||||
{0}, // duration
|
||||
{0}, // distance
|
||||
{}, // geometry id
|
||||
static_cast<AnnotationID>(annotation_data_id),
|
||||
{true,
|
||||
in_backward_direction && !split_edge,
|
||||
@@ -459,10 +459,10 @@ void ExtractorCallbacks::ProcessWay(const osmium::Way &input_way, const Extracti
|
||||
NodeBasedEdgeWithOSM edge = {
|
||||
OSMNodeID{static_cast<std::uint64_t>(first_node.ref())},
|
||||
OSMNodeID{static_cast<std::uint64_t>(last_node.ref())},
|
||||
0, // weight
|
||||
0, // duration
|
||||
0, // distance
|
||||
{}, // geometry id
|
||||
{0}, // weight
|
||||
{0}, // duration
|
||||
{0}, // distance
|
||||
{}, // geometry id
|
||||
static_cast<AnnotationID>(annotation_data_id),
|
||||
{false,
|
||||
true,
|
||||
|
||||
@@ -252,16 +252,18 @@ void GraphCompressor::Compress(const std::unordered_set<NodeID> &barrier_nodes,
|
||||
roads_on_the_left);
|
||||
scripting_environment.ProcessTurn(extraction_turn);
|
||||
|
||||
auto update_direction_penalty =
|
||||
[&extraction_turn, weight_multiplier](bool signal,
|
||||
EdgeDuration &duration_penalty,
|
||||
EdgeWeight &weight_penalty) {
|
||||
if (signal)
|
||||
{
|
||||
duration_penalty = extraction_turn.duration * SECOND_TO_DECISECOND;
|
||||
weight_penalty = extraction_turn.weight * weight_multiplier;
|
||||
}
|
||||
};
|
||||
auto update_direction_penalty = [&extraction_turn, weight_multiplier](
|
||||
bool signal,
|
||||
EdgeDuration &duration_penalty,
|
||||
EdgeWeight &weight_penalty) {
|
||||
if (signal)
|
||||
{
|
||||
duration_penalty = to_alias<EdgeDuration>(extraction_turn.duration *
|
||||
SECOND_TO_DECISECOND);
|
||||
weight_penalty =
|
||||
to_alias<EdgeWeight>(extraction_turn.weight * weight_multiplier);
|
||||
}
|
||||
};
|
||||
|
||||
update_direction_penalty(has_forward_signal,
|
||||
forward_node_duration_penalty,
|
||||
@@ -277,8 +279,8 @@ void GraphCompressor::Compress(const std::unordered_set<NodeID> &barrier_nodes,
|
||||
const auto forward_duration1 = fwd_edge_data1.duration;
|
||||
const auto forward_duration2 = fwd_edge_data2.duration;
|
||||
|
||||
BOOST_ASSERT(0 != forward_weight1);
|
||||
BOOST_ASSERT(0 != forward_weight2);
|
||||
BOOST_ASSERT(EdgeWeight{0} != forward_weight1);
|
||||
BOOST_ASSERT(EdgeWeight{0} != forward_weight2);
|
||||
|
||||
const auto reverse_weight1 = rev_edge_data1.weight;
|
||||
const auto reverse_weight2 = rev_edge_data2.weight;
|
||||
@@ -297,8 +299,8 @@ void GraphCompressor::Compress(const std::unordered_set<NodeID> &barrier_nodes,
|
||||
BOOST_ASSERT(forward_distance2 == reverse_distance1);
|
||||
#endif
|
||||
|
||||
BOOST_ASSERT(0 != reverse_weight1);
|
||||
BOOST_ASSERT(0 != reverse_weight2);
|
||||
BOOST_ASSERT(EdgeWeight{0} != reverse_weight1);
|
||||
BOOST_ASSERT(EdgeWeight{0} != reverse_weight2);
|
||||
|
||||
auto apply_e2_to_e1 = [&graph](EdgeID edge1,
|
||||
EdgeID edge2,
|
||||
@@ -346,8 +348,8 @@ void GraphCompressor::Compress(const std::unordered_set<NodeID> &barrier_nodes,
|
||||
if (weight_penalty == INVALID_EDGE_WEIGHT &&
|
||||
other_weight_penalty != INVALID_EDGE_WEIGHT)
|
||||
{
|
||||
weight_penalty = 0;
|
||||
duration_penalty = 0;
|
||||
weight_penalty = {0};
|
||||
duration_penalty = {0};
|
||||
}
|
||||
};
|
||||
set_dummy_penalty(forward_node_weight_penalty,
|
||||
|
||||
@@ -549,7 +549,7 @@ void Sol2ScriptingEnvironment::InitContext(LuaScriptingContext &context)
|
||||
"precision",
|
||||
COORDINATE_PRECISION,
|
||||
"max_turn_weight",
|
||||
std::numeric_limits<TurnPenalty>::max());
|
||||
std::numeric_limits<TurnPenalty::value_type>::max());
|
||||
|
||||
// call initialize function
|
||||
sol::function setup_function = function_table.value()["setup"];
|
||||
|
||||
+63
-46
@@ -84,7 +84,7 @@ inline SegmentDuration convertToDuration(double speed_in_kmh, double distance_in
|
||||
const auto speed_in_ms = speed_in_kmh / 3.6;
|
||||
const auto duration = distance_in_meters / speed_in_ms;
|
||||
auto segment_duration = std::max<SegmentDuration>(
|
||||
1, boost::numeric_cast<SegmentDuration>(std::round(duration * 10.)));
|
||||
{1}, {boost::numeric_cast<SegmentDuration::value_type>(std::round(duration * 10.))});
|
||||
if (segment_duration >= INVALID_SEGMENT_DURATION)
|
||||
{
|
||||
util::Log(logWARNING) << "Clamping segment duration " << segment_duration << " to "
|
||||
@@ -114,7 +114,8 @@ void checkWeightsConsistency(
|
||||
{
|
||||
auto range = segment_data.GetForwardWeights(geometry_id.id);
|
||||
// NOLINTNEXTLINE(bugprone-fold-init-type)
|
||||
EdgeWeight weight = std::accumulate(range.begin(), range.end(), EdgeWeight{0});
|
||||
EdgeWeight weight = alias_cast<EdgeWeight>(
|
||||
std::accumulate(range.begin(), range.end(), SegmentWeight{0}));
|
||||
if (weight > edge.data.weight)
|
||||
{
|
||||
util::Log(logWARNING) << geometry_id.id << " vs " << edge.data.turn_id << ":"
|
||||
@@ -125,7 +126,8 @@ void checkWeightsConsistency(
|
||||
{
|
||||
auto range = segment_data.GetReverseWeights(geometry_id.id);
|
||||
// NOLINTNEXTLINE(bugprone-fold-init-type)
|
||||
EdgeWeight weight = std::accumulate(range.begin(), range.end(), EdgeWeight{0});
|
||||
EdgeWeight weight = alias_cast<EdgeWeight>(
|
||||
std::accumulate(range.begin(), range.end(), SegmentWeight{0}));
|
||||
if (weight > edge.data.weight)
|
||||
{
|
||||
util::Log(logWARNING) << geometry_id.id << " vs " << edge.data.turn_id << ":"
|
||||
@@ -185,8 +187,10 @@ updateSegmentData(const UpdaterConfig &config,
|
||||
|
||||
const auto weight_multiplier = profile_properties.GetWeightMultiplier();
|
||||
const auto weight = distance_in_meters / rate;
|
||||
auto segment_weight = std::max<SegmentWeight>(
|
||||
1, boost::numeric_cast<SegmentWeight>(std::round(weight * weight_multiplier)));
|
||||
auto segment_weight =
|
||||
std::max<SegmentWeight>({1},
|
||||
{boost::numeric_cast<SegmentWeight::value_type>(
|
||||
std::round(weight * weight_multiplier))});
|
||||
if (segment_weight >= INVALID_SEGMENT_WEIGHT)
|
||||
{
|
||||
util::Log(logWARNING) << "Clamping segment weight " << segment_weight << " to "
|
||||
@@ -356,18 +360,21 @@ updateSegmentData(const UpdaterConfig &config,
|
||||
if (new_fwd_datasources_range[segment_offset] == LUA_SOURCE)
|
||||
continue;
|
||||
|
||||
if (old_fwd_durations_range[segment_offset] >=
|
||||
(new_fwd_durations_range[segment_offset] * config.log_edge_updates_factor))
|
||||
SegmentDuration old_fwd_duration = old_fwd_durations_range[segment_offset];
|
||||
SegmentDuration new_fwd_duration = new_fwd_durations_range[segment_offset];
|
||||
|
||||
if (old_fwd_duration >=
|
||||
to_alias<SegmentDuration>(from_alias<double>(new_fwd_duration) *
|
||||
config.log_edge_updates_factor))
|
||||
{
|
||||
auto from = osm_node_ids[nodes_range[segment_offset]];
|
||||
auto to = osm_node_ids[nodes_range[segment_offset + 1]];
|
||||
util::Log(logWARNING)
|
||||
<< "[weight updates] Edge weight update from "
|
||||
<< old_fwd_durations_range[segment_offset] / 10. << "s to "
|
||||
<< new_fwd_durations_range[segment_offset] / 10. << "s Segment: " << from
|
||||
<< "," << to << " based on "
|
||||
<< config.segment_speed_lookup_paths
|
||||
[new_fwd_datasources_range[segment_offset] - 1];
|
||||
util::Log(logWARNING) << "[weight updates] Edge weight update from "
|
||||
<< from_alias<double>(old_fwd_duration) / 10. << "s to "
|
||||
<< from_alias<double>(new_fwd_duration) / 10.
|
||||
<< "s Segment: " << from << "," << to << " based on "
|
||||
<< config.segment_speed_lookup_paths
|
||||
[new_fwd_datasources_range[segment_offset] - 1];
|
||||
}
|
||||
}
|
||||
|
||||
@@ -377,18 +384,21 @@ updateSegmentData(const UpdaterConfig &config,
|
||||
if (new_rev_datasources_range[segment_offset] == LUA_SOURCE)
|
||||
continue;
|
||||
|
||||
if (old_rev_durations_range[segment_offset] >=
|
||||
(new_rev_durations_range[segment_offset] * config.log_edge_updates_factor))
|
||||
SegmentDuration old_rev_duration = old_rev_durations_range[segment_offset];
|
||||
SegmentDuration new_rev_duration = new_rev_durations_range[segment_offset];
|
||||
|
||||
if (old_rev_duration >=
|
||||
to_alias<SegmentDuration>(from_alias<double>(new_rev_duration) *
|
||||
config.log_edge_updates_factor))
|
||||
{
|
||||
auto from = osm_node_ids[nodes_range[segment_offset + 1]];
|
||||
auto to = osm_node_ids[nodes_range[segment_offset]];
|
||||
util::Log(logWARNING)
|
||||
<< "[weight updates] Edge weight update from "
|
||||
<< old_rev_durations_range[segment_offset] / 10. << "s to "
|
||||
<< new_rev_durations_range[segment_offset] / 10. << "s Segment: " << from
|
||||
<< "," << to << " based on "
|
||||
<< config.segment_speed_lookup_paths
|
||||
[new_rev_datasources_range[segment_offset] - 1];
|
||||
util::Log(logWARNING) << "[weight updates] Edge weight update from "
|
||||
<< from_alias<double>(old_rev_duration) / 10. << "s to "
|
||||
<< from_alias<double>(new_rev_duration) / 10.
|
||||
<< "s Segment: " << from << "," << to << " based on "
|
||||
<< config.segment_speed_lookup_paths
|
||||
[new_rev_datasources_range[segment_offset] - 1];
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -455,18 +465,20 @@ updateTurnPenalties(const UpdaterConfig &config,
|
||||
|
||||
if (auto value = turn_penalty_lookup(osm_turn))
|
||||
{
|
||||
turn_duration_penalty =
|
||||
boost::numeric_cast<TurnPenalty>(std::round(value->duration * 10.));
|
||||
turn_weight_penalty = boost::numeric_cast<TurnPenalty>(std::round(
|
||||
std::isfinite(value->weight) ? value->weight * weight_multiplier
|
||||
: turn_duration_penalty * weight_multiplier / 10.));
|
||||
turn_duration_penalty = {
|
||||
boost::numeric_cast<TurnPenalty::value_type>(std::round(value->duration * 10.))};
|
||||
turn_weight_penalty = {boost::numeric_cast<TurnPenalty::value_type>(
|
||||
std::round(std::isfinite(value->weight)
|
||||
? value->weight * weight_multiplier
|
||||
: from_alias<TurnPenalty::value_type>(turn_duration_penalty) *
|
||||
weight_multiplier / 10.))};
|
||||
|
||||
turn_duration_penalties[edge_index] = turn_duration_penalty;
|
||||
turn_weight_penalties[edge_index] = turn_weight_penalty;
|
||||
updated_turns.push_back(edge_index);
|
||||
}
|
||||
|
||||
if (turn_weight_penalty < 0)
|
||||
if (turn_weight_penalty < TurnPenalty{0})
|
||||
{
|
||||
util::Log(logWARNING) << "Negative turn penalty at " << osm_turn.from << ", "
|
||||
<< osm_turn.via << ", " << osm_turn.to << ": turn penalty "
|
||||
@@ -674,42 +686,44 @@ Updater::LoadAndUpdateEdgeExpandedGraph(std::vector<extractor::EdgeBasedEdge> &e
|
||||
return std::tie(lhs.id, lhs.forward) < std::tie(rhs.id, rhs.forward);
|
||||
});
|
||||
|
||||
using WeightAndDuration = std::tuple<EdgeWeight, EdgeWeight>;
|
||||
using WeightAndDuration = std::tuple<EdgeWeight, EdgeDuration>;
|
||||
const auto compute_new_weight_and_duration =
|
||||
[&](const GeometryID geometry_id) -> WeightAndDuration {
|
||||
EdgeWeight new_weight = 0;
|
||||
EdgeWeight new_duration = 0;
|
||||
EdgeWeight new_weight = {0};
|
||||
EdgeDuration new_duration = {0};
|
||||
if (geometry_id.forward)
|
||||
{
|
||||
const auto weights = segment_data.GetForwardWeights(geometry_id.id);
|
||||
for (const auto weight : weights)
|
||||
for (const SegmentWeight weight : weights)
|
||||
{
|
||||
if (weight == INVALID_SEGMENT_WEIGHT)
|
||||
{
|
||||
new_weight = INVALID_EDGE_WEIGHT;
|
||||
break;
|
||||
}
|
||||
new_weight += weight;
|
||||
new_weight += alias_cast<EdgeWeight>(weight);
|
||||
}
|
||||
const auto durations = segment_data.GetForwardDurations(geometry_id.id);
|
||||
// NOLINTNEXTLINE(bugprone-fold-init-type)
|
||||
new_duration = std::accumulate(durations.begin(), durations.end(), EdgeWeight{0});
|
||||
new_duration = alias_cast<EdgeDuration>(
|
||||
std::accumulate(durations.begin(), durations.end(), SegmentDuration{0}));
|
||||
}
|
||||
else
|
||||
{
|
||||
const auto weights = segment_data.GetReverseWeights(geometry_id.id);
|
||||
for (const auto weight : weights)
|
||||
for (const SegmentWeight weight : weights)
|
||||
{
|
||||
if (weight == INVALID_SEGMENT_WEIGHT)
|
||||
{
|
||||
new_weight = INVALID_EDGE_WEIGHT;
|
||||
break;
|
||||
}
|
||||
new_weight += weight;
|
||||
new_weight += alias_cast<EdgeWeight>(SegmentWeight(weight));
|
||||
}
|
||||
const auto durations = segment_data.GetReverseDurations(geometry_id.id);
|
||||
// NOLINTNEXTLINE(bugprone-fold-init-type)
|
||||
new_duration = std::accumulate(durations.begin(), durations.end(), EdgeWeight{0});
|
||||
new_duration = alias_cast<EdgeDuration>(
|
||||
std::accumulate(durations.begin(), durations.end(), SegmentDuration{0}));
|
||||
}
|
||||
return std::make_tuple(new_weight, new_duration);
|
||||
};
|
||||
@@ -740,7 +754,7 @@ Updater::LoadAndUpdateEdgeExpandedGraph(std::vector<extractor::EdgeBasedEdge> &e
|
||||
// Find a segment with zero speed and simultaneously compute the new edge
|
||||
// weight
|
||||
EdgeWeight new_weight;
|
||||
EdgeWeight new_duration;
|
||||
EdgeDuration new_duration;
|
||||
std::tie(new_weight, new_duration) =
|
||||
accumulated_segment_data[updated_iter - updated_segments.begin()];
|
||||
|
||||
@@ -749,7 +763,9 @@ Updater::LoadAndUpdateEdgeExpandedGraph(std::vector<extractor::EdgeBasedEdge> &e
|
||||
// but we should always assign the same value here.
|
||||
BOOST_ASSERT(edge.source < node_weights.size());
|
||||
node_weights[edge.source] =
|
||||
node_weights[edge.source] & 0x80000000 ? new_weight | 0x80000000 : new_weight;
|
||||
from_alias<EdgeWeight::value_type>(node_weights[edge.source]) & 0x80000000
|
||||
? new_weight | EdgeWeight{static_cast<EdgeWeight::value_type>(0x80000000)}
|
||||
: new_weight;
|
||||
node_durations[edge.source] = new_duration;
|
||||
|
||||
// We found a zero-speed edge, so we'll skip this whole edge-based-edge
|
||||
@@ -765,15 +781,15 @@ Updater::LoadAndUpdateEdgeExpandedGraph(std::vector<extractor::EdgeBasedEdge> &e
|
||||
auto turn_weight_penalty = turn_weight_penalties[edge.data.turn_id];
|
||||
auto turn_duration_penalty = turn_duration_penalties[edge.data.turn_id];
|
||||
const auto num_nodes = segment_data.GetForwardGeometry(geometry_id.id).size();
|
||||
const auto weight_min_value = static_cast<EdgeWeight>(num_nodes);
|
||||
if (turn_weight_penalty + new_weight < weight_min_value)
|
||||
const auto weight_min_value = to_alias<EdgeWeight>(num_nodes);
|
||||
if (alias_cast<EdgeWeight>(turn_weight_penalty) + new_weight < weight_min_value)
|
||||
{
|
||||
if (turn_weight_penalty < 0)
|
||||
if (turn_weight_penalty < TurnPenalty{0})
|
||||
{
|
||||
util::Log(logWARNING)
|
||||
<< "turn penalty " << turn_weight_penalty
|
||||
<< " is too negative: clamping turn weight to " << weight_min_value;
|
||||
turn_weight_penalty = weight_min_value - new_weight;
|
||||
turn_weight_penalty = alias_cast<TurnPenalty>(weight_min_value - new_weight);
|
||||
turn_weight_penalties[edge.data.turn_id] = turn_weight_penalty;
|
||||
}
|
||||
else
|
||||
@@ -783,8 +799,9 @@ Updater::LoadAndUpdateEdgeExpandedGraph(std::vector<extractor::EdgeBasedEdge> &e
|
||||
}
|
||||
|
||||
// Update edge weight
|
||||
edge.data.weight = new_weight + turn_weight_penalty;
|
||||
edge.data.duration = new_duration + turn_duration_penalty;
|
||||
edge.data.weight = new_weight + alias_cast<EdgeWeight>(turn_weight_penalty);
|
||||
edge.data.duration = from_alias<EdgeDuration::value_type>(
|
||||
new_duration + alias_cast<EdgeDuration>(turn_duration_penalty));
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
Reference in New Issue
Block a user