implement MLD shortest path plugin
This commit is contained in:
parent
a1fa1c610c
commit
48a098a9c7
@ -96,6 +96,9 @@ template <> struct HasGetTileTurns<corech::Algorithm> final : std::true_type
|
|||||||
template <> struct HasDirectShortestPathSearch<mld::Algorithm> final : std::true_type
|
template <> struct HasDirectShortestPathSearch<mld::Algorithm> final : std::true_type
|
||||||
{
|
{
|
||||||
};
|
};
|
||||||
|
template <> struct HasShortestPathSearch<mld::Algorithm> final : std::true_type
|
||||||
|
{
|
||||||
|
};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -187,7 +187,8 @@ inline std::vector<routing_algorithms::TurnData> RoutingAlgorithms<Algorithm>::G
|
|||||||
|
|
||||||
// CoreCH overrides
|
// CoreCH overrides
|
||||||
template <>
|
template <>
|
||||||
InternalRouteResult inline RoutingAlgorithms<routing_algorithms::corech::Algorithm>::AlternativePathSearch(const PhantomNodes &) const
|
InternalRouteResult inline RoutingAlgorithms<
|
||||||
|
routing_algorithms::corech::Algorithm>::AlternativePathSearch(const PhantomNodes &) const
|
||||||
{
|
{
|
||||||
throw util::exception("AlternativePathSearch is disabled due to performance reasons");
|
throw util::exception("AlternativePathSearch is disabled due to performance reasons");
|
||||||
}
|
}
|
||||||
@ -210,14 +211,6 @@ InternalRouteResult inline RoutingAlgorithms<
|
|||||||
throw util::exception("AlternativePathSearch is not implemented");
|
throw util::exception("AlternativePathSearch is not implemented");
|
||||||
}
|
}
|
||||||
|
|
||||||
template <>
|
|
||||||
inline InternalRouteResult
|
|
||||||
RoutingAlgorithms<routing_algorithms::mld::Algorithm>::ShortestPathSearch(
|
|
||||||
const std::vector<PhantomNodes> &, const boost::optional<bool>) const
|
|
||||||
{
|
|
||||||
throw util::exception("ShortestPathSearch is not implemented");
|
|
||||||
}
|
|
||||||
|
|
||||||
template <>
|
template <>
|
||||||
inline std::vector<EdgeWeight>
|
inline std::vector<EdgeWeight>
|
||||||
RoutingAlgorithms<routing_algorithms::mld::Algorithm>::ManyToManySearch(
|
RoutingAlgorithms<routing_algorithms::mld::Algorithm>::ManyToManySearch(
|
||||||
|
@ -22,7 +22,7 @@ static const constexpr double DEFAULT_GPS_PRECISION = 5;
|
|||||||
|
|
||||||
//[1] "Hidden Markov Map Matching Through Noise and Sparseness";
|
//[1] "Hidden Markov Map Matching Through Noise and Sparseness";
|
||||||
// P. Newson and J. Krumm; 2009; ACM GIS
|
// P. Newson and J. Krumm; 2009; ACM GIS
|
||||||
template<typename Algorithm>
|
template <typename Algorithm>
|
||||||
SubMatchingList mapMatching(SearchEngineData<Algorithm> &engine_working_data,
|
SubMatchingList mapMatching(SearchEngineData<Algorithm> &engine_working_data,
|
||||||
const datafacade::ContiguousInternalMemoryDataFacade<Algorithm> &facade,
|
const datafacade::ContiguousInternalMemoryDataFacade<Algorithm> &facade,
|
||||||
const CandidateLists &candidates_list,
|
const CandidateLists &candidates_list,
|
||||||
@ -30,7 +30,6 @@ SubMatchingList mapMatching(SearchEngineData<Algorithm> &engine_working_data,
|
|||||||
const std::vector<unsigned> &trace_timestamps,
|
const std::vector<unsigned> &trace_timestamps,
|
||||||
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);
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -37,6 +37,10 @@ static constexpr bool FORWARD_DIRECTION = true;
|
|||||||
static constexpr bool REVERSE_DIRECTION = false;
|
static constexpr bool REVERSE_DIRECTION = false;
|
||||||
static constexpr bool DO_NOT_FORCE_LOOPS = false;
|
static constexpr bool DO_NOT_FORCE_LOOPS = false;
|
||||||
|
|
||||||
|
bool needsLoopForward(const PhantomNode &source_phantom, const PhantomNode &target_phantom);
|
||||||
|
|
||||||
|
bool needsLoopBackwards(const PhantomNode &source_phantom, const PhantomNode &target_phantom);
|
||||||
|
|
||||||
template <bool DIRECTION, typename Heap>
|
template <bool DIRECTION, typename Heap>
|
||||||
void insertNodesInHeap(Heap &heap, const PhantomNode &phantom_node)
|
void insertNodesInHeap(Heap &heap, const PhantomNode &phantom_node)
|
||||||
{
|
{
|
||||||
|
@ -365,10 +365,11 @@ inline void search(const datafacade::ContiguousInternalMemoryDataFacade<Algorith
|
|||||||
SearchEngineData<Algorithm>::QueryHeap &reverse_heap,
|
SearchEngineData<Algorithm>::QueryHeap &reverse_heap,
|
||||||
SearchEngineData<Algorithm>::QueryHeap &,
|
SearchEngineData<Algorithm>::QueryHeap &,
|
||||||
SearchEngineData<Algorithm>::QueryHeap &,
|
SearchEngineData<Algorithm>::QueryHeap &,
|
||||||
std::int32_t &weight,
|
EdgeWeight &weight,
|
||||||
std::vector<NodeID> &packed_leg,
|
std::vector<NodeID> &packed_leg,
|
||||||
const bool force_loop_forward,
|
const bool force_loop_forward,
|
||||||
const bool force_loop_reverse,
|
const bool force_loop_reverse,
|
||||||
|
const PhantomNodes & /*phantom_nodes*/,
|
||||||
const int duration_upper_bound = INVALID_EDGE_WEIGHT)
|
const int duration_upper_bound = INVALID_EDGE_WEIGHT)
|
||||||
{
|
{
|
||||||
search(facade,
|
search(facade,
|
||||||
@ -381,10 +382,6 @@ inline void search(const datafacade::ContiguousInternalMemoryDataFacade<Algorith
|
|||||||
duration_upper_bound);
|
duration_upper_bound);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool needsLoopForward(const PhantomNode &source_phantom, const PhantomNode &target_phantom);
|
|
||||||
|
|
||||||
bool needsLoopBackwards(const PhantomNode &source_phantom, const PhantomNode &target_phantom);
|
|
||||||
|
|
||||||
double getPathDistance(const datafacade::ContiguousInternalMemoryDataFacade<ch::Algorithm> &facade,
|
double getPathDistance(const datafacade::ContiguousInternalMemoryDataFacade<ch::Algorithm> &facade,
|
||||||
const std::vector<NodeID> &packed_path,
|
const std::vector<NodeID> &packed_path,
|
||||||
const PhantomNode &source_phantom,
|
const PhantomNode &source_phantom,
|
||||||
@ -437,6 +434,7 @@ void search(const datafacade::ContiguousInternalMemoryDataFacade<corech::Algorit
|
|||||||
std::vector<NodeID> &packed_leg,
|
std::vector<NodeID> &packed_leg,
|
||||||
const bool force_loop_forward,
|
const bool force_loop_forward,
|
||||||
const bool force_loop_reverse,
|
const bool force_loop_reverse,
|
||||||
|
const PhantomNodes &phantom_nodes,
|
||||||
int duration_upper_bound = INVALID_EDGE_WEIGHT);
|
int duration_upper_bound = INVALID_EDGE_WEIGHT);
|
||||||
|
|
||||||
// Requires the heaps for be empty
|
// Requires the heaps for be empty
|
||||||
@ -451,6 +449,17 @@ getNetworkDistance(const datafacade::ContiguousInternalMemoryDataFacade<corech::
|
|||||||
const PhantomNode &source_phantom,
|
const PhantomNode &source_phantom,
|
||||||
const PhantomNode &target_phantom,
|
const PhantomNode &target_phantom,
|
||||||
int duration_upper_bound = INVALID_EDGE_WEIGHT);
|
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 corech
|
||||||
|
|
||||||
} // namespace routing_algorithms
|
} // namespace routing_algorithms
|
||||||
|
@ -174,6 +174,8 @@ std::tuple<EdgeWeight, NodeID, NodeID, std::vector<EdgeID>>
|
|||||||
search(const datafacade::ContiguousInternalMemoryDataFacade<Algorithm> &facade,
|
search(const datafacade::ContiguousInternalMemoryDataFacade<Algorithm> &facade,
|
||||||
SearchEngineData<Algorithm>::QueryHeap &forward_heap,
|
SearchEngineData<Algorithm>::QueryHeap &forward_heap,
|
||||||
SearchEngineData<Algorithm>::QueryHeap &reverse_heap,
|
SearchEngineData<Algorithm>::QueryHeap &reverse_heap,
|
||||||
|
const bool force_loop_forward,
|
||||||
|
const bool force_loop_reverse,
|
||||||
Args... args)
|
Args... args)
|
||||||
{
|
{
|
||||||
|
|
||||||
@ -268,7 +270,7 @@ search(const datafacade::ContiguousInternalMemoryDataFacade<Algorithm> &facade,
|
|||||||
NodeID subpath_source, subpath_target;
|
NodeID subpath_source, subpath_target;
|
||||||
std::vector<EdgeID> subpath;
|
std::vector<EdgeID> subpath;
|
||||||
std::tie(subpath_weight, subpath_source, subpath_target, subpath) =
|
std::tie(subpath_weight, subpath_source, subpath_target, subpath) =
|
||||||
search(facade, forward_heap, reverse_heap, sublevel, parent_cell_id);
|
search(facade, forward_heap, reverse_heap, force_loop_forward, force_loop_reverse, sublevel, parent_cell_id);
|
||||||
BOOST_ASSERT(!subpath.empty());
|
BOOST_ASSERT(!subpath.empty());
|
||||||
BOOST_ASSERT(subpath_source == source);
|
BOOST_ASSERT(subpath_source == source);
|
||||||
BOOST_ASSERT(subpath_target == target);
|
BOOST_ASSERT(subpath_target == target);
|
||||||
@ -279,6 +281,63 @@ search(const datafacade::ContiguousInternalMemoryDataFacade<Algorithm> &facade,
|
|||||||
return std::make_tuple(weight, source_node, target_node, std::move(unpacked_path));
|
return std::make_tuple(weight, source_node, target_node, std::move(unpacked_path));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Alias to be compatible with the overload for CoreCH that needs 4 heaps
|
||||||
|
inline void search(const datafacade::ContiguousInternalMemoryDataFacade<Algorithm> &facade,
|
||||||
|
SearchEngineData<Algorithm>::QueryHeap &forward_heap,
|
||||||
|
SearchEngineData<Algorithm>::QueryHeap &reverse_heap,
|
||||||
|
SearchEngineData<Algorithm>::QueryHeap &,
|
||||||
|
SearchEngineData<Algorithm>::QueryHeap &,
|
||||||
|
EdgeWeight &weight,
|
||||||
|
std::vector<NodeID> &packed_leg,
|
||||||
|
const bool force_loop_forward,
|
||||||
|
const bool force_loop_reverse,
|
||||||
|
const PhantomNodes &phantom_nodes,
|
||||||
|
const int duration_upper_bound = INVALID_EDGE_WEIGHT)
|
||||||
|
{
|
||||||
|
(void)duration_upper_bound;
|
||||||
|
|
||||||
|
NodeID source_node, target_node;
|
||||||
|
std::vector<EdgeID> unpacked_edges;
|
||||||
|
std::tie(weight, source_node, target_node, unpacked_edges) =
|
||||||
|
mld::search(facade, forward_heap, reverse_heap, force_loop_forward, force_loop_reverse, phantom_nodes);
|
||||||
|
|
||||||
|
if (weight != INVALID_EDGE_WEIGHT)
|
||||||
|
{
|
||||||
|
packed_leg.push_back(source_node);
|
||||||
|
std::transform(unpacked_edges.begin(),
|
||||||
|
unpacked_edges.end(),
|
||||||
|
std::back_inserter(packed_leg),
|
||||||
|
[&facade](const auto edge) { return facade.GetTarget(edge); });
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
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)
|
||||||
|
{
|
||||||
|
const auto nodes_number = std::distance(packed_path_begin, packed_path_end);
|
||||||
|
BOOST_ASSERT(nodes_number > 0);
|
||||||
|
|
||||||
|
std::vector<EdgeID> unpacked_edges;
|
||||||
|
|
||||||
|
auto source_node = *packed_path_begin, target_node = *packed_path_begin;
|
||||||
|
|
||||||
|
if (nodes_number > 1)
|
||||||
|
{
|
||||||
|
target_node = *std::prev(packed_path_end);
|
||||||
|
util::for_each_pair(packed_path_begin,
|
||||||
|
packed_path_end,
|
||||||
|
[&facade, &unpacked_edges](const auto from, const auto to) {
|
||||||
|
unpacked_edges.push_back(facade.FindEdge(from, to));
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
annotatePath(facade, source_node, target_node, unpacked_edges, phantom_nodes, unpacked_path);
|
||||||
|
}
|
||||||
|
|
||||||
} // namespace mld
|
} // namespace mld
|
||||||
} // namespace routing_algorithms
|
} // namespace routing_algorithms
|
||||||
} // namespace engine
|
} // namespace engine
|
||||||
|
@ -13,7 +13,7 @@ namespace engine
|
|||||||
namespace routing_algorithms
|
namespace routing_algorithms
|
||||||
{
|
{
|
||||||
|
|
||||||
template<typename Algorithm>
|
template <typename Algorithm>
|
||||||
InternalRouteResult
|
InternalRouteResult
|
||||||
shortestPathSearch(SearchEngineData<Algorithm> &engine_working_data,
|
shortestPathSearch(SearchEngineData<Algorithm> &engine_working_data,
|
||||||
const datafacade::ContiguousInternalMemoryDataFacade<Algorithm> &facade,
|
const datafacade::ContiguousInternalMemoryDataFacade<Algorithm> &facade,
|
||||||
|
@ -75,8 +75,12 @@ template <> struct SearchEngineData<routing_algorithms::mld::Algorithm>
|
|||||||
|
|
||||||
static SearchEngineHeapPtr forward_heap_1;
|
static SearchEngineHeapPtr forward_heap_1;
|
||||||
static SearchEngineHeapPtr reverse_heap_1;
|
static SearchEngineHeapPtr reverse_heap_1;
|
||||||
|
static SearchEngineHeapPtr forward_heap_2;
|
||||||
|
static SearchEngineHeapPtr reverse_heap_2;
|
||||||
|
|
||||||
void InitializeOrClearFirstThreadLocalStorage(unsigned number_of_nodes);
|
void InitializeOrClearFirstThreadLocalStorage(unsigned number_of_nodes);
|
||||||
|
|
||||||
|
void InitializeOrClearSecondThreadLocalStorage(unsigned number_of_nodes);
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -84,7 +84,8 @@ InternalRouteResult directShortestPathSearchImpl(
|
|||||||
weight,
|
weight,
|
||||||
packed_leg,
|
packed_leg,
|
||||||
DO_NOT_FORCE_LOOPS,
|
DO_NOT_FORCE_LOOPS,
|
||||||
DO_NOT_FORCE_LOOPS);
|
DO_NOT_FORCE_LOOPS,
|
||||||
|
phantom_nodes);
|
||||||
|
|
||||||
std::vector<EdgeID> unpacked_edges;
|
std::vector<EdgeID> unpacked_edges;
|
||||||
auto source_node = SPECIAL_NODEID, target_node = SPECIAL_NODEID;
|
auto source_node = SPECIAL_NODEID, target_node = SPECIAL_NODEID;
|
||||||
@ -139,8 +140,8 @@ InternalRouteResult directShortestPathSearch(
|
|||||||
EdgeWeight weight;
|
EdgeWeight weight;
|
||||||
NodeID source_node, target_node;
|
NodeID source_node, target_node;
|
||||||
std::vector<EdgeID> unpacked_edges;
|
std::vector<EdgeID> unpacked_edges;
|
||||||
std::tie(weight, source_node, target_node, unpacked_edges) =
|
std::tie(weight, source_node, target_node, unpacked_edges) = mld::search(
|
||||||
mld::search(facade, forward_heap, reverse_heap, phantom_nodes);
|
facade, forward_heap, reverse_heap, DO_NOT_FORCE_LOOPS, DO_NOT_FORCE_LOOPS, phantom_nodes);
|
||||||
|
|
||||||
return extractRoute(facade, weight, source_node, target_node, unpacked_edges, phantom_nodes);
|
return extractRoute(facade, weight, source_node, target_node, unpacked_edges, phantom_nodes);
|
||||||
}
|
}
|
||||||
|
@ -420,14 +420,15 @@ mapMatchingImpl(SearchEngineData<Algorithm> &engine_working_data,
|
|||||||
return sub_matchings;
|
return sub_matchings;
|
||||||
}
|
}
|
||||||
|
|
||||||
template<>
|
template <>
|
||||||
SubMatchingList mapMatching(SearchEngineData<ch::Algorithm> &engine_working_data,
|
SubMatchingList
|
||||||
const datafacade::ContiguousInternalMemoryDataFacade<ch::Algorithm> &facade,
|
mapMatching(SearchEngineData<ch::Algorithm> &engine_working_data,
|
||||||
const CandidateLists &candidates_list,
|
const datafacade::ContiguousInternalMemoryDataFacade<ch::Algorithm> &facade,
|
||||||
const std::vector<util::Coordinate> &trace_coordinates,
|
const CandidateLists &candidates_list,
|
||||||
const std::vector<unsigned> &trace_timestamps,
|
const std::vector<util::Coordinate> &trace_coordinates,
|
||||||
const std::vector<boost::optional<double>> &trace_gps_precision,
|
const std::vector<unsigned> &trace_timestamps,
|
||||||
const bool use_tidying)
|
const std::vector<boost::optional<double>> &trace_gps_precision,
|
||||||
|
const bool use_tidying)
|
||||||
{
|
{
|
||||||
return mapMatchingImpl(engine_working_data,
|
return mapMatchingImpl(engine_working_data,
|
||||||
facade,
|
facade,
|
||||||
@ -438,14 +439,15 @@ SubMatchingList mapMatching(SearchEngineData<ch::Algorithm> &engine_working_data
|
|||||||
use_tidying);
|
use_tidying);
|
||||||
}
|
}
|
||||||
|
|
||||||
template<>
|
template <>
|
||||||
SubMatchingList mapMatching(SearchEngineData<corech::Algorithm> &engine_working_data,
|
SubMatchingList
|
||||||
const datafacade::ContiguousInternalMemoryDataFacade<corech::Algorithm> &facade,
|
mapMatching(SearchEngineData<corech::Algorithm> &engine_working_data,
|
||||||
const CandidateLists &candidates_list,
|
const datafacade::ContiguousInternalMemoryDataFacade<corech::Algorithm> &facade,
|
||||||
const std::vector<util::Coordinate> &trace_coordinates,
|
const CandidateLists &candidates_list,
|
||||||
const std::vector<unsigned> &trace_timestamps,
|
const std::vector<util::Coordinate> &trace_coordinates,
|
||||||
const std::vector<boost::optional<double>> &trace_gps_precision,
|
const std::vector<unsigned> &trace_timestamps,
|
||||||
const bool use_tidying)
|
const std::vector<boost::optional<double>> &trace_gps_precision,
|
||||||
|
const bool use_tidying)
|
||||||
{
|
{
|
||||||
|
|
||||||
return mapMatchingImpl(engine_working_data,
|
return mapMatchingImpl(engine_working_data,
|
||||||
|
28
src/engine/routing_algorithms/routing_base.cpp
Normal file
28
src/engine/routing_algorithms/routing_base.cpp
Normal file
@ -0,0 +1,28 @@
|
|||||||
|
#include "engine/routing_algorithms/routing_base.hpp"
|
||||||
|
|
||||||
|
namespace osrm
|
||||||
|
{
|
||||||
|
namespace engine
|
||||||
|
{
|
||||||
|
namespace routing_algorithms
|
||||||
|
{
|
||||||
|
|
||||||
|
bool needsLoopForward(const PhantomNode &source_phantom, const PhantomNode &target_phantom)
|
||||||
|
{
|
||||||
|
return source_phantom.forward_segment_id.enabled && target_phantom.forward_segment_id.enabled &&
|
||||||
|
source_phantom.forward_segment_id.id == target_phantom.forward_segment_id.id &&
|
||||||
|
source_phantom.GetForwardWeightPlusOffset() >
|
||||||
|
target_phantom.GetForwardWeightPlusOffset();
|
||||||
|
}
|
||||||
|
|
||||||
|
bool needsLoopBackwards(const PhantomNode &source_phantom, const PhantomNode &target_phantom)
|
||||||
|
{
|
||||||
|
return source_phantom.reverse_segment_id.enabled && target_phantom.reverse_segment_id.enabled &&
|
||||||
|
source_phantom.reverse_segment_id.id == target_phantom.reverse_segment_id.id &&
|
||||||
|
source_phantom.GetReverseWeightPlusOffset() >
|
||||||
|
target_phantom.GetReverseWeightPlusOffset();
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace routing_algorithms
|
||||||
|
} // namespace engine
|
||||||
|
} // namespace osrm
|
@ -139,22 +139,6 @@ void search(const datafacade::ContiguousInternalMemoryDataFacade<Algorithm> &fac
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
bool needsLoopForward(const PhantomNode &source_phantom, const PhantomNode &target_phantom)
|
|
||||||
{
|
|
||||||
return source_phantom.forward_segment_id.enabled && target_phantom.forward_segment_id.enabled &&
|
|
||||||
source_phantom.forward_segment_id.id == target_phantom.forward_segment_id.id &&
|
|
||||||
source_phantom.GetForwardWeightPlusOffset() >
|
|
||||||
target_phantom.GetForwardWeightPlusOffset();
|
|
||||||
}
|
|
||||||
|
|
||||||
bool needsLoopBackwards(const PhantomNode &source_phantom, const PhantomNode &target_phantom)
|
|
||||||
{
|
|
||||||
return source_phantom.reverse_segment_id.enabled && target_phantom.reverse_segment_id.enabled &&
|
|
||||||
source_phantom.reverse_segment_id.id == target_phantom.reverse_segment_id.id &&
|
|
||||||
source_phantom.GetReverseWeightPlusOffset() >
|
|
||||||
target_phantom.GetReverseWeightPlusOffset();
|
|
||||||
}
|
|
||||||
|
|
||||||
double getPathDistance(const datafacade::ContiguousInternalMemoryDataFacade<Algorithm> &facade,
|
double getPathDistance(const datafacade::ContiguousInternalMemoryDataFacade<Algorithm> &facade,
|
||||||
const std::vector<NodeID> &packed_path,
|
const std::vector<NodeID> &packed_path,
|
||||||
const PhantomNode &source_phantom,
|
const PhantomNode &source_phantom,
|
||||||
@ -290,6 +274,7 @@ void search(const datafacade::ContiguousInternalMemoryDataFacade<Algorithm> &fac
|
|||||||
std::vector<NodeID> &packed_leg,
|
std::vector<NodeID> &packed_leg,
|
||||||
const bool force_loop_forward,
|
const bool force_loop_forward,
|
||||||
const bool force_loop_reverse,
|
const bool force_loop_reverse,
|
||||||
|
const PhantomNodes & /*phantom_nodes*/,
|
||||||
EdgeWeight weight_upper_bound)
|
EdgeWeight weight_upper_bound)
|
||||||
{
|
{
|
||||||
NodeID middle = SPECIAL_NODEID;
|
NodeID middle = SPECIAL_NODEID;
|
||||||
@ -486,6 +471,7 @@ double getNetworkDistance(const datafacade::ContiguousInternalMemoryDataFacade<A
|
|||||||
packed_path,
|
packed_path,
|
||||||
DO_NOT_FORCE_LOOPS,
|
DO_NOT_FORCE_LOOPS,
|
||||||
DO_NOT_FORCE_LOOPS,
|
DO_NOT_FORCE_LOOPS,
|
||||||
|
{source_phantom, target_phantom},
|
||||||
weight_upper_bound);
|
weight_upper_bound);
|
||||||
|
|
||||||
double distance = std::numeric_limits<double>::max();
|
double distance = std::numeric_limits<double>::max();
|
||||||
|
@ -1,5 +1,6 @@
|
|||||||
#include "engine/routing_algorithms/shortest_path.hpp"
|
#include "engine/routing_algorithms/shortest_path.hpp"
|
||||||
#include "engine/routing_algorithms/routing_base_ch.hpp"
|
#include "engine/routing_algorithms/routing_base_ch.hpp"
|
||||||
|
#include "engine/routing_algorithms/routing_base_mld.hpp"
|
||||||
|
|
||||||
#include <boost/assert.hpp>
|
#include <boost/assert.hpp>
|
||||||
#include <boost/optional.hpp>
|
#include <boost/optional.hpp>
|
||||||
@ -16,16 +17,15 @@ namespace
|
|||||||
{
|
{
|
||||||
|
|
||||||
const static constexpr bool DO_NOT_FORCE_LOOP = false;
|
const static constexpr bool DO_NOT_FORCE_LOOP = false;
|
||||||
using QueryHeap = SearchEngineData<ch::Algorithm>::QueryHeap;
|
|
||||||
|
|
||||||
// allows a uturn at the target_phantom
|
// allows a uturn at the target_phantom
|
||||||
// searches source forward/reverse -> target forward/reverse
|
// searches source forward/reverse -> target forward/reverse
|
||||||
template <typename AlgorithmT>
|
template <typename Algorithm>
|
||||||
void searchWithUTurn(const datafacade::ContiguousInternalMemoryDataFacade<AlgorithmT> &facade,
|
void searchWithUTurn(const datafacade::ContiguousInternalMemoryDataFacade<Algorithm> &facade,
|
||||||
QueryHeap &forward_heap,
|
typename SearchEngineData<Algorithm>::QueryHeap &forward_heap,
|
||||||
QueryHeap &reverse_heap,
|
typename SearchEngineData<Algorithm>::QueryHeap &reverse_heap,
|
||||||
QueryHeap &forward_core_heap,
|
typename SearchEngineData<Algorithm>::QueryHeap &forward_core_heap,
|
||||||
QueryHeap &reverse_core_heap,
|
typename SearchEngineData<Algorithm>::QueryHeap &reverse_core_heap,
|
||||||
const bool search_from_forward_node,
|
const bool search_from_forward_node,
|
||||||
const bool search_from_reverse_node,
|
const bool search_from_reverse_node,
|
||||||
const bool search_to_forward_node,
|
const bool search_to_forward_node,
|
||||||
@ -71,24 +71,24 @@ void searchWithUTurn(const datafacade::ContiguousInternalMemoryDataFacade<Algori
|
|||||||
auto is_oneway_source = !(search_from_forward_node && search_from_reverse_node);
|
auto is_oneway_source = !(search_from_forward_node && search_from_reverse_node);
|
||||||
auto is_oneway_target = !(search_to_forward_node && search_to_reverse_node);
|
auto is_oneway_target = !(search_to_forward_node && search_to_reverse_node);
|
||||||
// we only enable loops here if we can't search from forward to backward node
|
// we only enable loops here if we can't search from forward to backward node
|
||||||
auto needs_loop_forwad =
|
auto needs_loop_forwards = is_oneway_source && needsLoopForward(source_phantom, target_phantom);
|
||||||
is_oneway_source && ch::needsLoopForward(source_phantom, target_phantom);
|
|
||||||
auto needs_loop_backwards =
|
auto needs_loop_backwards =
|
||||||
is_oneway_target && ch::needsLoopBackwards(source_phantom, target_phantom);
|
is_oneway_target && needsLoopBackwards(source_phantom, target_phantom);
|
||||||
|
|
||||||
forward_core_heap.Clear();
|
forward_core_heap.Clear();
|
||||||
reverse_core_heap.Clear();
|
reverse_core_heap.Clear();
|
||||||
BOOST_ASSERT(forward_core_heap.Size() == 0);
|
BOOST_ASSERT(forward_core_heap.Size() == 0);
|
||||||
BOOST_ASSERT(reverse_core_heap.Size() == 0);
|
BOOST_ASSERT(reverse_core_heap.Size() == 0);
|
||||||
ch::search(facade,
|
search(facade,
|
||||||
forward_heap,
|
forward_heap,
|
||||||
reverse_heap,
|
reverse_heap,
|
||||||
forward_core_heap,
|
forward_core_heap,
|
||||||
reverse_core_heap,
|
reverse_core_heap,
|
||||||
new_total_weight,
|
new_total_weight,
|
||||||
leg_packed_path,
|
leg_packed_path,
|
||||||
needs_loop_forwad,
|
needs_loop_forwards,
|
||||||
needs_loop_backwards);
|
needs_loop_backwards,
|
||||||
|
{source_phantom, target_phantom});
|
||||||
|
|
||||||
// if no route is found between two parts of the via-route, the entire route becomes
|
// if no route is found between two parts of the via-route, the entire route becomes
|
||||||
// invalid. Adding to invalid edge weight sadly doesn't return an invalid edge weight. Here
|
// invalid. Adding to invalid edge weight sadly doesn't return an invalid edge weight. Here
|
||||||
@ -100,12 +100,12 @@ void searchWithUTurn(const datafacade::ContiguousInternalMemoryDataFacade<Algori
|
|||||||
// searches shortest path between:
|
// searches shortest path between:
|
||||||
// source forward/reverse -> target forward
|
// source forward/reverse -> target forward
|
||||||
// source forward/reverse -> target reverse
|
// source forward/reverse -> target reverse
|
||||||
template <typename AlgorithmT>
|
template <typename Algorithm>
|
||||||
void search(const datafacade::ContiguousInternalMemoryDataFacade<AlgorithmT> &facade,
|
void search(const datafacade::ContiguousInternalMemoryDataFacade<Algorithm> &facade,
|
||||||
QueryHeap &forward_heap,
|
typename SearchEngineData<Algorithm>::QueryHeap &forward_heap,
|
||||||
QueryHeap &reverse_heap,
|
typename SearchEngineData<Algorithm>::QueryHeap &reverse_heap,
|
||||||
QueryHeap &forward_core_heap,
|
typename SearchEngineData<Algorithm>::QueryHeap &forward_core_heap,
|
||||||
QueryHeap &reverse_core_heap,
|
typename SearchEngineData<Algorithm>::QueryHeap &reverse_core_heap,
|
||||||
const bool search_from_forward_node,
|
const bool search_from_forward_node,
|
||||||
const bool search_from_reverse_node,
|
const bool search_from_reverse_node,
|
||||||
const bool search_to_forward_node,
|
const bool search_to_forward_node,
|
||||||
@ -148,15 +148,16 @@ void search(const datafacade::ContiguousInternalMemoryDataFacade<AlgorithmT> &fa
|
|||||||
reverse_core_heap.Clear();
|
reverse_core_heap.Clear();
|
||||||
BOOST_ASSERT(forward_core_heap.Size() == 0);
|
BOOST_ASSERT(forward_core_heap.Size() == 0);
|
||||||
BOOST_ASSERT(reverse_core_heap.Size() == 0);
|
BOOST_ASSERT(reverse_core_heap.Size() == 0);
|
||||||
ch::search(facade,
|
search(facade,
|
||||||
forward_heap,
|
forward_heap,
|
||||||
reverse_heap,
|
reverse_heap,
|
||||||
forward_core_heap,
|
forward_core_heap,
|
||||||
reverse_core_heap,
|
reverse_core_heap,
|
||||||
new_total_weight_to_forward,
|
new_total_weight_to_forward,
|
||||||
leg_packed_path_forward,
|
leg_packed_path_forward,
|
||||||
ch::needsLoopForward(source_phantom, target_phantom),
|
needsLoopForward(source_phantom, target_phantom),
|
||||||
DO_NOT_FORCE_LOOP);
|
routing_algorithms::DO_NOT_FORCE_LOOP,
|
||||||
|
{source_phantom, target_phantom});
|
||||||
}
|
}
|
||||||
|
|
||||||
if (search_to_reverse_node)
|
if (search_to_reverse_node)
|
||||||
@ -186,19 +187,21 @@ void search(const datafacade::ContiguousInternalMemoryDataFacade<AlgorithmT> &fa
|
|||||||
reverse_core_heap.Clear();
|
reverse_core_heap.Clear();
|
||||||
BOOST_ASSERT(forward_core_heap.Size() == 0);
|
BOOST_ASSERT(forward_core_heap.Size() == 0);
|
||||||
BOOST_ASSERT(reverse_core_heap.Size() == 0);
|
BOOST_ASSERT(reverse_core_heap.Size() == 0);
|
||||||
ch::search(facade,
|
search(facade,
|
||||||
forward_heap,
|
forward_heap,
|
||||||
reverse_heap,
|
reverse_heap,
|
||||||
forward_core_heap,
|
forward_core_heap,
|
||||||
reverse_core_heap,
|
reverse_core_heap,
|
||||||
new_total_weight_to_reverse,
|
new_total_weight_to_reverse,
|
||||||
leg_packed_path_reverse,
|
leg_packed_path_reverse,
|
||||||
DO_NOT_FORCE_LOOP,
|
routing_algorithms::DO_NOT_FORCE_LOOP,
|
||||||
ch::needsLoopBackwards(source_phantom, target_phantom));
|
needsLoopBackwards(source_phantom, target_phantom),
|
||||||
|
{source_phantom, target_phantom});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void unpackLegs(const datafacade::ContiguousInternalMemoryDataFacade<ch::Algorithm> &facade,
|
template <typename Algorithm>
|
||||||
|
void unpackLegs(const datafacade::ContiguousInternalMemoryDataFacade<Algorithm> &facade,
|
||||||
const std::vector<PhantomNodes> &phantom_nodes_vector,
|
const std::vector<PhantomNodes> &phantom_nodes_vector,
|
||||||
const std::vector<NodeID> &total_packed_path,
|
const std::vector<NodeID> &total_packed_path,
|
||||||
const std::vector<std::size_t> &packed_leg_begin,
|
const std::vector<std::size_t> &packed_leg_begin,
|
||||||
@ -214,11 +217,11 @@ void unpackLegs(const datafacade::ContiguousInternalMemoryDataFacade<ch::Algorit
|
|||||||
auto leg_begin = total_packed_path.begin() + packed_leg_begin[current_leg];
|
auto leg_begin = total_packed_path.begin() + packed_leg_begin[current_leg];
|
||||||
auto leg_end = total_packed_path.begin() + packed_leg_begin[current_leg + 1];
|
auto leg_end = total_packed_path.begin() + packed_leg_begin[current_leg + 1];
|
||||||
const auto &unpack_phantom_node_pair = phantom_nodes_vector[current_leg];
|
const auto &unpack_phantom_node_pair = phantom_nodes_vector[current_leg];
|
||||||
ch::unpackPath(facade,
|
unpackPath(facade,
|
||||||
leg_begin,
|
leg_begin,
|
||||||
leg_end,
|
leg_end,
|
||||||
unpack_phantom_node_pair,
|
unpack_phantom_node_pair,
|
||||||
raw_route_data.unpacked_path_segments[current_leg]);
|
raw_route_data.unpacked_path_segments[current_leg]);
|
||||||
|
|
||||||
raw_route_data.source_traversed_in_reverse.push_back(
|
raw_route_data.source_traversed_in_reverse.push_back(
|
||||||
(*leg_begin != phantom_nodes_vector[current_leg].source_phantom.forward_segment_id.id));
|
(*leg_begin != phantom_nodes_vector[current_leg].source_phantom.forward_segment_id.id));
|
||||||
@ -484,7 +487,7 @@ shortestPathSearchImpl(SearchEngineData<Algorithm> &engine_working_data,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
template<>
|
template <>
|
||||||
InternalRouteResult
|
InternalRouteResult
|
||||||
shortestPathSearch(SearchEngineData<ch::Algorithm> &engine_working_data,
|
shortestPathSearch(SearchEngineData<ch::Algorithm> &engine_working_data,
|
||||||
const datafacade::ContiguousInternalMemoryDataFacade<ch::Algorithm> &facade,
|
const datafacade::ContiguousInternalMemoryDataFacade<ch::Algorithm> &facade,
|
||||||
@ -495,7 +498,7 @@ shortestPathSearch(SearchEngineData<ch::Algorithm> &engine_working_data,
|
|||||||
engine_working_data, facade, phantom_nodes_vector, continue_straight_at_waypoint);
|
engine_working_data, facade, phantom_nodes_vector, continue_straight_at_waypoint);
|
||||||
}
|
}
|
||||||
|
|
||||||
template<>
|
template <>
|
||||||
InternalRouteResult
|
InternalRouteResult
|
||||||
shortestPathSearch(SearchEngineData<corech::Algorithm> &engine_working_data,
|
shortestPathSearch(SearchEngineData<corech::Algorithm> &engine_working_data,
|
||||||
const datafacade::ContiguousInternalMemoryDataFacade<corech::Algorithm> &facade,
|
const datafacade::ContiguousInternalMemoryDataFacade<corech::Algorithm> &facade,
|
||||||
@ -506,6 +509,17 @@ shortestPathSearch(SearchEngineData<corech::Algorithm> &engine_working_data,
|
|||||||
engine_working_data, facade, phantom_nodes_vector, continue_straight_at_waypoint);
|
engine_working_data, facade, phantom_nodes_vector, continue_straight_at_waypoint);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
template <>
|
||||||
|
InternalRouteResult
|
||||||
|
shortestPathSearch(SearchEngineData<mld::Algorithm> &engine_working_data,
|
||||||
|
const datafacade::ContiguousInternalMemoryDataFacade<mld::Algorithm> &facade,
|
||||||
|
const std::vector<PhantomNodes> &phantom_nodes_vector,
|
||||||
|
const boost::optional<bool> continue_straight_at_waypoint)
|
||||||
|
{
|
||||||
|
return shortestPathSearchImpl(
|
||||||
|
engine_working_data, facade, phantom_nodes_vector, continue_straight_at_waypoint);
|
||||||
|
}
|
||||||
|
|
||||||
} // namespace routing_algorithms
|
} // namespace routing_algorithms
|
||||||
} // namespace engine
|
} // namespace engine
|
||||||
} // namespace osrm
|
} // namespace osrm
|
||||||
|
@ -7,13 +7,27 @@ namespace osrm
|
|||||||
namespace engine
|
namespace engine
|
||||||
{
|
{
|
||||||
|
|
||||||
template<typename Algorithm> typename SearchEngineData<Algorithm>::SearchEngineHeapPtr SearchEngineData<Algorithm>::forward_heap_1;
|
template <typename Algorithm>
|
||||||
template<typename Algorithm> typename SearchEngineData<Algorithm>::SearchEngineHeapPtr SearchEngineData<Algorithm>::reverse_heap_1;
|
typename SearchEngineData<Algorithm>::SearchEngineHeapPtr
|
||||||
template<typename Algorithm> typename SearchEngineData<Algorithm>::SearchEngineHeapPtr SearchEngineData<Algorithm>::forward_heap_2;
|
SearchEngineData<Algorithm>::forward_heap_1;
|
||||||
template<typename Algorithm> typename SearchEngineData<Algorithm>::SearchEngineHeapPtr SearchEngineData<Algorithm>::reverse_heap_2;
|
template <typename Algorithm>
|
||||||
template<typename Algorithm> typename SearchEngineData<Algorithm>::SearchEngineHeapPtr SearchEngineData<Algorithm>::forward_heap_3;
|
typename SearchEngineData<Algorithm>::SearchEngineHeapPtr
|
||||||
template<typename Algorithm> typename SearchEngineData<Algorithm>::SearchEngineHeapPtr SearchEngineData<Algorithm>::reverse_heap_3;
|
SearchEngineData<Algorithm>::reverse_heap_1;
|
||||||
template<typename Algorithm> typename SearchEngineData<Algorithm>::ManyToManyHeapPtr SearchEngineData<Algorithm>::many_to_many_heap;
|
template <typename Algorithm>
|
||||||
|
typename SearchEngineData<Algorithm>::SearchEngineHeapPtr
|
||||||
|
SearchEngineData<Algorithm>::forward_heap_2;
|
||||||
|
template <typename Algorithm>
|
||||||
|
typename SearchEngineData<Algorithm>::SearchEngineHeapPtr
|
||||||
|
SearchEngineData<Algorithm>::reverse_heap_2;
|
||||||
|
template <typename Algorithm>
|
||||||
|
typename SearchEngineData<Algorithm>::SearchEngineHeapPtr
|
||||||
|
SearchEngineData<Algorithm>::forward_heap_3;
|
||||||
|
template <typename Algorithm>
|
||||||
|
typename SearchEngineData<Algorithm>::SearchEngineHeapPtr
|
||||||
|
SearchEngineData<Algorithm>::reverse_heap_3;
|
||||||
|
template <typename Algorithm>
|
||||||
|
typename SearchEngineData<Algorithm>::ManyToManyHeapPtr
|
||||||
|
SearchEngineData<Algorithm>::many_to_many_heap;
|
||||||
|
|
||||||
template <typename Algorithm>
|
template <typename Algorithm>
|
||||||
void SearchEngineData<Algorithm>::InitializeOrClearFirstThreadLocalStorage(unsigned number_of_nodes)
|
void SearchEngineData<Algorithm>::InitializeOrClearFirstThreadLocalStorage(unsigned number_of_nodes)
|
||||||
@ -106,17 +120,18 @@ template SearchEngineData<CH>::SearchEngineHeapPtr SearchEngineData<CH>::forward
|
|||||||
template SearchEngineData<CH>::SearchEngineHeapPtr SearchEngineData<CH>::reverse_heap_3;
|
template SearchEngineData<CH>::SearchEngineHeapPtr SearchEngineData<CH>::reverse_heap_3;
|
||||||
template SearchEngineData<CH>::ManyToManyHeapPtr SearchEngineData<CH>::many_to_many_heap;
|
template SearchEngineData<CH>::ManyToManyHeapPtr SearchEngineData<CH>::many_to_many_heap;
|
||||||
|
|
||||||
template
|
template void
|
||||||
void SearchEngineData<routing_algorithms::ch::Algorithm>::InitializeOrClearFirstThreadLocalStorage(unsigned number_of_nodes);
|
SearchEngineData<routing_algorithms::ch::Algorithm>::InitializeOrClearFirstThreadLocalStorage(
|
||||||
|
unsigned number_of_nodes);
|
||||||
|
|
||||||
template
|
template void
|
||||||
void SearchEngineData<CH>::InitializeOrClearSecondThreadLocalStorage(unsigned number_of_nodes);
|
SearchEngineData<CH>::InitializeOrClearSecondThreadLocalStorage(unsigned number_of_nodes);
|
||||||
|
|
||||||
template
|
template void
|
||||||
void SearchEngineData<CH>::InitializeOrClearThirdThreadLocalStorage(unsigned number_of_nodes);
|
SearchEngineData<CH>::InitializeOrClearThirdThreadLocalStorage(unsigned number_of_nodes);
|
||||||
|
|
||||||
template
|
template void
|
||||||
void SearchEngineData<CH>::InitializeOrClearManyToManyThreadLocalStorage(unsigned number_of_nodes);
|
SearchEngineData<CH>::InitializeOrClearManyToManyThreadLocalStorage(unsigned number_of_nodes);
|
||||||
|
|
||||||
// CoreCH
|
// CoreCH
|
||||||
using CoreCH = routing_algorithms::corech::Algorithm;
|
using CoreCH = routing_algorithms::corech::Algorithm;
|
||||||
@ -128,23 +143,24 @@ template SearchEngineData<CoreCH>::SearchEngineHeapPtr SearchEngineData<CoreCH>:
|
|||||||
template SearchEngineData<CoreCH>::SearchEngineHeapPtr SearchEngineData<CoreCH>::reverse_heap_3;
|
template SearchEngineData<CoreCH>::SearchEngineHeapPtr SearchEngineData<CoreCH>::reverse_heap_3;
|
||||||
template SearchEngineData<CoreCH>::ManyToManyHeapPtr SearchEngineData<CoreCH>::many_to_many_heap;
|
template SearchEngineData<CoreCH>::ManyToManyHeapPtr SearchEngineData<CoreCH>::many_to_many_heap;
|
||||||
|
|
||||||
template
|
template void
|
||||||
void SearchEngineData<CoreCH>::InitializeOrClearFirstThreadLocalStorage(unsigned number_of_nodes);
|
SearchEngineData<CoreCH>::InitializeOrClearFirstThreadLocalStorage(unsigned number_of_nodes);
|
||||||
|
|
||||||
template
|
template void
|
||||||
void SearchEngineData<CoreCH>::InitializeOrClearSecondThreadLocalStorage(unsigned number_of_nodes);
|
SearchEngineData<CoreCH>::InitializeOrClearSecondThreadLocalStorage(unsigned number_of_nodes);
|
||||||
|
|
||||||
template
|
template void
|
||||||
void SearchEngineData<CoreCH>::InitializeOrClearThirdThreadLocalStorage(unsigned number_of_nodes);
|
SearchEngineData<CoreCH>::InitializeOrClearThirdThreadLocalStorage(unsigned number_of_nodes);
|
||||||
|
|
||||||
template
|
template void
|
||||||
void SearchEngineData<CoreCH>::InitializeOrClearManyToManyThreadLocalStorage(
|
SearchEngineData<CoreCH>::InitializeOrClearManyToManyThreadLocalStorage(unsigned number_of_nodes);
|
||||||
unsigned number_of_nodes);
|
|
||||||
|
|
||||||
// MLD
|
// MLD
|
||||||
using MLD = routing_algorithms::mld::Algorithm;
|
using MLD = routing_algorithms::mld::Algorithm;
|
||||||
SearchEngineData<MLD>::SearchEngineHeapPtr SearchEngineData<MLD>::forward_heap_1;
|
SearchEngineData<MLD>::SearchEngineHeapPtr SearchEngineData<MLD>::forward_heap_1;
|
||||||
SearchEngineData<MLD>::SearchEngineHeapPtr SearchEngineData<MLD>::reverse_heap_1;
|
SearchEngineData<MLD>::SearchEngineHeapPtr SearchEngineData<MLD>::reverse_heap_1;
|
||||||
|
SearchEngineData<MLD>::SearchEngineHeapPtr SearchEngineData<MLD>::forward_heap_2;
|
||||||
|
SearchEngineData<MLD>::SearchEngineHeapPtr SearchEngineData<MLD>::reverse_heap_2;
|
||||||
|
|
||||||
void SearchEngineData<MLD>::InitializeOrClearFirstThreadLocalStorage(unsigned number_of_nodes)
|
void SearchEngineData<MLD>::InitializeOrClearFirstThreadLocalStorage(unsigned number_of_nodes)
|
||||||
{
|
{
|
||||||
@ -167,5 +183,25 @@ void SearchEngineData<MLD>::InitializeOrClearFirstThreadLocalStorage(unsigned nu
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void SearchEngineData<MLD>::InitializeOrClearSecondThreadLocalStorage(unsigned)
|
||||||
|
{
|
||||||
|
if (forward_heap_2.get())
|
||||||
|
{
|
||||||
|
forward_heap_2->Clear();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
forward_heap_2.reset(new QueryHeap(1));
|
||||||
|
}
|
||||||
|
|
||||||
|
if (reverse_heap_2.get())
|
||||||
|
{
|
||||||
|
reverse_heap_2->Clear();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
reverse_heap_2.reset(new QueryHeap(1));
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user