Initial version of core ch
This improves preprocessing times in favour of worse query performance. Core size can be set over the --core parameater, default is the old behaviour to fully contract the graph.
This commit is contained in:
parent
94f44e1d5d
commit
b526cadebd
@ -284,7 +284,7 @@ class Contractor
|
||||
|
||||
~Contractor() {}
|
||||
|
||||
void Run()
|
||||
void Run( double core_factor = 1.0 )
|
||||
{
|
||||
// for the preperation we can use a big grain size, which is much faster (probably cache)
|
||||
constexpr size_t InitGrainSize = 100000;
|
||||
@ -333,9 +333,9 @@ class Contractor
|
||||
<< std::flush;
|
||||
|
||||
bool flushed_contractor = false;
|
||||
while (number_of_nodes > 2 && number_of_contracted_nodes < number_of_nodes)
|
||||
while (number_of_nodes > 2 && number_of_contracted_nodes < static_cast<NodeID>(number_of_nodes * core_factor) )
|
||||
{
|
||||
if (!flushed_contractor && (number_of_contracted_nodes > (number_of_nodes * 0.65)))
|
||||
if (!flushed_contractor && (number_of_contracted_nodes > static_cast<NodeID>(number_of_nodes * 0.65 * core_factor)))
|
||||
{
|
||||
DeallocatingVector<ContractorEdge> new_edge_set; // this one is not explicitely
|
||||
// cleared since it goes out of
|
||||
@ -524,7 +524,7 @@ class Contractor
|
||||
// unsigned quaddegree = 0;
|
||||
//
|
||||
// for(unsigned i = 0; i < remaining_nodes.size(); ++i) {
|
||||
// unsigned degree = contractor_graph->EndEdges(remaining_nodes[i].first)
|
||||
// unsigned degree = contractor_graph->EndEdges(remaining_nodes[i].id)
|
||||
// -
|
||||
// contractor_graph->BeginEdges(remaining_nodes[i].first);
|
||||
// if(degree > maxdegree)
|
||||
@ -546,6 +546,8 @@ class Contractor
|
||||
p.printStatus(number_of_contracted_nodes);
|
||||
}
|
||||
|
||||
SimpleLogger().Write() << "[core] " << remaining_nodes.size() << " nodes " << contractor_graph->GetNumberOfEdges() << " edges." << std::endl;
|
||||
|
||||
thread_data_list.data.clear();
|
||||
}
|
||||
|
||||
|
@ -56,7 +56,11 @@ ContractorOptions::ParseArguments(int argc, char *argv[], ContractorConfig &cont
|
||||
"Path to LUA routing profile")(
|
||||
"threads,t", boost::program_options::value<unsigned int>(&contractor_config.requested_num_threads)
|
||||
->default_value(tbb::task_scheduler_init::default_num_threads()),
|
||||
"Number of threads to use");
|
||||
"Number of threads to use")(
|
||||
"core,k", boost::program_options::value<double>(&contractor_config.core_factor)
|
||||
->default_value(1.0),"Percentage of the graph (in vertices) to contract [0.1]");
|
||||
|
||||
|
||||
|
||||
// hidden options, will be allowed both on command line and in config file, but will not be
|
||||
// shown to the user
|
||||
|
@ -56,6 +56,12 @@ struct ContractorConfig
|
||||
std::string rtree_leafs_output_path;
|
||||
|
||||
unsigned requested_num_threads;
|
||||
|
||||
//A percentage of vertices that will be contracted for the hierarchy.
|
||||
//Offers a trade-off between preprocessing and query time.
|
||||
//The remaining vertices form the core of the hierarchy
|
||||
//(e.g. 0.8 contracts 80 percent of the hierarchy, leaving a core of 20%)
|
||||
double core_factor;
|
||||
};
|
||||
|
||||
struct ContractorOptions
|
||||
|
@ -414,7 +414,7 @@ void Prepare::ContractGraph(const unsigned max_edge_id,
|
||||
DeallocatingVector<QueryEdge>& contracted_edge_list)
|
||||
{
|
||||
Contractor contractor(max_edge_id + 1, edge_based_edge_list);
|
||||
contractor.Run();
|
||||
contractor.Run(config.core_factor);
|
||||
contractor.GetEdges(contracted_edge_list);
|
||||
}
|
||||
|
||||
|
@ -189,6 +189,11 @@ class BinaryHeap
|
||||
return inserted_nodes[heap[1].index].node;
|
||||
}
|
||||
|
||||
Weight MinKey() const {
|
||||
BOOST_ASSERT(heap.size() > 1);
|
||||
return heap[1].weight;
|
||||
}
|
||||
|
||||
NodeID DeleteMin()
|
||||
{
|
||||
BOOST_ASSERT(heap.size() > 1);
|
||||
|
@ -33,6 +33,7 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
#include "../routing_algorithms/many_to_many.hpp"
|
||||
#include "../routing_algorithms/map_matching.hpp"
|
||||
#include "../routing_algorithms/shortest_path.hpp"
|
||||
#include "../routing_algorithms/direct_shortest_path.hpp"
|
||||
|
||||
#include <type_traits>
|
||||
|
||||
@ -44,6 +45,7 @@ template <class DataFacadeT> class SearchEngine
|
||||
|
||||
public:
|
||||
ShortestPathRouting<DataFacadeT> shortest_path;
|
||||
DirectShortestPathRouting<DataFacadeT> direct_shortest_path;
|
||||
AlternativeRouting<DataFacadeT> alternative_path;
|
||||
ManyToManyRouting<DataFacadeT> distance_table;
|
||||
MapMatching<DataFacadeT> map_matching;
|
||||
@ -51,6 +53,7 @@ template <class DataFacadeT> class SearchEngine
|
||||
explicit SearchEngine(DataFacadeT *facade)
|
||||
: facade(facade),
|
||||
shortest_path(facade, engine_working_data),
|
||||
direct_shortest_path(facade, engine_working_data),
|
||||
alternative_path(facade, engine_working_data),
|
||||
distance_table(facade, engine_working_data),
|
||||
map_matching(facade, engine_working_data)
|
||||
|
@ -16,7 +16,8 @@ Feature: osrm-prepare command line options: help
|
||||
And stdout should contain "--restrictions"
|
||||
And stdout should contain "--profile"
|
||||
And stdout should contain "--threads"
|
||||
And stdout should contain 15 lines
|
||||
And stdout should contain "--core"
|
||||
And stdout should contain 17 lines
|
||||
And it should exit with code 1
|
||||
|
||||
Scenario: osrm-prepare - Help, short
|
||||
@ -31,7 +32,8 @@ Feature: osrm-prepare command line options: help
|
||||
And stdout should contain "--restrictions"
|
||||
And stdout should contain "--profile"
|
||||
And stdout should contain "--threads"
|
||||
And stdout should contain 15 lines
|
||||
And stdout should contain "--core"
|
||||
And stdout should contain 17 lines
|
||||
And it should exit with code 0
|
||||
|
||||
Scenario: osrm-prepare - Help, long
|
||||
@ -46,5 +48,6 @@ Feature: osrm-prepare command line options: help
|
||||
And stdout should contain "--restrictions"
|
||||
And stdout should contain "--profile"
|
||||
And stdout should contain "--threads"
|
||||
And stdout should contain 15 lines
|
||||
And stdout should contain "--core"
|
||||
And stdout should contain 17 lines
|
||||
And it should exit with code 0
|
||||
|
@ -39,6 +39,7 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
#include "../util/json_renderer.hpp"
|
||||
#include "../util/make_unique.hpp"
|
||||
#include "../util/simple_logger.hpp"
|
||||
#include "../util/timing_util.hpp"
|
||||
|
||||
#include <osrm/json_container.hpp>
|
||||
|
||||
@ -153,10 +154,18 @@ template <class DataFacadeT> class ViaRoutePlugin final : public BasePlugin
|
||||
};
|
||||
osrm::for_each_pair(phantom_node_pair_list, build_phantom_pairs);
|
||||
|
||||
if (route_parameters.alternate_route && 1 == raw_route.segment_end_coordinates.size())
|
||||
if (1 == raw_route.segment_end_coordinates.size())
|
||||
{
|
||||
search_engine_ptr->alternative_path(raw_route.segment_end_coordinates.front(),
|
||||
raw_route);
|
||||
if (route_parameters.alternate_route)
|
||||
{
|
||||
search_engine_ptr->alternative_path(raw_route.segment_end_coordinates.front(),
|
||||
raw_route);
|
||||
}
|
||||
else
|
||||
{
|
||||
search_engine_ptr->direct_shortest_path(raw_route.segment_end_coordinates,
|
||||
route_parameters.uturns, raw_route);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
|
165
routing_algorithms/direct_shortest_path.hpp
Normal file
165
routing_algorithms/direct_shortest_path.hpp
Normal file
@ -0,0 +1,165 @@
|
||||
/*
|
||||
|
||||
Copyright (c) 2015, Project OSRM contributors
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without modification,
|
||||
are permitted provided that the following conditions are met:
|
||||
|
||||
Redistributions of source code must retain the above copyright notice, this list
|
||||
of conditions and the following disclaimer.
|
||||
Redistributions in binary form must reproduce the above copyright notice, this
|
||||
list of conditions and the following disclaimer in the documentation and/or
|
||||
other materials provided with the distribution.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
|
||||
ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
|
||||
ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
*/
|
||||
|
||||
#ifndef DIRECT_SHORTEST_PATH_HPP
|
||||
#define DIRECT_SHORTEST_PATH_HPP
|
||||
|
||||
#include <boost/assert.hpp>
|
||||
|
||||
#include "routing_base.hpp"
|
||||
#include "../data_structures/search_engine_data.hpp"
|
||||
#include "../util/integer_range.hpp"
|
||||
#include "../util/timing_util.hpp"
|
||||
#include "../typedefs.h"
|
||||
|
||||
/// This is a striped down version of the general shortest path algorithm.
|
||||
/// The general algorithm always computes two queries for each leg. This is only
|
||||
/// necessary in case of vias, where the directions of the start node is constrainted
|
||||
/// by the previous route.
|
||||
/// This variation is only an optimazation for graphs with slow queries, for example
|
||||
/// not fully contracted graphs.
|
||||
template <class DataFacadeT>
|
||||
class DirectShortestPathRouting final
|
||||
: public BasicRoutingInterface<DataFacadeT, DirectShortestPathRouting<DataFacadeT>>
|
||||
{
|
||||
using super = BasicRoutingInterface<DataFacadeT, DirectShortestPathRouting<DataFacadeT>>;
|
||||
using QueryHeap = SearchEngineData::QueryHeap;
|
||||
SearchEngineData &engine_working_data;
|
||||
|
||||
public:
|
||||
DirectShortestPathRouting(DataFacadeT *facade, SearchEngineData &engine_working_data)
|
||||
: super(facade), engine_working_data(engine_working_data)
|
||||
{
|
||||
}
|
||||
|
||||
~DirectShortestPathRouting() {}
|
||||
|
||||
void operator()(const std::vector<PhantomNodes> &phantom_nodes_vector,
|
||||
const std::vector<bool> &uturn_indicators,
|
||||
InternalRouteResult &raw_route_data) const
|
||||
{
|
||||
engine_working_data.InitializeOrClearFirstThreadLocalStorage(
|
||||
super::facade->GetNumberOfNodes());
|
||||
|
||||
QueryHeap &forward_heap = *(engine_working_data.forward_heap_1);
|
||||
QueryHeap &reverse_heap = *(engine_working_data.reverse_heap_1);
|
||||
|
||||
// Get distance to next pair of target nodes.
|
||||
BOOST_ASSERT_MSG(1 == phantom_nodes_vector.size(),
|
||||
"Direct Shortest Path Query only accepts a single source and target pair. Multiple ones have been specified.");
|
||||
|
||||
const auto& phantom_node_pair = phantom_nodes_vector.front();
|
||||
|
||||
forward_heap.Clear();
|
||||
reverse_heap.Clear();
|
||||
int distance = INVALID_EDGE_WEIGHT;
|
||||
NodeID middle = SPECIAL_NODEID;
|
||||
|
||||
const EdgeWeight min_edge_offset =
|
||||
std::min(-phantom_node_pair.source_phantom.GetForwardWeightPlusOffset(),
|
||||
-phantom_node_pair.source_phantom.GetReverseWeightPlusOffset());
|
||||
|
||||
// insert new starting nodes into forward heap, adjusted by previous distances.
|
||||
if (phantom_node_pair.source_phantom.forward_node_id != SPECIAL_NODEID)
|
||||
{
|
||||
forward_heap.Insert(
|
||||
phantom_node_pair.source_phantom.forward_node_id,
|
||||
-phantom_node_pair.source_phantom.GetForwardWeightPlusOffset(),
|
||||
phantom_node_pair.source_phantom.forward_node_id);
|
||||
}
|
||||
if ( phantom_node_pair.source_phantom.reverse_node_id != SPECIAL_NODEID)
|
||||
{
|
||||
forward_heap.Insert(
|
||||
phantom_node_pair.source_phantom.reverse_node_id,
|
||||
-phantom_node_pair.source_phantom.GetReverseWeightPlusOffset(),
|
||||
phantom_node_pair.source_phantom.reverse_node_id);
|
||||
}
|
||||
|
||||
// insert new backward nodes into backward heap, unadjusted.
|
||||
if (phantom_node_pair.target_phantom.forward_node_id != SPECIAL_NODEID)
|
||||
{
|
||||
reverse_heap.Insert(phantom_node_pair.target_phantom.forward_node_id,
|
||||
phantom_node_pair.target_phantom.GetForwardWeightPlusOffset(),
|
||||
phantom_node_pair.target_phantom.forward_node_id);
|
||||
}
|
||||
|
||||
if (phantom_node_pair.target_phantom.reverse_node_id != SPECIAL_NODEID)
|
||||
{
|
||||
reverse_heap.Insert(phantom_node_pair.target_phantom.reverse_node_id,
|
||||
phantom_node_pair.target_phantom.GetReverseWeightPlusOffset(),
|
||||
phantom_node_pair.target_phantom.reverse_node_id);
|
||||
}
|
||||
|
||||
// run two-Target Dijkstra routing step.
|
||||
while (0 < (forward_heap.Size() + reverse_heap.Size()) )
|
||||
{
|
||||
if (!forward_heap.Empty())
|
||||
{
|
||||
super::RoutingStep(forward_heap, reverse_heap, &middle, &distance,
|
||||
min_edge_offset, true);
|
||||
}
|
||||
if (!reverse_heap.Empty())
|
||||
{
|
||||
super::RoutingStep(reverse_heap, forward_heap, &middle, &distance,
|
||||
min_edge_offset, false);
|
||||
}
|
||||
}
|
||||
|
||||
// No path found for both target nodes?
|
||||
if ((INVALID_EDGE_WEIGHT == distance))
|
||||
{
|
||||
raw_route_data.shortest_path_length = INVALID_EDGE_WEIGHT;
|
||||
raw_route_data.alternative_path_length = INVALID_EDGE_WEIGHT;
|
||||
return;
|
||||
}
|
||||
|
||||
// Was a paths over one of the forward/reverse nodes not found?
|
||||
BOOST_ASSERT_MSG((SPECIAL_NODEID == middle || INVALID_EDGE_WEIGHT != distance),
|
||||
"no path found");
|
||||
|
||||
// Unpack paths if they exist
|
||||
std::vector<NodeID> packed_leg;
|
||||
if (INVALID_EDGE_WEIGHT != distance)
|
||||
{
|
||||
super::RetrievePackedPathFromHeap(forward_heap, reverse_heap, middle, packed_leg);
|
||||
|
||||
BOOST_ASSERT_MSG(!packed_leg.empty(), "packed path empty");
|
||||
|
||||
raw_route_data.unpacked_path_segments.resize(1);
|
||||
raw_route_data.source_traversed_in_reverse.push_back(
|
||||
(packed_leg.front() != phantom_node_pair.source_phantom.forward_node_id));
|
||||
raw_route_data.target_traversed_in_reverse.push_back(
|
||||
(packed_leg.back() != phantom_node_pair.target_phantom.forward_node_id));
|
||||
|
||||
super::UnpackPath(packed_leg, phantom_node_pair, raw_route_data.unpacked_path_segments.front());
|
||||
}
|
||||
|
||||
raw_route_data.shortest_path_length = distance;
|
||||
}
|
||||
};
|
||||
|
||||
#endif /* DIRECT_SHORTEST_PATH_HPP */
|
@ -165,6 +165,7 @@ BOOST_FIXTURE_TEST_CASE_TEMPLATE(decrease_key_test, T, storage_types, RandomData
|
||||
{
|
||||
heap.DecreaseKey(id, weights[id]);
|
||||
BOOST_CHECK_EQUAL(heap.Min(), min_id);
|
||||
BOOST_CHECK_EQUAL(heap.MinKey(), min_weight);
|
||||
weights[id]--;
|
||||
}
|
||||
|
||||
@ -172,6 +173,7 @@ BOOST_FIXTURE_TEST_CASE_TEMPLATE(decrease_key_test, T, storage_types, RandomData
|
||||
weights[id] -= 2;
|
||||
heap.DecreaseKey(id, weights[id]);
|
||||
BOOST_CHECK_EQUAL(heap.Min(), id);
|
||||
BOOST_CHECK_EQUAL(heap.MinKey(), weights[id]);
|
||||
}
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user