fallback to CH, when coreCH used
This commit is contained in:
parent
7cf7c46939
commit
2a13f9d10b
@ -45,7 +45,7 @@ struct ContractorConfig final : storage::IOConfig
|
|||||||
ContractorConfig()
|
ContractorConfig()
|
||||||
: IOConfig({".osrm.ebg", ".osrm.ebg_nodes", ".osrm.properties"},
|
: IOConfig({".osrm.ebg", ".osrm.ebg_nodes", ".osrm.properties"},
|
||||||
{},
|
{},
|
||||||
{".osrm.level", ".osrm.core", ".osrm.hsgr", ".osrm.enw"}),
|
{".osrm.hsgr", ".osrm.enw"}),
|
||||||
requested_num_threads(0)
|
requested_num_threads(0)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
@ -65,6 +65,7 @@ struct ContractorConfig final : storage::IOConfig
|
|||||||
|
|
||||||
unsigned requested_num_threads;
|
unsigned requested_num_threads;
|
||||||
|
|
||||||
|
// Deprecated
|
||||||
// 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.
|
||||||
// The remaining vertices form the core of the hierarchy
|
// The remaining vertices form the core of the hierarchy
|
||||||
|
@ -14,37 +14,6 @@ namespace contractor
|
|||||||
{
|
{
|
||||||
namespace files
|
namespace files
|
||||||
{
|
{
|
||||||
// reads .osrm.core
|
|
||||||
template <typename CoreVectorT>
|
|
||||||
void readCoreMarker(const boost::filesystem::path &path, std::vector<CoreVectorT> &cores)
|
|
||||||
{
|
|
||||||
static_assert(util::is_view_or_vector<bool, CoreVectorT>::value,
|
|
||||||
"cores must be a vector of boolean vectors");
|
|
||||||
storage::io::FileReader reader(path, storage::io::FileReader::VerifyFingerprint);
|
|
||||||
|
|
||||||
auto num_cores = reader.ReadElementCount64();
|
|
||||||
cores.resize(num_cores);
|
|
||||||
for (const auto index : util::irange<std::size_t>(0, num_cores))
|
|
||||||
{
|
|
||||||
storage::serialization::read(reader, cores[index]);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// writes .osrm.core
|
|
||||||
template <typename CoreVectorT>
|
|
||||||
void writeCoreMarker(const boost::filesystem::path &path, const std::vector<CoreVectorT> &cores)
|
|
||||||
{
|
|
||||||
static_assert(util::is_view_or_vector<bool, CoreVectorT>::value,
|
|
||||||
"cores must be a vector of boolean vectors");
|
|
||||||
storage::io::FileWriter writer(path, storage::io::FileWriter::GenerateFingerprint);
|
|
||||||
|
|
||||||
writer.WriteElementCount64(cores.size());
|
|
||||||
for (const auto &core : cores)
|
|
||||||
{
|
|
||||||
storage::serialization::write(writer, core);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// reads .osrm.hsgr file
|
// reads .osrm.hsgr file
|
||||||
template <typename QueryGraphT, typename EdgeFilterT>
|
template <typename QueryGraphT, typename EdgeFilterT>
|
||||||
inline void readGraph(const boost::filesystem::path &path,
|
inline void readGraph(const boost::filesystem::path &path,
|
||||||
@ -96,24 +65,6 @@ inline void writeGraph(const boost::filesystem::path &path,
|
|||||||
storage::serialization::write(writer, filter);
|
storage::serialization::write(writer, filter);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// reads .levels file
|
|
||||||
inline void readLevels(const boost::filesystem::path &path, std::vector<float> &node_levels)
|
|
||||||
{
|
|
||||||
const auto fingerprint = storage::io::FileReader::VerifyFingerprint;
|
|
||||||
storage::io::FileReader reader{path, fingerprint};
|
|
||||||
|
|
||||||
storage::serialization::read(reader, node_levels);
|
|
||||||
}
|
|
||||||
|
|
||||||
// writes .levels file
|
|
||||||
inline void writeLevels(const boost::filesystem::path &path, const std::vector<float> &node_levels)
|
|
||||||
{
|
|
||||||
const auto fingerprint = storage::io::FileWriter::GenerateFingerprint;
|
|
||||||
storage::io::FileWriter writer{path, fingerprint};
|
|
||||||
|
|
||||||
storage::serialization::write(writer, node_levels);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -17,13 +17,6 @@ struct Algorithm final
|
|||||||
{
|
{
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
// Contraction Hiearchy with core
|
|
||||||
namespace corech
|
|
||||||
{
|
|
||||||
struct Algorithm final
|
|
||||||
{
|
|
||||||
};
|
|
||||||
}
|
|
||||||
// Multi-Level Dijkstra
|
// Multi-Level Dijkstra
|
||||||
namespace mld
|
namespace mld
|
||||||
{
|
{
|
||||||
@ -35,7 +28,6 @@ struct Algorithm final
|
|||||||
// Algorithm names
|
// Algorithm names
|
||||||
template <typename AlgorithmT> const char *name();
|
template <typename AlgorithmT> const char *name();
|
||||||
template <> inline const char *name<ch::Algorithm>() { return "CH"; }
|
template <> inline const char *name<ch::Algorithm>() { return "CH"; }
|
||||||
template <> inline const char *name<corech::Algorithm>() { return "CoreCH"; }
|
|
||||||
template <> inline const char *name<mld::Algorithm>() { return "MLD"; }
|
template <> inline const char *name<mld::Algorithm>() { return "MLD"; }
|
||||||
|
|
||||||
template <typename AlgorithmT> struct HasAlternativePathSearch final : std::false_type
|
template <typename AlgorithmT> struct HasAlternativePathSearch final : std::false_type
|
||||||
@ -83,24 +75,6 @@ template <> struct HasExcludeFlags<ch::Algorithm> final : std::true_type
|
|||||||
{
|
{
|
||||||
};
|
};
|
||||||
|
|
||||||
// Algorithms supported by Contraction Hierarchies with core
|
|
||||||
// the rest is disabled because of performance reasons
|
|
||||||
template <> struct HasShortestPathSearch<corech::Algorithm> final : std::true_type
|
|
||||||
{
|
|
||||||
};
|
|
||||||
template <> struct HasDirectShortestPathSearch<corech::Algorithm> final : std::true_type
|
|
||||||
{
|
|
||||||
};
|
|
||||||
template <> struct HasMapMatching<corech::Algorithm> final : std::true_type
|
|
||||||
{
|
|
||||||
};
|
|
||||||
template <> struct HasGetTileTurns<corech::Algorithm> final : std::true_type
|
|
||||||
{
|
|
||||||
};
|
|
||||||
template <> struct HasExcludeFlags<corech::Algorithm> final : std::true_type
|
|
||||||
{
|
|
||||||
};
|
|
||||||
|
|
||||||
// Algorithms supported by Multi-Level Dijkstra
|
// Algorithms supported by Multi-Level Dijkstra
|
||||||
template <> struct HasAlternativePathSearch<mld::Algorithm> final : std::true_type
|
template <> struct HasAlternativePathSearch<mld::Algorithm> final : std::true_type
|
||||||
{
|
{
|
||||||
|
@ -20,7 +20,6 @@ namespace datafacade
|
|||||||
|
|
||||||
// Namespace local aliases for algorithms
|
// Namespace local aliases for algorithms
|
||||||
using CH = routing_algorithms::ch::Algorithm;
|
using CH = routing_algorithms::ch::Algorithm;
|
||||||
using CoreCH = routing_algorithms::corech::Algorithm;
|
|
||||||
using MLD = routing_algorithms::mld::Algorithm;
|
using MLD = routing_algorithms::mld::Algorithm;
|
||||||
|
|
||||||
template <typename AlgorithmT> class AlgorithmDataFacade;
|
template <typename AlgorithmT> class AlgorithmDataFacade;
|
||||||
@ -57,14 +56,6 @@ template <> class AlgorithmDataFacade<CH>
|
|||||||
const std::function<bool(EdgeData)> filter) const = 0;
|
const std::function<bool(EdgeData)> filter) const = 0;
|
||||||
};
|
};
|
||||||
|
|
||||||
template <> class AlgorithmDataFacade<CoreCH>
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
using EdgeData = contractor::QueryEdge::EdgeData;
|
|
||||||
|
|
||||||
virtual bool IsCoreNode(const NodeID id) const = 0;
|
|
||||||
};
|
|
||||||
|
|
||||||
template <> class AlgorithmDataFacade<MLD>
|
template <> class AlgorithmDataFacade<MLD>
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
|
@ -166,50 +166,6 @@ class ContiguousInternalMemoryAlgorithmDataFacade<CH> : public datafacade::Algor
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
template <>
|
|
||||||
class ContiguousInternalMemoryAlgorithmDataFacade<CoreCH>
|
|
||||||
: public datafacade::AlgorithmDataFacade<CoreCH>
|
|
||||||
{
|
|
||||||
private:
|
|
||||||
util::vector_view<bool> m_is_core_node;
|
|
||||||
|
|
||||||
// allocator that keeps the allocation data
|
|
||||||
std::shared_ptr<ContiguousBlockAllocator> allocator;
|
|
||||||
|
|
||||||
void InitializeCoreInformationPointer(storage::DataLayout &data_layout,
|
|
||||||
char *memory_block,
|
|
||||||
const std::size_t exclude_index)
|
|
||||||
{
|
|
||||||
auto core_block_id = static_cast<storage::DataLayout::BlockID>(
|
|
||||||
storage::DataLayout::CH_CORE_MARKER_0 + exclude_index);
|
|
||||||
auto core_marker_ptr = data_layout.GetBlockPtr<unsigned>(memory_block, core_block_id);
|
|
||||||
util::vector_view<bool> is_core_node(core_marker_ptr,
|
|
||||||
data_layout.num_entries[core_block_id]);
|
|
||||||
m_is_core_node = std::move(is_core_node);
|
|
||||||
}
|
|
||||||
|
|
||||||
public:
|
|
||||||
ContiguousInternalMemoryAlgorithmDataFacade(
|
|
||||||
std::shared_ptr<ContiguousBlockAllocator> allocator_, const std::size_t exclude_index)
|
|
||||||
: allocator(std::move(allocator_))
|
|
||||||
{
|
|
||||||
InitializeInternalPointers(allocator->GetLayout(), allocator->GetMemory(), exclude_index);
|
|
||||||
}
|
|
||||||
|
|
||||||
void InitializeInternalPointers(storage::DataLayout &data_layout,
|
|
||||||
char *memory_block,
|
|
||||||
const std::size_t exclude_index)
|
|
||||||
{
|
|
||||||
InitializeCoreInformationPointer(data_layout, memory_block, exclude_index);
|
|
||||||
}
|
|
||||||
|
|
||||||
bool IsCoreNode(const NodeID id) const override final
|
|
||||||
{
|
|
||||||
BOOST_ASSERT(m_is_core_node.empty() || id < m_is_core_node.size());
|
|
||||||
return !m_is_core_node.empty() || m_is_core_node[id];
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This base class implements the Datafacade interface for accessing
|
* This base class implements the Datafacade interface for accessing
|
||||||
* data that's stored in a single large block of memory (RAM).
|
* data that's stored in a single large block of memory (RAM).
|
||||||
@ -948,21 +904,6 @@ class ContiguousInternalMemoryDataFacade<CH>
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
template <>
|
|
||||||
class ContiguousInternalMemoryDataFacade<CoreCH> final
|
|
||||||
: public ContiguousInternalMemoryDataFacade<CH>,
|
|
||||||
public ContiguousInternalMemoryAlgorithmDataFacade<CoreCH>
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
ContiguousInternalMemoryDataFacade(std::shared_ptr<ContiguousBlockAllocator> allocator,
|
|
||||||
const std::size_t exclude_index)
|
|
||||||
: ContiguousInternalMemoryDataFacade<CH>(allocator, exclude_index),
|
|
||||||
ContiguousInternalMemoryAlgorithmDataFacade<CoreCH>(allocator, exclude_index)
|
|
||||||
|
|
||||||
{
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
template <> class ContiguousInternalMemoryAlgorithmDataFacade<MLD> : public AlgorithmDataFacade<MLD>
|
template <> class ContiguousInternalMemoryAlgorithmDataFacade<MLD> : public AlgorithmDataFacade<MLD>
|
||||||
{
|
{
|
||||||
// MLD data
|
// MLD data
|
||||||
|
@ -160,38 +160,6 @@ bool Engine<routing_algorithms::ch::Algorithm>::CheckCompatibility(const EngineC
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
template <>
|
|
||||||
bool Engine<routing_algorithms::corech::Algorithm>::CheckCompatibility(const EngineConfig &config)
|
|
||||||
{
|
|
||||||
if (!Engine<routing_algorithms::ch::Algorithm>::CheckCompatibility(config))
|
|
||||||
{
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (config.use_shared_memory)
|
|
||||||
{
|
|
||||||
storage::SharedMonitor<storage::SharedDataTimestamp> barrier;
|
|
||||||
using mutex_type = typename decltype(barrier)::mutex_type;
|
|
||||||
boost::interprocess::scoped_lock<mutex_type> current_region_lock(barrier.get_mutex());
|
|
||||||
|
|
||||||
auto mem = storage::makeSharedMemory(barrier.data().region);
|
|
||||||
auto layout = reinterpret_cast<storage::DataLayout *>(mem->Ptr());
|
|
||||||
return layout->GetBlockSize(storage::DataLayout::CH_CORE_MARKER_0) >
|
|
||||||
sizeof(std::uint64_t) + sizeof(util::FingerPrint);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
if (!boost::filesystem::exists(config.storage_config.GetPath(".osrm.core")))
|
|
||||||
return false;
|
|
||||||
storage::io::FileReader in(config.storage_config.GetPath(".osrm.core"),
|
|
||||||
storage::io::FileReader::VerifyFingerprint);
|
|
||||||
in.ReadElementCount64(); // number of core markers
|
|
||||||
const auto number_of_core_markers = in.ReadElementCount64();
|
|
||||||
|
|
||||||
return number_of_core_markers > 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
template <>
|
template <>
|
||||||
bool Engine<routing_algorithms::mld::Algorithm>::CheckCompatibility(const EngineConfig &config)
|
bool Engine<routing_algorithms::mld::Algorithm>::CheckCompatibility(const EngineConfig &config)
|
||||||
{
|
{
|
||||||
|
@ -217,24 +217,6 @@ inline std::vector<routing_algorithms::TurnData> RoutingAlgorithms<Algorithm>::G
|
|||||||
return routing_algorithms::getTileTurns(*facade, edges, sorted_edge_indexes);
|
return routing_algorithms::getTileTurns(*facade, edges, sorted_edge_indexes);
|
||||||
}
|
}
|
||||||
|
|
||||||
// CoreCH overrides
|
|
||||||
template <>
|
|
||||||
InternalManyRoutesResult inline RoutingAlgorithms<
|
|
||||||
routing_algorithms::corech::Algorithm>::AlternativePathSearch(const PhantomNodes &,
|
|
||||||
unsigned) const
|
|
||||||
{
|
|
||||||
throw util::exception("AlternativePathSearch is disabled due to performance reasons");
|
|
||||||
}
|
|
||||||
|
|
||||||
template <>
|
|
||||||
inline std::vector<EdgeDuration>
|
|
||||||
RoutingAlgorithms<routing_algorithms::corech::Algorithm>::ManyToManySearch(
|
|
||||||
const std::vector<PhantomNode> &,
|
|
||||||
const std::vector<std::size_t> &,
|
|
||||||
const std::vector<std::size_t> &) const
|
|
||||||
{
|
|
||||||
throw util::exception("ManyToManySearch is disabled due to performance reasons");
|
|
||||||
}
|
|
||||||
} // ns engine
|
} // ns engine
|
||||||
} // ns osrm
|
} // ns osrm
|
||||||
|
|
||||||
|
@ -15,11 +15,11 @@ namespace engine
|
|||||||
namespace routing_algorithms
|
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
|
/// 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.
|
/// 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.
|
/// not fully contracted graphs.
|
||||||
template <typename Algorithm>
|
template <typename Algorithm>
|
||||||
InternalRouteResult directShortestPathSearch(SearchEngineData<Algorithm> &engine_working_data,
|
InternalRouteResult directShortestPathSearch(SearchEngineData<Algorithm> &engine_working_data,
|
||||||
|
@ -375,52 +375,6 @@ double getNetworkDistance(SearchEngineData<Algorithm> &engine_working_data,
|
|||||||
int duration_upper_bound = INVALID_EDGE_WEIGHT);
|
int duration_upper_bound = INVALID_EDGE_WEIGHT);
|
||||||
|
|
||||||
} // namespace ch
|
} // 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<corech::Algorithm> &facade,
|
|
||||||
SearchEngineData<ch::Algorithm>::QueryHeap &forward_heap,
|
|
||||||
SearchEngineData<ch::Algorithm>::QueryHeap &reverse_heap,
|
|
||||||
int &weight,
|
|
||||||
std::vector<NodeID> &packed_leg,
|
|
||||||
const bool force_loop_forward,
|
|
||||||
const bool force_loop_reverse,
|
|
||||||
const PhantomNodes &phantom_nodes,
|
|
||||||
int duration_upper_bound = INVALID_EDGE_WEIGHT);
|
|
||||||
|
|
||||||
// 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<corech::Algorithm> &facade,
|
|
||||||
SearchEngineData<ch::Algorithm>::QueryHeap &forward_heap,
|
|
||||||
SearchEngineData<ch::Algorithm>::QueryHeap &reverse_heap,
|
|
||||||
const PhantomNode &source_phantom,
|
|
||||||
const PhantomNode &target_phantom,
|
|
||||||
int duration_upper_bound = INVALID_EDGE_WEIGHT);
|
|
||||||
|
|
||||||
template <typename RandomIter, typename FacadeT>
|
|
||||||
void unpackPath(const FacadeT &facade,
|
|
||||||
RandomIter packed_path_begin,
|
|
||||||
RandomIter packed_path_end,
|
|
||||||
const PhantomNodes &phantom_nodes,
|
|
||||||
std::vector<PathData> &unpacked_path)
|
|
||||||
{
|
|
||||||
return ch::unpackPath(facade, packed_path_begin, packed_path_end, phantom_nodes, unpacked_path);
|
|
||||||
}
|
|
||||||
|
|
||||||
} // namespace corech
|
|
||||||
|
|
||||||
} // namespace routing_algorithms
|
} // namespace routing_algorithms
|
||||||
} // namespace engine
|
} // namespace engine
|
||||||
} // namespace osrm
|
} // namespace osrm
|
||||||
|
@ -64,12 +64,6 @@ template <> struct SearchEngineData<routing_algorithms::ch::Algorithm>
|
|||||||
void InitializeOrClearManyToManyThreadLocalStorage(unsigned number_of_nodes);
|
void InitializeOrClearManyToManyThreadLocalStorage(unsigned number_of_nodes);
|
||||||
};
|
};
|
||||||
|
|
||||||
template <>
|
|
||||||
struct SearchEngineData<routing_algorithms::corech::Algorithm>
|
|
||||||
: public SearchEngineData<routing_algorithms::ch::Algorithm>
|
|
||||||
{
|
|
||||||
};
|
|
||||||
|
|
||||||
struct MultiLayerDijkstraHeapData
|
struct MultiLayerDijkstraHeapData
|
||||||
{
|
{
|
||||||
NodeID parent;
|
NodeID parent;
|
||||||
|
@ -42,9 +42,10 @@ namespace contractor
|
|||||||
|
|
||||||
int Contractor::Run()
|
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)
|
if (config.use_cached_priority)
|
||||||
@ -104,8 +105,6 @@ int Contractor::Run()
|
|||||||
|
|
||||||
files::writeGraph(config.GetPath(".osrm.hsgr"), checksum, query_graph, edge_filters);
|
files::writeGraph(config.GetPath(".osrm.hsgr"), checksum, query_graph, edge_filters);
|
||||||
|
|
||||||
files::writeCoreMarker(config.GetPath(".osrm.core"), cores);
|
|
||||||
|
|
||||||
TIMER_STOP(preparing);
|
TIMER_STOP(preparing);
|
||||||
|
|
||||||
util::Log() << "Preprocessing : " << TIMER_SEC(preparing) << " seconds";
|
util::Log() << "Preprocessing : " << TIMER_SEC(preparing) << " seconds";
|
||||||
|
@ -11,11 +11,11 @@ namespace engine
|
|||||||
namespace routing_algorithms
|
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
|
/// 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.
|
/// 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.
|
/// not fully contracted graphs.
|
||||||
template <typename Algorithm>
|
template <typename Algorithm>
|
||||||
InternalRouteResult directShortestPathSearch(SearchEngineData<Algorithm> &engine_working_data,
|
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);
|
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
|
template InternalRouteResult
|
||||||
directShortestPathSearch(SearchEngineData<ch::Algorithm> &engine_working_data,
|
directShortestPathSearch(SearchEngineData<ch::Algorithm> &engine_working_data,
|
||||||
const DataFacade<ch::Algorithm> &facade,
|
const DataFacade<ch::Algorithm> &facade,
|
||||||
|
@ -420,6 +420,7 @@ SubMatchingList mapMatching(SearchEngineData<Algorithm> &engine_working_data,
|
|||||||
return sub_matchings;
|
return sub_matchings;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// CH
|
||||||
template SubMatchingList
|
template SubMatchingList
|
||||||
mapMatching(SearchEngineData<ch::Algorithm> &engine_working_data,
|
mapMatching(SearchEngineData<ch::Algorithm> &engine_working_data,
|
||||||
const DataFacade<ch::Algorithm> &facade,
|
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 std::vector<boost::optional<double>> &trace_gps_precision,
|
||||||
const bool allow_splitting);
|
const bool allow_splitting);
|
||||||
|
|
||||||
template SubMatchingList
|
// MLD
|
||||||
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);
|
|
||||||
|
|
||||||
template SubMatchingList
|
template SubMatchingList
|
||||||
mapMatching(SearchEngineData<mld::Algorithm> &engine_working_data,
|
mapMatching(SearchEngineData<mld::Algorithm> &engine_working_data,
|
||||||
const DataFacade<mld::Algorithm> &facade,
|
const DataFacade<mld::Algorithm> &facade,
|
||||||
|
@ -192,237 +192,6 @@ double getNetworkDistance(SearchEngineData<Algorithm> &engine_working_data,
|
|||||||
}
|
}
|
||||||
} // namespace ch
|
} // 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 routing_algorithms
|
||||||
} // namespace engine
|
} // namespace engine
|
||||||
} // namespace osrm
|
} // namespace osrm
|
||||||
|
@ -15,12 +15,6 @@ shortestPathSearch(SearchEngineData<ch::Algorithm> &engine_working_data,
|
|||||||
const std::vector<PhantomNodes> &phantom_nodes_vector,
|
const std::vector<PhantomNodes> &phantom_nodes_vector,
|
||||||
const boost::optional<bool> continue_straight_at_waypoint);
|
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
|
template InternalRouteResult
|
||||||
shortestPathSearch(SearchEngineData<mld::Algorithm> &engine_working_data,
|
shortestPathSearch(SearchEngineData<mld::Algorithm> &engine_working_data,
|
||||||
const DataFacade<mld::Algorithm> &facade,
|
const DataFacade<mld::Algorithm> &facade,
|
||||||
|
@ -19,7 +19,6 @@ namespace osrm
|
|||||||
OSRM::OSRM(engine::EngineConfig &config)
|
OSRM::OSRM(engine::EngineConfig &config)
|
||||||
{
|
{
|
||||||
using CH = engine::routing_algorithms::ch::Algorithm;
|
using CH = engine::routing_algorithms::ch::Algorithm;
|
||||||
using CoreCH = engine::routing_algorithms::corech::Algorithm;
|
|
||||||
using MLD = engine::routing_algorithms::mld::Algorithm;
|
using MLD = engine::routing_algorithms::mld::Algorithm;
|
||||||
|
|
||||||
// First, check that necessary core data is available
|
// 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
|
// Now, check that the algorithm requested can be used with the data
|
||||||
// that's available.
|
// that's available.
|
||||||
|
|
||||||
if (config.algorithm == EngineConfig::Algorithm::CoreCH ||
|
if (config.algorithm == EngineConfig::Algorithm::CH)
|
||||||
config.algorithm == EngineConfig::Algorithm::CH)
|
|
||||||
{
|
{
|
||||||
bool corech_compatible = engine::Engine<CoreCH>::CheckCompatibility(config);
|
|
||||||
bool ch_compatible = engine::Engine<CH>::CheckCompatibility(config);
|
bool ch_compatible = engine::Engine<CH>::CheckCompatibility(config);
|
||||||
|
|
||||||
// Activate CoreCH if we can because it is faster
|
// throw error if dataset is not usable with CH
|
||||||
if (config.algorithm == EngineConfig::Algorithm::CH && corech_compatible)
|
if (config.algorithm == EngineConfig::Algorithm::CH && !ch_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 util::exception("Dataset is not compatible with CH");
|
throw util::exception("Dataset is not compatible with CH");
|
||||||
}
|
}
|
||||||
@ -83,9 +68,6 @@ OSRM::OSRM(engine::EngineConfig &config)
|
|||||||
case EngineConfig::Algorithm::CH:
|
case EngineConfig::Algorithm::CH:
|
||||||
engine_ = std::make_unique<engine::Engine<CH>>(config);
|
engine_ = std::make_unique<engine::Engine<CH>>(config);
|
||||||
break;
|
break;
|
||||||
case EngineConfig::Algorithm::CoreCH:
|
|
||||||
engine_ = std::make_unique<engine::Engine<CoreCH>>(config);
|
|
||||||
break;
|
|
||||||
case EngineConfig::Algorithm::MLD:
|
case EngineConfig::Algorithm::MLD:
|
||||||
engine_ = std::make_unique<engine::Engine<MLD>>(config);
|
engine_ = std::make_unique<engine::Engine<MLD>>(config);
|
||||||
break;
|
break;
|
||||||
|
@ -913,21 +913,6 @@ void Storage::PopulateData(const DataLayout &layout, char *memory_ptr)
|
|||||||
layout.num_entries[DataLayout::R_SEARCH_TREE_LEVELS]);
|
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
|
// load profile properties
|
||||||
{
|
{
|
||||||
const auto profile_properties_ptr = layout.GetBlockPtr<extractor::ProfileProperties, true>(
|
const auto profile_properties_ptr = layout.GetBlockPtr<extractor::ProfileProperties, true>(
|
||||||
|
@ -49,7 +49,7 @@ return_code parseArguments(int argc,
|
|||||||
"Number of threads to use")(
|
"Number of threads to use")(
|
||||||
"core,k",
|
"core,k",
|
||||||
boost::program_options::value<double>(&contractor_config.core_factor)->default_value(1.0),
|
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",
|
"segment-speed-file",
|
||||||
boost::program_options::value<std::vector<std::string>>(
|
boost::program_options::value<std::vector<std::string>>(
|
||||||
&contractor_config.updater_config.segment_speed_lookup_paths)
|
&contractor_config.updater_config.segment_speed_lookup_paths)
|
||||||
|
@ -15,14 +15,6 @@ BOOST_AUTO_TEST_CASE(test_incompatible_with_mld)
|
|||||||
osrm::exception);
|
osrm::exception);
|
||||||
}
|
}
|
||||||
|
|
||||||
BOOST_AUTO_TEST_CASE(test_incompatible_with_corech)
|
|
||||||
{
|
|
||||||
// Note - CH-only data can't be used with the CoreCH algorithm
|
|
||||||
BOOST_CHECK_THROW(
|
|
||||||
getOSRM(OSRM_TEST_DATA_DIR "/ch/monaco.osrm", osrm::EngineConfig::Algorithm::CoreCH),
|
|
||||||
osrm::exception);
|
|
||||||
}
|
|
||||||
|
|
||||||
BOOST_AUTO_TEST_CASE(test_incompatible_with_ch)
|
BOOST_AUTO_TEST_CASE(test_incompatible_with_ch)
|
||||||
{
|
{
|
||||||
// Can't use the CH algorithm with MLD data
|
// Can't use the CH algorithm with MLD data
|
||||||
|
@ -300,14 +300,6 @@ BOOST_AUTO_TEST_CASE(test_tile_ch)
|
|||||||
validate_tile(osrm);
|
validate_tile(osrm);
|
||||||
}
|
}
|
||||||
|
|
||||||
BOOST_AUTO_TEST_CASE(test_tile_corech)
|
|
||||||
{
|
|
||||||
using namespace osrm;
|
|
||||||
auto osrm =
|
|
||||||
getOSRM(OSRM_TEST_DATA_DIR "/corech/monaco.osrm", osrm::EngineConfig::Algorithm::CoreCH);
|
|
||||||
validate_tile(osrm);
|
|
||||||
}
|
|
||||||
|
|
||||||
BOOST_AUTO_TEST_CASE(test_tile_mld)
|
BOOST_AUTO_TEST_CASE(test_tile_mld)
|
||||||
{
|
{
|
||||||
using namespace osrm;
|
using namespace osrm;
|
||||||
@ -551,15 +543,6 @@ BOOST_AUTO_TEST_CASE(test_tile_turns_ch)
|
|||||||
test_tile_turns(osrm);
|
test_tile_turns(osrm);
|
||||||
}
|
}
|
||||||
|
|
||||||
BOOST_AUTO_TEST_CASE(test_tile_turns_corech)
|
|
||||||
{
|
|
||||||
using namespace osrm;
|
|
||||||
auto osrm =
|
|
||||||
getOSRM(OSRM_TEST_DATA_DIR "/corech/monaco.osrm", osrm::EngineConfig::Algorithm::CoreCH);
|
|
||||||
|
|
||||||
test_tile_turns(osrm);
|
|
||||||
}
|
|
||||||
|
|
||||||
BOOST_AUTO_TEST_CASE(test_tile_turns_mld)
|
BOOST_AUTO_TEST_CASE(test_tile_turns_mld)
|
||||||
{
|
{
|
||||||
using namespace osrm;
|
using namespace osrm;
|
||||||
|
@ -308,30 +308,11 @@ class MockAlgorithmDataFacade<engine::datafacade::CH>
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
template <>
|
|
||||||
class MockAlgorithmDataFacade<engine::datafacade::CoreCH>
|
|
||||||
: public engine::datafacade::AlgorithmDataFacade<engine::datafacade::CoreCH>
|
|
||||||
{
|
|
||||||
private:
|
|
||||||
EdgeData foo;
|
|
||||||
|
|
||||||
public:
|
|
||||||
bool IsCoreNode(const NodeID /* id */) const override { return false; }
|
|
||||||
};
|
|
||||||
|
|
||||||
template <typename AlgorithmT>
|
template <typename AlgorithmT>
|
||||||
class MockDataFacade final : public MockBaseDataFacade, public MockAlgorithmDataFacade<AlgorithmT>
|
class MockDataFacade final : public MockBaseDataFacade, public MockAlgorithmDataFacade<AlgorithmT>
|
||||||
{
|
{
|
||||||
};
|
};
|
||||||
|
|
||||||
template <>
|
|
||||||
class MockDataFacade<engine::datafacade::CoreCH> final
|
|
||||||
: public MockBaseDataFacade,
|
|
||||||
public MockAlgorithmDataFacade<engine::datafacade::CH>,
|
|
||||||
public MockAlgorithmDataFacade<engine::datafacade::CoreCH>
|
|
||||||
{
|
|
||||||
};
|
|
||||||
|
|
||||||
} // ns test
|
} // ns test
|
||||||
} // ns osrm
|
} // ns osrm
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user