implement flag edge-weight-updates-over-factor, to log edge weight

updates over provided x factor
This commit is contained in:
karenzshea 2016-09-12 12:16:56 -04:00 committed by Moritz Kobitzsch
parent eafe3fa928
commit 3d5a53566c
7 changed files with 103 additions and 22 deletions

View File

@ -0,0 +1,30 @@
@contract @options @edge-weight-updates-over-factor
Feature: osrm-contract command line option: edge-weight-updates-over-factor
Background: Log edge weight updates over given factor
Scenario: Logging weight with updates over factor of 2, long segment
Given the node locations
| node | lat | lon |
| a | 0.1 | 0.1 |
| b | .05 | 0.1 |
| c | 0.3 | 0.1 |
And the ways
| nodes | highway |
| ab | residential |
| ac | primary |
Given the profile "testbot"
Given the extract extra arguments "--generate-edge-lookup"
Given the speed file
"""
1,2,100
1,3,100
"""
And the data has been extracted
When I run "osrm-contract --edge-weight-updates-over-factor 2 --segment-speed-file {speeds_file} {processed_file}"
And stderr should contain "weight updates"
And stderr should contain "New speed: 100 kph"
And I route I should get
| from | to | route | speed |
| a | b | ab,ab | 100 km/h |
| a | c | ac,ac | 100 km/h |

View File

@ -86,6 +86,10 @@ module.exports = function () {
assert.equal(this.stdout.split('\n').length - 1, parseInt(lines)); assert.equal(this.stdout.split('\n').length - 1, parseInt(lines));
}); });
this.Then(/^stderr should contain (\d+) lines?$/, (lines) => {
assert.equal(this.stderr.split('\n').length - 1, parseInt(lines));
});
this.Then(/^datasource names should contain "(.+)"$/, (expectedData) => { this.Then(/^datasource names should contain "(.+)"$/, (expectedData) => {
var actualData = fs.readFileSync(this.processedCacheFile + '.datasource_names', {encoding:'UTF-8'}).trim().split('\n').join(','); var actualData = fs.readFileSync(this.processedCacheFile + '.datasource_names', {encoding:'UTF-8'}).trim().split('\n').join(',');
assert.equal(actualData, expectedData); assert.equal(actualData, expectedData);

View File

@ -89,7 +89,8 @@ class Contractor
const std::string &geometry_filename, const std::string &geometry_filename,
const std::string &datasource_names_filename, const std::string &datasource_names_filename,
const std::string &datasource_indexes_filename, const std::string &datasource_indexes_filename,
const std::string &rtree_leaf_filename); const std::string &rtree_leaf_filename,
const double log_edge_updates_factor);
}; };
} }
} }

View File

@ -73,6 +73,7 @@ struct ContractorConfig
bool use_cached_priority; bool use_cached_priority;
unsigned requested_num_threads; unsigned requested_num_threads;
double log_edge_updates_factor;
// A percentage of vertices that will be contracted for the hierarchy. // A percentage of vertices that will be contracted for the hierarchy.
// Offers a trade-off between preprocessing and query time. // Offers a trade-off between preprocessing and query time.

View File

