fallback to CH, when coreCH used
This commit is contained in:
committed by
Patrick Niklaus
parent
7cf7c46939
commit
2a13f9d10b
@@ -42,9 +42,10 @@ namespace contractor
|
||||
|
||||
int Contractor::Run()
|
||||
{
|
||||
if (config.core_factor > 1.0 || config.core_factor < 0)
|
||||
if (config.core_factor)
|
||||
{
|
||||
throw util::exception("Core factor must be between 0.0 to 1.0 (inclusive)" + SOURCE_REF);
|
||||
util::Log(logWARNING) << "Using core factor is deprecated and will be ignored. Falling back to CH.";
|
||||
config.core_factor = 1.0;
|
||||
}
|
||||
|
||||
if (config.use_cached_priority)
|
||||
@@ -104,8 +105,6 @@ int Contractor::Run()
|
||||
|
||||
files::writeGraph(config.GetPath(".osrm.hsgr"), checksum, query_graph, edge_filters);
|
||||
|
||||
files::writeCoreMarker(config.GetPath(".osrm.core"), cores);
|
||||
|
||||
TIMER_STOP(preparing);
|
||||
|
||||
util::Log() << "Preprocessing : " << TIMER_SEC(preparing) << " seconds";
|
||||
|
||||
@@ -11,11 +11,11 @@ namespace engine
|
||||
namespace routing_algorithms
|
||||
{
|
||||
|
||||
/// This is a striped down version of the general shortest path algorithm.
|
||||
/// This is a stripped 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
|
||||
/// necessary in case of vias, where the directions of the start node is constrained
|
||||
/// by the previous route.
|
||||
/// This variation is only an optimazation for graphs with slow queries, for example
|
||||
/// This variation is only an optimization for graphs with slow queries, for example
|
||||
/// not fully contracted graphs.
|
||||
template <typename Algorithm>
|
||||
InternalRouteResult directShortestPathSearch(SearchEngineData<Algorithm> &engine_working_data,
|
||||
@@ -64,11 +64,6 @@ InternalRouteResult directShortestPathSearch(SearchEngineData<Algorithm> &engine
|
||||
return extractRoute(facade, weight, phantom_nodes, unpacked_nodes, unpacked_edges);
|
||||
}
|
||||
|
||||
template InternalRouteResult
|
||||
directShortestPathSearch(SearchEngineData<corech::Algorithm> &engine_working_data,
|
||||
const DataFacade<corech::Algorithm> &facade,
|
||||
const PhantomNodes &phantom_nodes);
|
||||
|
||||
template InternalRouteResult
|
||||
directShortestPathSearch(SearchEngineData<ch::Algorithm> &engine_working_data,
|
||||
const DataFacade<ch::Algorithm> &facade,
|
||||
|
||||
@@ -420,6 +420,7 @@ SubMatchingList mapMatching(SearchEngineData<Algorithm> &engine_working_data,
|
||||
return sub_matchings;
|
||||
}
|
||||
|
||||
// CH
|
||||
template SubMatchingList
|
||||
mapMatching(SearchEngineData<ch::Algorithm> &engine_working_data,
|
||||
const DataFacade<ch::Algorithm> &facade,
|
||||
@@ -429,15 +430,7 @@ mapMatching(SearchEngineData<ch::Algorithm> &engine_working_data,
|
||||
const std::vector<boost::optional<double>> &trace_gps_precision,
|
||||
const bool allow_splitting);
|
||||
|
||||
template SubMatchingList
|
||||
mapMatching(SearchEngineData<corech::Algorithm> &engine_working_data,
|
||||
const DataFacade<corech::Algorithm> &facade,
|
||||
const CandidateLists &candidates_list,
|
||||
const std::vector<util::Coordinate> &trace_coordinates,
|
||||
const std::vector<unsigned> &trace_timestamps,
|
||||
const std::vector<boost::optional<double>> &trace_gps_precision,
|
||||
const bool allow_splitting);
|
||||
|
||||
// MLD
|
||||
template SubMatchingList
|
||||
mapMatching(SearchEngineData<mld::Algorithm> &engine_working_data,
|
||||
const DataFacade<mld::Algorithm> &facade,
|
||||
|
||||
@@ -192,237 +192,6 @@ double getNetworkDistance(SearchEngineData<Algorithm> &engine_working_data,
|
||||
}
|
||||
} // namespace ch
|
||||
|
||||
namespace corech
|
||||
{
|
||||
// Assumes that heaps are already setup correctly.
|
||||
// A forced loop might be necessary, if source and target are on the same segment.
|
||||
// If this is the case and the offsets of the respective direction are larger for the source
|
||||
// than the target
|
||||
// then a force loop is required (e.g. source_phantom.forward_segment_id ==
|
||||
// target_phantom.forward_segment_id
|
||||
// && source_phantom.GetForwardWeightPlusOffset() > target_phantom.GetForwardWeightPlusOffset())
|
||||
// requires
|
||||
// a force loop, if the heaps have been initialized with positive offsets.
|
||||
void search(SearchEngineData<Algorithm> &engine_working_data,
|
||||
const DataFacade<Algorithm> &facade,
|
||||
SearchEngineData<Algorithm>::QueryHeap &forward_heap,
|
||||
SearchEngineData<Algorithm>::QueryHeap &reverse_heap,
|
||||
EdgeWeight &weight,
|
||||
std::vector<NodeID> &packed_leg,
|
||||
const bool force_loop_forward,
|
||||
const bool force_loop_reverse,
|
||||
const PhantomNodes & /*phantom_nodes*/,
|
||||
EdgeWeight weight_upper_bound)
|
||||
{
|
||||
NodeID middle = SPECIAL_NODEID;
|
||||
weight = weight_upper_bound;
|
||||
|
||||
using CoreEntryPoint = std::tuple<NodeID, EdgeWeight, NodeID>;
|
||||
std::vector<CoreEntryPoint> forward_entry_points;
|
||||
std::vector<CoreEntryPoint> reverse_entry_points;
|
||||
|
||||
// get offset to account for offsets on phantom nodes on compressed edges
|
||||
const auto min_edge_offset = std::min(0, forward_heap.MinKey());
|
||||
// we only every insert negative offsets for nodes in the forward heap
|
||||
BOOST_ASSERT(reverse_heap.MinKey() >= 0);
|
||||
|
||||
// run two-Target Dijkstra routing step.
|
||||
while (0 < (forward_heap.Size() + reverse_heap.Size()))
|
||||
{
|
||||
if (!forward_heap.Empty())
|
||||
{
|
||||
if (facade.IsCoreNode(forward_heap.Min()))
|
||||
{
|
||||
const NodeID node = forward_heap.DeleteMin();
|
||||
const EdgeWeight key = forward_heap.GetKey(node);
|
||||
forward_entry_points.emplace_back(node, key, forward_heap.GetData(node).parent);
|
||||
}
|
||||
else
|
||||
{
|
||||
ch::routingStep<FORWARD_DIRECTION>(facade,
|
||||
forward_heap,
|
||||
reverse_heap,
|
||||
middle,
|
||||
weight,
|
||||
min_edge_offset,
|
||||
force_loop_forward,
|
||||
force_loop_reverse);
|
||||
}
|
||||
}
|
||||
if (!reverse_heap.Empty())
|
||||
{
|
||||
if (facade.IsCoreNode(reverse_heap.Min()))
|
||||
{
|
||||
const NodeID node = reverse_heap.DeleteMin();
|
||||
const EdgeWeight key = reverse_heap.GetKey(node);
|
||||
reverse_entry_points.emplace_back(node, key, reverse_heap.GetData(node).parent);
|
||||
}
|
||||
else
|
||||
{
|
||||
ch::routingStep<REVERSE_DIRECTION>(facade,
|
||||
reverse_heap,
|
||||
forward_heap,
|
||||
middle,
|
||||
weight,
|
||||
min_edge_offset,
|
||||
force_loop_reverse,
|
||||
force_loop_forward);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
const auto insertInCoreHeap = [](const CoreEntryPoint &p, auto &core_heap) {
|
||||
NodeID id;
|
||||
EdgeWeight weight;
|
||||
NodeID parent;
|
||||
// TODO this should use std::apply when we get c++17 support
|
||||
std::tie(id, weight, parent) = p;
|
||||
core_heap.Insert(id, weight, parent);
|
||||
};
|
||||
|
||||
engine_working_data.InitializeOrClearSecondThreadLocalStorage(facade.GetNumberOfNodes());
|
||||
|
||||
auto &forward_core_heap = *engine_working_data.forward_heap_2;
|
||||
auto &reverse_core_heap = *engine_working_data.reverse_heap_2;
|
||||
|
||||
for (const auto &p : forward_entry_points)
|
||||
{
|
||||
insertInCoreHeap(p, forward_core_heap);
|
||||
}
|
||||
|
||||
for (const auto &p : reverse_entry_points)
|
||||
{
|
||||
insertInCoreHeap(p, reverse_core_heap);
|
||||
}
|
||||
|
||||
// get offset to account for offsets on phantom nodes on compressed edges
|
||||
EdgeWeight min_core_edge_offset = 0;
|
||||
if (forward_core_heap.Size() > 0)
|
||||
{
|
||||
min_core_edge_offset = std::min(min_core_edge_offset, forward_core_heap.MinKey());
|
||||
}
|
||||
if (reverse_core_heap.Size() > 0 && reverse_core_heap.MinKey() < 0)
|
||||
{
|
||||
min_core_edge_offset = std::min(min_core_edge_offset, reverse_core_heap.MinKey());
|
||||
}
|
||||
BOOST_ASSERT(min_core_edge_offset <= 0);
|
||||
|
||||
// run two-target Dijkstra routing step on core with termination criterion
|
||||
while (0 < forward_core_heap.Size() && 0 < reverse_core_heap.Size() &&
|
||||
weight > (forward_core_heap.MinKey() + reverse_core_heap.MinKey()))
|
||||
{
|
||||
ch::routingStep<FORWARD_DIRECTION, ch::DISABLE_STALLING>(facade,
|
||||
forward_core_heap,
|
||||
reverse_core_heap,
|
||||
middle,
|
||||
weight,
|
||||
min_core_edge_offset,
|
||||
force_loop_forward,
|
||||
force_loop_reverse);
|
||||
|
||||
ch::routingStep<REVERSE_DIRECTION, ch::DISABLE_STALLING>(facade,
|
||||
reverse_core_heap,
|
||||
forward_core_heap,
|
||||
middle,
|
||||
weight,
|
||||
min_core_edge_offset,
|
||||
force_loop_reverse,
|
||||
force_loop_forward);
|
||||
}
|
||||
|
||||
// No path found for both target nodes?
|
||||
if (weight_upper_bound <= weight || SPECIAL_NODEID == middle)
|
||||
{
|
||||
weight = 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 != weight), "no path found");
|
||||
|
||||
// we need to unpack sub path from core heaps
|
||||
if (facade.IsCoreNode(middle))
|
||||
{
|
||||
if (weight != forward_core_heap.GetKey(middle) + reverse_core_heap.GetKey(middle))
|
||||
{
|
||||
// self loop
|
||||
BOOST_ASSERT(forward_core_heap.GetData(middle).parent == middle &&
|
||||
reverse_core_heap.GetData(middle).parent == middle);
|
||||
packed_leg.push_back(middle);
|
||||
packed_leg.push_back(middle);
|
||||
}
|
||||
else
|
||||
{
|
||||
std::vector<NodeID> packed_core_leg;
|
||||
ch::retrievePackedPathFromHeap(
|
||||
forward_core_heap, reverse_core_heap, middle, packed_core_leg);
|
||||
BOOST_ASSERT(packed_core_leg.size() > 0);
|
||||
ch::retrievePackedPathFromSingleHeap(forward_heap, packed_core_leg.front(), packed_leg);
|
||||
std::reverse(packed_leg.begin(), packed_leg.end());
|
||||
packed_leg.insert(packed_leg.end(), packed_core_leg.begin(), packed_core_leg.end());
|
||||
ch::retrievePackedPathFromSingleHeap(reverse_heap, packed_core_leg.back(), packed_leg);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (weight != forward_heap.GetKey(middle) + reverse_heap.GetKey(middle))
|
||||
{
|
||||
// self loop
|
||||
BOOST_ASSERT(forward_heap.GetData(middle).parent == middle &&
|
||||
reverse_heap.GetData(middle).parent == middle);
|
||||
packed_leg.push_back(middle);
|
||||
packed_leg.push_back(middle);
|
||||
}
|
||||
else
|
||||
{
|
||||
ch::retrievePackedPathFromHeap(forward_heap, reverse_heap, middle, packed_leg);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Requires the heaps for be empty
|
||||
// If heaps should be adjusted to be initialized outside of this function,
|
||||
// the addition of force_loop parameters might be required
|
||||
double getNetworkDistance(SearchEngineData<Algorithm> &engine_working_data,
|
||||
const DataFacade<Algorithm> &facade,
|
||||
SearchEngineData<Algorithm>::QueryHeap &forward_heap,
|
||||
SearchEngineData<Algorithm>::QueryHeap &reverse_heap,
|
||||
const PhantomNode &source_phantom,
|
||||
const PhantomNode &target_phantom,
|
||||
EdgeWeight weight_upper_bound)
|
||||
{
|
||||
forward_heap.Clear();
|
||||
reverse_heap.Clear();
|
||||
|
||||
insertNodesInHeaps(forward_heap, reverse_heap, {source_phantom, target_phantom});
|
||||
|
||||
EdgeWeight weight = INVALID_EDGE_WEIGHT;
|
||||
std::vector<NodeID> packed_path;
|
||||
search(engine_working_data,
|
||||
facade,
|
||||
forward_heap,
|
||||
reverse_heap,
|
||||
weight,
|
||||
packed_path,
|
||||
DO_NOT_FORCE_LOOPS,
|
||||
DO_NOT_FORCE_LOOPS,
|
||||
{source_phantom, target_phantom},
|
||||
weight_upper_bound);
|
||||
|
||||
if (weight == INVALID_EDGE_WEIGHT)
|
||||
return std::numeric_limits<double>::max();
|
||||
|
||||
std::vector<PathData> unpacked_path;
|
||||
ch::unpackPath(facade,
|
||||
packed_path.begin(),
|
||||
packed_path.end(),
|
||||
{source_phantom, target_phantom},
|
||||
unpacked_path);
|
||||
|
||||
return getPathDistance(facade, unpacked_path, source_phantom, target_phantom);
|
||||
}
|
||||
} // namespace corech
|
||||
|
||||
} // namespace routing_algorithms
|
||||
} // namespace engine
|
||||
} // namespace osrm
|
||||
|
||||
@@ -15,12 +15,6 @@ shortestPathSearch(SearchEngineData<ch::Algorithm> &engine_working_data,
|
||||
const std::vector<PhantomNodes> &phantom_nodes_vector,
|
||||
const boost::optional<bool> continue_straight_at_waypoint);
|
||||
|
||||
template InternalRouteResult
|
||||
shortestPathSearch(SearchEngineData<corech::Algorithm> &engine_working_data,
|
||||
const DataFacade<corech::Algorithm> &facade,
|
||||
const std::vector<PhantomNodes> &phantom_nodes_vector,
|
||||
const boost::optional<bool> continue_straight_at_waypoint);
|
||||
|
||||
template InternalRouteResult
|
||||
shortestPathSearch(SearchEngineData<mld::Algorithm> &engine_working_data,
|
||||
const DataFacade<mld::Algorithm> &facade,
|
||||
|
||||
+3
-21
@@ -19,7 +19,6 @@ namespace osrm
|
||||
OSRM::OSRM(engine::EngineConfig &config)
|
||||
{
|
||||
using CH = engine::routing_algorithms::ch::Algorithm;
|
||||
using CoreCH = engine::routing_algorithms::corech::Algorithm;
|
||||
using MLD = engine::routing_algorithms::mld::Algorithm;
|
||||
|
||||
// First, check that necessary core data is available
|
||||
@@ -44,26 +43,12 @@ OSRM::OSRM(engine::EngineConfig &config)
|
||||
// Now, check that the algorithm requested can be used with the data
|
||||
// that's available.
|
||||
|
||||
if (config.algorithm == EngineConfig::Algorithm::CoreCH ||
|
||||
config.algorithm == EngineConfig::Algorithm::CH)
|
||||
if (config.algorithm == EngineConfig::Algorithm::CH)
|
||||
{
|
||||
bool corech_compatible = engine::Engine<CoreCH>::CheckCompatibility(config);
|
||||
bool ch_compatible = engine::Engine<CH>::CheckCompatibility(config);
|
||||
|
||||
// Activate CoreCH if we can because it is faster
|
||||
if (config.algorithm == EngineConfig::Algorithm::CH && corech_compatible)
|
||||
{
|
||||
config.algorithm = EngineConfig::Algorithm::CoreCH;
|
||||
}
|
||||
|
||||
// throw error if dataset is not usable with CoreCH or CH
|
||||
if (config.algorithm == EngineConfig::Algorithm::CoreCH && !corech_compatible)
|
||||
{
|
||||
throw util::RuntimeError("Dataset is not compatible with CoreCH.",
|
||||
ErrorCode::IncompatibleDataset,
|
||||
SOURCE_REF);
|
||||
}
|
||||
else if (config.algorithm == EngineConfig::Algorithm::CH && !ch_compatible)
|
||||
// throw error if dataset is not usable with CH
|
||||
if (config.algorithm == EngineConfig::Algorithm::CH && !ch_compatible)
|
||||
{
|
||||
throw util::exception("Dataset is not compatible with CH");
|
||||
}
|
||||
@@ -83,9 +68,6 @@ OSRM::OSRM(engine::EngineConfig &config)
|
||||
case EngineConfig::Algorithm::CH:
|
||||
engine_ = std::make_unique<engine::Engine<CH>>(config);
|
||||
break;
|
||||
case EngineConfig::Algorithm::CoreCH:
|
||||
engine_ = std::make_unique<engine::Engine<CoreCH>>(config);
|
||||
break;
|
||||
case EngineConfig::Algorithm::MLD:
|
||||
engine_ = std::make_unique<engine::Engine<MLD>>(config);
|
||||
break;
|
||||
|
||||
@@ -913,21 +913,6 @@ void Storage::PopulateData(const DataLayout &layout, char *memory_ptr)
|
||||
layout.num_entries[DataLayout::R_SEARCH_TREE_LEVELS]);
|
||||
}
|
||||
|
||||
if (boost::filesystem::exists(config.GetPath(".osrm.core")))
|
||||
{
|
||||
std::vector<util::vector_view<bool>> cores;
|
||||
for (auto index : util::irange<std::size_t>(0, NUM_METRICS))
|
||||
{
|
||||
auto block_id =
|
||||
static_cast<DataLayout::BlockID>(storage::DataLayout::CH_CORE_MARKER_0 + index);
|
||||
auto data_ptr = layout.GetBlockPtr<unsigned, true>(memory_ptr, block_id);
|
||||
auto num_entries = layout.num_entries[block_id];
|
||||
cores.emplace_back(data_ptr, num_entries);
|
||||
}
|
||||
|
||||
contractor::files::readCoreMarker(config.GetPath(".osrm.core"), cores);
|
||||
}
|
||||
|
||||
// load profile properties
|
||||
{
|
||||
const auto profile_properties_ptr = layout.GetBlockPtr<extractor::ProfileProperties, true>(
|
||||
|
||||
@@ -49,7 +49,7 @@ return_code parseArguments(int argc,
|
||||
"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]")(
|
||||
"Percentage of the graph (in vertices) to contract [0..1]. Will always be 1.0")(
|
||||
"segment-speed-file",
|
||||
boost::program_options::value<std::vector<std::string>>(
|
||||
&contractor_config.updater_config.segment_speed_lookup_paths)
|
||||
|
||||
Reference in New Issue
Block a user