Implement CoreCH algorithm

This commit is contained in:
Patrick Niklaus
2017-02-25 05:13:38 +00:00
committed by Patrick Niklaus
parent 922e155763
commit 7da86b5984
19 changed files with 562 additions and 300 deletions
+61 -15
View File
@@ -11,29 +11,75 @@ namespace algorithm
{
// Contraction Hiearchy
struct CH final {};
struct CH final
{
};
// Contraction Hiearchy with core
struct CoreCH final {};
struct CoreCH final
{
};
}
namespace algorithm_trais
{
template <typename AlgorithmT> struct HasAlternativePathSearch final : std::false_type {};
template <typename AlgorithmT> struct HasShortestPathSearch final : std::false_type {};
template <typename AlgorithmT> struct HasDirectShortestPathSearch final : std::false_type {};
template <typename AlgorithmT> struct HasMapMatching final : std::false_type {};
template <typename AlgorithmT> struct HasManyToManySearch final : std::false_type {};
template <typename AlgorithmT> struct HasGetTileTurns final : std::false_type {};
template <typename AlgorithmT> struct HasAlternativePathSearch final : std::false_type
{
};
template <typename AlgorithmT> struct HasShortestPathSearch final : std::false_type
{
};
template <typename AlgorithmT> struct HasDirectShortestPathSearch final : std::false_type
{
};
template <typename AlgorithmT> struct HasMapMatching final : std::false_type
{
};
template <typename AlgorithmT> struct HasManyToManySearch final : std::false_type
{
};
template <typename AlgorithmT> struct HasGetTileTurns final : std::false_type
{
};
template <> struct HasAlternativePathSearch<algorithm::CH> final : std::true_type {};
template <> struct HasShortestPathSearch<algorithm::CH> final : std::true_type {};
template <> struct HasDirectShortestPathSearch<algorithm::CH> final : std::true_type {};
template <> struct HasMapMatching<algorithm::CH> final : std::true_type {};
template <> struct HasManyToManySearch<algorithm::CH> final : std::true_type {};
template <> struct HasGetTileTurns<algorithm::CH> final : std::true_type {};
template <> struct HasAlternativePathSearch<algorithm::CH> final : std::true_type
{
};
template <> struct HasShortestPathSearch<algorithm::CH> final : std::true_type
{
};
template <> struct HasDirectShortestPathSearch<algorithm::CH> final : std::true_type
{
};
template <> struct HasMapMatching<algorithm::CH> final : std::true_type
{
};
template <> struct HasManyToManySearch<algorithm::CH> final : std::true_type
{
};
template <> struct HasGetTileTurns<algorithm::CH> final : std::true_type
{
};
// disbaled because of perfomance reasons
template <> struct HasAlternativePathSearch<algorithm::CoreCH> final : std::false_type
{
};
template <> struct HasManyToManySearch<algorithm::CoreCH> final : std::false_type
{
};
template <> struct HasShortestPathSearch<algorithm::CoreCH> final : std::true_type
{
};
template <> struct HasDirectShortestPathSearch<algorithm::CoreCH> final : std::true_type
{
};
template <> struct HasMapMatching<algorithm::CoreCH> final : std::true_type
{
};
template <> struct HasGetTileTurns<algorithm::CoreCH> final : std::true_type
{
};
}
}
}
@@ -49,6 +49,12 @@ template <> class AlgorithmDataFacade<algorithm::CH>
virtual EdgeID FindSmallestEdge(const NodeID from,
const NodeID to,
const std::function<bool(EdgeData)> filter) const = 0;
};
template <> class AlgorithmDataFacade<algorithm::CoreCH>
{
public:
using EdgeData = contractor::QueryEdge::EdgeData;
virtual bool IsCoreNode(const NodeID id) const = 0;
@@ -58,7 +58,6 @@ class ContiguousInternalMemoryAlgorithmDataFacade<algorithm::CH>
using GraphEdge = QueryGraph::EdgeArrayEntry;
std::unique_ptr<QueryGraph> m_query_graph;
util::ShM<bool, true>::vector m_is_core_node;
// allocator that keeps the allocation data
std::shared_ptr<ContiguousBlockAllocator> allocator;
@@ -78,15 +77,6 @@ class ContiguousInternalMemoryAlgorithmDataFacade<algorithm::CH>
m_query_graph.reset(new QueryGraph(node_list, edge_list));
}
void InitializeCoreInformationPointer(storage::DataLayout &data_layout, char *memory_block)
{
auto core_marker_ptr =
data_layout.GetBlockPtr<unsigned>(memory_block, storage::DataLayout::CH_CORE_MARKER);
util::ShM<bool, true>::vector is_core_node(
core_marker_ptr, data_layout.num_entries[storage::DataLayout::CH_CORE_MARKER]);
m_is_core_node = std::move(is_core_node);
}
public:
ContiguousInternalMemoryAlgorithmDataFacade(
std::shared_ptr<ContiguousBlockAllocator> allocator_)
@@ -98,21 +88,8 @@ class ContiguousInternalMemoryAlgorithmDataFacade<algorithm::CH>
void InitializeInternalPointers(storage::DataLayout &data_layout, char *memory_block)
{
InitializeGraphPointer(data_layout, memory_block);
InitializeCoreInformationPointer(data_layout, memory_block);
}
bool IsCoreNode(const NodeID id) const override final
{
if (m_is_core_node.size() > 0)
{
return m_is_core_node.at(id);
}
return false;
}
std::size_t GetCoreSize() const override final { return m_is_core_node.size(); }
// search graph access
unsigned GetNumberOfNodes() const override final { return m_query_graph->GetNumberOfNodes(); }
@@ -164,6 +141,51 @@ class ContiguousInternalMemoryAlgorithmDataFacade<algorithm::CH>
}
};
template <>
class ContiguousInternalMemoryAlgorithmDataFacade<algorithm::CoreCH>
: public datafacade::AlgorithmDataFacade<algorithm::CoreCH>
{
private:
util::ShM<bool, true>::vector m_is_core_node;
// allocator that keeps the allocation data
std::shared_ptr<ContiguousBlockAllocator> allocator;
void InitializeCoreInformationPointer(storage::DataLayout &data_layout, char *memory_block)
{
auto core_marker_ptr =
data_layout.GetBlockPtr<unsigned>(memory_block, storage::DataLayout::CH_CORE_MARKER);
util::ShM<bool, true>::vector is_core_node(
core_marker_ptr, data_layout.num_entries[storage::DataLayout::CH_CORE_MARKER]);
m_is_core_node = std::move(is_core_node);
}
public:
ContiguousInternalMemoryAlgorithmDataFacade(
std::shared_ptr<ContiguousBlockAllocator> allocator_)
: allocator(std::move(allocator_))
{
InitializeInternalPointers(allocator->GetLayout(), allocator->GetMemory());
}
void InitializeInternalPointers(storage::DataLayout &data_layout, char *memory_block)
{
InitializeCoreInformationPointer(data_layout, memory_block);
}
bool IsCoreNode(const NodeID id) const override final
{
if (m_is_core_node.size() > 0)
{
return m_is_core_node.at(id);
}
return false;
}
std::size_t GetCoreSize() const override final { return m_is_core_node.size(); }
};
/**
* This base class implements the Datafacade interface for accessing
* data that's stored in a single large block of memory (RAM).
@@ -1050,6 +1072,20 @@ class ContiguousInternalMemoryDataFacade<algorithm::CH>
{
}
};
template <>
class ContiguousInternalMemoryDataFacade<algorithm::CoreCH> final
: public ContiguousInternalMemoryDataFacade<algorithm::CH>,
public ContiguousInternalMemoryAlgorithmDataFacade<algorithm::CoreCH>
{
public:
ContiguousInternalMemoryDataFacade(std::shared_ptr<ContiguousBlockAllocator> allocator)
: ContiguousInternalMemoryDataFacade<algorithm::CH>(allocator),
ContiguousInternalMemoryAlgorithmDataFacade<algorithm::CoreCH>(allocator)
{
}
};
}
}
}
+50
View File
@@ -125,6 +125,8 @@ template <typename AlgorithmT> class Engine final : public EngineInterface
return tile_plugin.HandleRequest(*facade, algorithms, params, result);
}
static bool CheckCompability(const EngineConfig &config);
private:
std::unique_ptr<DataFacadeProvider<AlgorithmT>> facade_provider;
mutable SearchEngineData heaps;
@@ -136,6 +138,54 @@ template <typename AlgorithmT> class Engine final : public EngineInterface
const plugins::MatchPlugin match_plugin;
const plugins::TilePlugin tile_plugin;
};
template <> bool Engine<algorithm::CH>::CheckCompability(const EngineConfig &config)
{
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_GRAPH_NODE_LIST) > 0 &&
layout->GetBlockSize(storage::DataLayout::CH_GRAPH_EDGE_LIST) > 0;
}
else
{
std::ifstream in(config.storage_config.hsgr_data_path.string().c_str());
in.seekg(std::ios::end);
auto size = in.tellg();
return size > 0;
}
}
template <> bool Engine<algorithm::CoreCH>::CheckCompability(const EngineConfig &config)
{
if (!Engine<algorithm::CH>::CheckCompability(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;
}
else
{
std::ifstream in(config.storage_config.core_data_path.string().c_str());
in.seekg(std::ios::end);
auto size = in.tellg();
return size > 0;
}
}
}
}
+19 -17
View File
@@ -19,19 +19,20 @@ namespace engine
class RoutingAlgorithmsInterface
{
public:
virtual InternalRouteResult AlternativePathSearch(const PhantomNodes &phantom_node_pair) const = 0;
virtual InternalRouteResult
AlternativePathSearch(const PhantomNodes &phantom_node_pair) const = 0;
virtual InternalRouteResult
ShortestPathSearch(const std::vector<PhantomNodes> &phantom_node_pair,
const boost::optional<bool> continue_straight_at_waypoint) const = 0;
const boost::optional<bool> continue_straight_at_waypoint) const = 0;
virtual InternalRouteResult
DirectShortestPathSearch(const std::vector<PhantomNodes> &phantom_node_pair) const = 0;
DirectShortestPathSearch(const PhantomNodes &phantom_node_pair) const = 0;
virtual std::vector<EdgeWeight>
ManyToManySearch(const std::vector<PhantomNode> &phantom_nodes,
const std::vector<std::size_t> &source_indices,
const std::vector<std::size_t> &target_indices) const = 0;
const std::vector<std::size_t> &source_indices,
const std::vector<std::size_t> &target_indices) const = 0;
virtual routing_algorithms::SubMatchingList
MapMatching(const routing_algorithms::CandidateLists &candidates_list,
@@ -41,7 +42,7 @@ class RoutingAlgorithmsInterface
virtual std::vector<routing_algorithms::TurnData>
GetTileTurns(const std::vector<datafacade::BaseDataFacade::RTreeLeaf> &edges,
const std::vector<std::size_t> &sorted_edge_indexes) const = 0;
const std::vector<std::size_t> &sorted_edge_indexes) const = 0;
virtual bool HasAlternativePathSearch() const = 0;
virtual bool HasShortestPathSearch() const = 0;
@@ -54,8 +55,9 @@ class RoutingAlgorithmsInterface
namespace detail
{
struct NotImplementedException : public std::runtime_error {};
struct NotImplementedException : public std::runtime_error
{
};
}
// Short-lived object passed to each plugin in request to wrap routing algorithms
@@ -74,24 +76,24 @@ template <typename AlgorithmT> class RoutingAlgorithms final : public RoutingAlg
return routing_algorithms::alternativePathSearch(heaps, facade, phantom_node_pair);
}
InternalRouteResult
ShortestPathSearch(const std::vector<PhantomNodes> &phantom_node_pair,
const boost::optional<bool> continue_straight_at_waypoint) const final override
InternalRouteResult ShortestPathSearch(
const std::vector<PhantomNodes> &phantom_node_pair,
const boost::optional<bool> continue_straight_at_waypoint) const final override
{
return routing_algorithms::shortestPathSearch(
heaps, facade, phantom_node_pair, continue_straight_at_waypoint);
}
InternalRouteResult DirectShortestPathSearch(
const std::vector<PhantomNodes> &phantom_node_pair) const final override
InternalRouteResult
DirectShortestPathSearch(const PhantomNodes &phantom_nodes) const final override
{
return routing_algorithms::directShortestPathSearch(heaps, facade, phantom_node_pair);
return routing_algorithms::directShortestPathSearch(heaps, facade, phantom_nodes);
}
std::vector<EdgeWeight>
ManyToManySearch(const std::vector<PhantomNode> &phantom_nodes,
const std::vector<std::size_t> &source_indices,
const std::vector<std::size_t> &target_indices) const final override
const std::vector<std::size_t> &source_indices,
const std::vector<std::size_t> &target_indices) const final override
{
return routing_algorithms::manyToManySearch(
heaps, facade, phantom_nodes, source_indices, target_indices);
@@ -113,7 +115,7 @@ template <typename AlgorithmT> class RoutingAlgorithms final : public RoutingAlg
std::vector<routing_algorithms::TurnData>
GetTileTurns(const std::vector<datafacade::BaseDataFacade::RTreeLeaf> &edges,
const std::vector<std::size_t> &sorted_edge_indexes) const final override
const std::vector<std::size_t> &sorted_edge_indexes) const final override
{
return routing_algorithms::getTileTurns(facade, edges, sorted_edge_indexes);
}
@@ -34,7 +34,12 @@ directShortestPathSearch(SearchEngineData &,
InternalRouteResult directShortestPathSearch(
SearchEngineData &engine_working_data,
const datafacade::ContiguousInternalMemoryDataFacade<algorithm::CH> &facade,
const std::vector<PhantomNodes> &phantom_nodes_vector);
const PhantomNodes &phantom_nodes);
InternalRouteResult directShortestPathSearch(
SearchEngineData &engine_working_data,
const datafacade::ContiguousInternalMemoryDataFacade<algorithm::CoreCH> &facade,
const PhantomNodes &phantom_nodes);
} // namespace routing_algorithms
} // namespace engine
@@ -39,6 +39,14 @@ mapMatching(SearchEngineData &engine_working_data,
const std::vector<util::Coordinate> &trace_coordinates,
const std::vector<unsigned> &trace_timestamps,
const std::vector<boost::optional<double>> &trace_gps_precision);
SubMatchingList
mapMatching(SearchEngineData &engine_working_data,
const datafacade::ContiguousInternalMemoryDataFacade<algorithm::CoreCH> &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);
}
}
}
@@ -452,6 +452,28 @@ void search(const datafacade::ContiguousInternalMemoryDataFacade<algorithm::CH>
const bool force_loop_reverse,
const int duration_upper_bound = INVALID_EDGE_WEIGHT);
// Alias to be compatible with the overload for CoreCH that needs 4 heaps
inline void search(const datafacade::ContiguousInternalMemoryDataFacade<algorithm::CH> &facade,
SearchEngineData::QueryHeap &forward_heap,
SearchEngineData::QueryHeap &reverse_heap,
SearchEngineData::QueryHeap &,
SearchEngineData::QueryHeap &,
std::int32_t &weight,
std::vector<NodeID> &packed_leg,
const bool force_loop_forward,
const bool force_loop_reverse,
const int duration_upper_bound = INVALID_EDGE_WEIGHT)
{
search(facade,
forward_heap,
reverse_heap,
weight,
packed_leg,
force_loop_forward,
force_loop_reverse,
duration_upper_bound);
}
// 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
@@ -461,16 +483,16 @@ void search(const datafacade::ContiguousInternalMemoryDataFacade<algorithm::CH>
// && source_phantom.GetForwardWeightPlusOffset() > target_phantom.GetForwardWeightPlusOffset())
// requires
// a force loop, if the heaps have been initialized with positive offsets.
void searchWithCore(const datafacade::ContiguousInternalMemoryDataFacade<algorithm::CH> &facade,
SearchEngineData::QueryHeap &forward_heap,
SearchEngineData::QueryHeap &reverse_heap,
SearchEngineData::QueryHeap &forward_core_heap,
SearchEngineData::QueryHeap &reverse_core_heap,
int &weight,
std::vector<NodeID> &packed_leg,
const bool force_loop_forward,
const bool force_loop_reverse,
int duration_upper_bound = INVALID_EDGE_WEIGHT);
void search(const datafacade::ContiguousInternalMemoryDataFacade<algorithm::CoreCH> &facade,
SearchEngineData::QueryHeap &forward_heap,
SearchEngineData::QueryHeap &reverse_heap,
SearchEngineData::QueryHeap &forward_core_heap,
SearchEngineData::QueryHeap &reverse_core_heap,
int &weight,
std::vector<NodeID> &packed_leg,
const bool force_loop_forward,
const bool force_loop_reverse,
int duration_upper_bound = INVALID_EDGE_WEIGHT);
bool needsLoopForward(const PhantomNode &source_phantom, const PhantomNode &target_phantom);
@@ -484,15 +506,15 @@ double getPathDistance(const datafacade::ContiguousInternalMemoryDataFacade<algo
// 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 getNetworkDistanceWithCore(
const datafacade::ContiguousInternalMemoryDataFacade<algorithm::CH> &facade,
SearchEngineData::QueryHeap &forward_heap,
SearchEngineData::QueryHeap &reverse_heap,
SearchEngineData::QueryHeap &forward_core_heap,
SearchEngineData::QueryHeap &reverse_core_heap,
const PhantomNode &source_phantom,
const PhantomNode &target_phantom,
int duration_upper_bound = INVALID_EDGE_WEIGHT);
double
getNetworkDistance(const datafacade::ContiguousInternalMemoryDataFacade<algorithm::CoreCH> &facade,
SearchEngineData::QueryHeap &forward_heap,
SearchEngineData::QueryHeap &reverse_heap,
SearchEngineData::QueryHeap &forward_core_heap,
SearchEngineData::QueryHeap &reverse_core_heap,
const PhantomNode &source_phantom,
const PhantomNode &target_phantom,
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,
@@ -505,6 +527,21 @@ getNetworkDistance(const datafacade::ContiguousInternalMemoryDataFacade<algorith
const PhantomNode &target_phantom,
int duration_upper_bound = INVALID_EDGE_WEIGHT);
// Alias to be compatible with the overload for CoreCH that needs 4 heaps
inline double
getNetworkDistance(const datafacade::ContiguousInternalMemoryDataFacade<algorithm::CH> &facade,
SearchEngineData::QueryHeap &forward_heap,
SearchEngineData::QueryHeap &reverse_heap,
SearchEngineData::QueryHeap &,
SearchEngineData::QueryHeap &,
const PhantomNode &source_phantom,
const PhantomNode &target_phantom,
int duration_upper_bound = INVALID_EDGE_WEIGHT)
{
return getNetworkDistance(
facade, forward_heap, reverse_heap, source_phantom, target_phantom, duration_upper_bound);
}
} // namespace routing_algorithms
} // namespace engine
} // namespace osrm
@@ -30,6 +30,12 @@ shortestPathSearch(SearchEngineData &engine_working_data,
const std::vector<PhantomNodes> &phantom_nodes_vector,
const boost::optional<bool> continue_straight_at_waypoint);
InternalRouteResult
shortestPathSearch(SearchEngineData &engine_working_data,
const datafacade::ContiguousInternalMemoryDataFacade<algorithm::CoreCH> &facade,
const std::vector<PhantomNodes> &phantom_nodes_vector,
const boost::optional<bool> continue_straight_at_waypoint);
} // namespace routing_algorithms
} // namespace engine
} // namespace osrm