@ -81,6 +81,41 @@ inline EdgeWeight distanceAndSpeedToWeight(double distance_in_meters, double spe
return std::max<EdgeWeight>(1, static_cast<EdgeWeight>(std::round(duration * 10))); return std::max<EdgeWeight>(1, static_cast<EdgeWeight>(std::round(duration * 10)));
} }
// Returns updated edge weight
template <class IterType>
EdgeWeight getNewWeight(IterType speed_iter,
const double &segment_length,
const std::vector<std::string> &segment_speed_filenames,
const EdgeWeight old_weight,
const double log_edge_updates_factor)
{
const auto new_segment_weight =
(speed_iter->speed_source.speed > 0)
? distanceAndSpeedToWeight(segment_length, speed_iter->speed_source.speed)
: INVALID_EDGE_WEIGHT;
// the check here is enabled by the `--edge-weight-updates-over-factor` flag
// it logs a warning if the new weight exceeds a heuristic of what a reasonable weight update is
if (log_edge_updates_factor > 0 && old_weight != 0)
{
auto new_secs = new_segment_weight / 10.0;
auto old_secs = old_weight / 10.0;
auto approx_original_speed = (segment_length / old_secs) * 3.6;
if (old_weight >= (new_segment_weight * log_edge_updates_factor))
{
auto speed_file = segment_speed_filenames.at(speed_iter->speed_source.source - 1);
util::SimpleLogger().Write(logWARNING)
<< "[weight updates] Edge weight update from " << old_secs << "s to " << new_secs << "s"
<< ". New speed: " << speed_iter->speed_source.speed << " kph"
<< ". Old speed: " << approx_original_speed << " kph"
<< ". Segment length: " << segment_length << " m"
<< ". Segment: " << speed_iter->segment.from << ","
<< speed_iter->segment.to << " based on " << speed_file;
}
}
return new_segment_weight;
}
int Contractor::Run() int Contractor::Run()
{ {
#ifdef WIN32 #ifdef WIN32
@ -113,7 +148,8 @@ int Contractor::Run()
config.geometry_path, config.geometry_path,
config.datasource_names_path, config.datasource_names_path,
config.datasource_indexes_path, config.datasource_indexes_path,
config.rtree_leaf_path); config.rtree_leaf_path,
config.log_edge_updates_factor);
// Contracting the edge-expanded graph // Contracting the edge-expanded graph
@ -370,7 +406,8 @@ EdgeID Contractor::LoadEdgeExpandedGraph(
const std::string &geometry_filename, const std::string &geometry_filename,
const std::string &datasource_names_filename, const std::string &datasource_names_filename,
const std::string &datasource_indexes_filename, const std::string &datasource_indexes_filename,
const std::string &rtree_leaf_filename) const std::string &rtree_leaf_filename,
const double log_edge_updates_factor)
{ {
if (segment_speed_filenames.size() > 255 || turn_penalty_filenames.size() > 255) if (segment_speed_filenames.size() > 255 || turn_penalty_filenames.size() > 255)
throw util::exception("Limit of 255 segment speed and turn penalty files each reached"); throw util::exception("Limit of 255 segment speed and turn penalty files each reached");
@ -556,10 +593,12 @@ EdgeID Contractor::LoadEdgeExpandedGraph(
extractor::QueryNode *u; extractor::QueryNode *u;
extractor::QueryNode *v; extractor::QueryNode *v;
// forward_packed_geometry_id is the index id for geometry, weight and duration of the segments
if (leaf_object.forward_packed_geometry_id != SPECIAL_EDGEID) if (leaf_object.forward_packed_geometry_id != SPECIAL_EDGEID)
{ {
const unsigned forward_begin = const unsigned forward_begin =
m_geometry_indices.at(leaf_object.forward_packed_geometry_id); m_geometry_indices.at(leaf_object.forward_packed_geometry_id);
const auto current_fwd_segment = &(m_geometry_list[forward_begin + leaf_object.fwd_segment_position]);
if (leaf_object.fwd_segment_position == 0) if (leaf_object.fwd_segment_position == 0)
{ {
@ -574,23 +613,23 @@ EdgeID Contractor::LoadEdgeExpandedGraph(
leaf_object.fwd_segment_position - 1] leaf_object.fwd_segment_position - 1]
.node_id]); .node_id]);
v = &(internal_to_external_node_map v = &(internal_to_external_node_map
[m_geometry_list[forward_begin + leaf_object.fwd_segment_position] [current_fwd_segment->node_id]);
.node_id]);
} }
const double segment_length = util::coordinate_calculation::greatCircleDistance( const double segment_length = util::coordinate_calculation::greatCircleDistance(
util::Coordinate{u->lon, u->lat}, util::Coordinate{v->lon, v->lat}); util::Coordinate{u->lon, u->lat}, util::Coordinate{v->lon, v->lat});
auto forward_speed_iter = auto forward_speed_iter =
find(segment_speed_lookup, Segment{u->node_id, v->node_id}); find(segment_speed_lookup, Segment{u->node_id, v->node_id});
if (forward_speed_iter != segment_speed_lookup.end()) if (forward_speed_iter != segment_speed_lookup.end())
{ {
auto new_segment_weight = const auto new_segment_weight = getNewWeight(
(forward_speed_iter->speed_source.speed > 0) forward_speed_iter,
? distanceAndSpeedToWeight(segment_length, segment_length,
forward_speed_iter->speed_source.speed) segment_speed_filenames,
: INVALID_EDGE_WEIGHT; current_fwd_segment->weight,
m_geometry_list[forward_begin + leaf_object.fwd_segment_position].weight = log_edge_updates_factor);
new_segment_weight; current_fwd_segment->weight = new_segment_weight;
m_geometry_datasource[forward_begin + leaf_object.fwd_segment_position] = m_geometry_datasource[forward_begin + leaf_object.fwd_segment_position] =
forward_speed_iter->speed_source.source; forward_speed_iter->speed_source.source;
@ -603,6 +642,7 @@ EdgeID Contractor::LoadEdgeExpandedGraph(
counters[LUA_SOURCE] += 1; counters[LUA_SOURCE] += 1;
} }
} }
// reverse_packed_geometry_id is the index id for geometry, weight and duration of the segment
if (leaf_object.reverse_packed_geometry_id != SPECIAL_EDGEID) if (leaf_object.reverse_packed_geometry_id != SPECIAL_EDGEID)
{ {
const unsigned reverse_begin = const unsigned reverse_begin =
@ -612,6 +652,7 @@ EdgeID Contractor::LoadEdgeExpandedGraph(
int rev_segment_position = int rev_segment_position =
(reverse_end - reverse_begin) - leaf_object.fwd_segment_position - 1; (reverse_end - reverse_begin) - leaf_object.fwd_segment_position - 1;
const auto current_rev_segment = &(m_geometry_list[reverse_begin + rev_segment_position]);
if (rev_segment_position == 0) if (rev_segment_position == 0)
{ {
u = &(internal_to_external_node_map[leaf_object.v]); u = &(internal_to_external_node_map[leaf_object.v]);
@ -625,7 +666,7 @@ EdgeID Contractor::LoadEdgeExpandedGraph(
rev_segment_position - 1] rev_segment_position - 1]
.node_id]); .node_id]);
v = &(internal_to_external_node_map v = &(internal_to_external_node_map
[m_geometry_list[reverse_begin + rev_segment_position].node_id]); [current_rev_segment->node_id]);
} }
const double segment_length = util::coordinate_calculation::greatCircleDistance( const double segment_length = util::coordinate_calculation::greatCircleDistance(
util::Coordinate{u->lon, u->lat}, util::Coordinate{v->lon, v->lat}); util::Coordinate{u->lon, u->lat}, util::Coordinate{v->lon, v->lat});
@ -634,13 +675,13 @@ EdgeID Contractor::LoadEdgeExpandedGraph(
find(segment_speed_lookup, Segment{u->node_id, v->node_id}); find(segment_speed_lookup, Segment{u->node_id, v->node_id});
if (reverse_speed_iter != segment_speed_lookup.end()) if (reverse_speed_iter != segment_speed_lookup.end())
{ {
auto new_segment_weight = const auto new_segment_weight = getNewWeight(
(reverse_speed_iter->speed_source.speed > 0) reverse_speed_iter,
? distanceAndSpeedToWeight(segment_length, segment_length,
reverse_speed_iter->speed_source.speed) segment_speed_filenames,
: INVALID_EDGE_WEIGHT; current_rev_segment->weight,
m_geometry_list[reverse_begin + rev_segment_position].weight = log_edge_updates_factor);
new_segment_weight; current_rev_segment->weight = new_segment_weight;
m_geometry_datasource[reverse_begin + rev_segment_position] = m_geometry_datasource[reverse_begin + rev_segment_position] =
reverse_speed_iter->speed_source.source; reverse_speed_iter->speed_source.source;

View File

@ -52,7 +52,11 @@ return_code parseArguments(int argc, char *argv[], contractor::ContractorConfig
"level-cache,o", "level-cache,o",
boost::program_options::value<bool>(&contractor_config.use_cached_priority) boost::program_options::value<bool>(&contractor_config.use_cached_priority)
->default_value(false), ->default_value(false),
"Use .level file to retain the contaction level for each node from the last run."); "Use .level file to retain the contaction level for each node from the last run.")(
"edge-weight-updates-over-factor",
boost::program_options::value<double>(&contractor_config.log_edge_updates_factor)
->default_value(0.0),
"Use with `--segment-speed-file`. Provide an `x` factor, by which Extractor will log edge weights updated by more than this factor");
// hidden options, will be allowed on command line, but will not be shown to the user // hidden options, will be allowed on command line, but will not be shown to the user
boost::program_options::options_description hidden_options("Hidden options"); boost::program_options::options_description hidden_options("Hidden options");