1#ifndef ROUTING_KIT_CONTRACTION_HIERARCHY_H
2#define ROUTING_KIT_CONTRACTION_HIERARCHY_H
23 unsigned node_count, std::vector<unsigned>
tail, std::vector<unsigned>head, std::vector<unsigned>
weight,
28 std::vector<unsigned>
rank,
29 std::vector<unsigned>
tail, std::vector<unsigned>head, std::vector<unsigned>
weight,
34 std::vector<unsigned>
order,
35 std::vector<unsigned>
tail, std::vector<unsigned>head, std::vector<unsigned>
weight,
40 static ContractionHierarchy read(std::function<
void(
char*,
unsigned long long)>data_source,
unsigned long long file_size);
45 void write(std::function<
void(
const char*,
unsigned long long)>data_sink)
const;
46 void write(std::ostream&out)
const;
47 void save_file(
const std::string&file_name)
const;
74 template<
class InputWeightContainer,
class LinkFunction>
77 template<
class InputWeightContainer,
class LinkFunction>
85 using ReturnTypeWhenPassedIntOf =
typename std::remove_const<typename std::remove_reference<decltype(std::declval<T>()(1))>::type>::type;
88 using ValueTypeOfContainer =
typename std::remove_const<typename std::remove_reference<decltype(std::declval<T>()[1])>::type>::type;
124 template<
class ExtraWeight,
class LinkFunction>
194 template<
class ExtraWeight,
class LinkFunction> std::vector<detail::GetExtraWeightType<ExtraWeight>>
get_extra_weight_distances_to_targets(
const ExtraWeight&extra_weight,
const LinkFunction&link);
195 template<
class ExtraWeight,
class LinkFunction,
class TmpContainer> std::vector<detail::GetExtraWeightType<ExtraWeight>>
get_extra_weight_distances_to_targets(
const ExtraWeight&extra_weight,
const LinkFunction&link, TmpContainer&tmp);
197 template<
class ExtraWeight,
class LinkFunction> std::vector<detail::GetExtraWeightType<ExtraWeight>>
get_extra_weight_distances_to_sources(
const ExtraWeight&extra_weight,
const LinkFunction&link);
198 template<
class ExtraWeight,
class LinkFunction,
class TmpContainer> std::vector<detail::GetExtraWeightType<ExtraWeight>>
get_extra_weight_distances_to_sources(
const ExtraWeight&extra_weight,
const LinkFunction&link, TmpContainer&tmp);
223 unsigned operator()(
unsigned l,
unsigned r)
const;
241template<
class ExtraWeight,
class LinkFunction>
243 const ExtraWeight&extra_weight,
244 const LinkFunction&link
251template<
class ExtraWeight,
class LinkFunction,
class TmpContainer>
253 const ExtraWeight&extra_weight,
254 const LinkFunction&link,
263template<
class ExtraWeight,
class LinkFunction>
265 const ExtraWeight&extra_weight,
266 const LinkFunction&link
273template<
class ExtraWeight,
class LinkFunction,
class TmpContainer>
275 const ExtraWeight&extra_weight,
276 const LinkFunction&link,
286 assert(l <=
inf_weight &&
"unsigned weight must not be larger than inf_weight");
287 assert(r <=
inf_weight &&
"unsigned weight must not be larger than inf_weight");
296 static_assert(
inf_weight == INT_MAX,
"this function assumes that inf_weight is INT_MAX");
298 if (r > INT_MAX - l){
301 }
else if(r < INT_MIN - l){
309 template<
class LinkFunction>
313 template<
class L,
class R>
315 ->
decltype(std::declval<LinkFunction>()(std::forward<R>(r), std::forward<L>(l)))
317 return link(std::forward<R>(r), std::forward<L>(l));
323 template<
class LinkFunction>
328 template<
class InputWeightContainer,
class LinkFunction>
330 typedef typename std::remove_reference<decltype(std::declval<InputWeightContainer>()[0])>::type
Weight;
359 template<
class WeightT,
class LinkFunction>
367 extra_weight(extra_weight){}
378 template<
class ExtraWeight,
class LinkFunction>
383 template<
class ShortcutWeights>
400 template<
class ShortcutWeights>
405 template<
class GetForwardWeight,
class LinkFunction>
407 unsigned shortest_path_meeting_node,
408 const std::vector<unsigned>&forward_predecessor_node,
409 const std::vector<unsigned>&forward_predecessor_arc,
410 const GetForwardWeight&get_forward_extra_weight,
411 const LinkFunction&link
415 unsigned x = shortest_path_meeting_node;
416 assert(forward_predecessor_node[x] !=
invalid_id);
417 Weight ret = get_forward_extra_weight(forward_predecessor_arc[x]);
418 x = forward_predecessor_node[x];
420 while(forward_predecessor_node[x] !=
invalid_id){
421 ret = link(get_forward_extra_weight(forward_predecessor_arc[x]), ret);
422 x = forward_predecessor_node[x];
428 template<
class ShortcutWeights,
class LinkFunction>
431 const LinkFunction&link,
432 unsigned shortest_path_meeting_node,
433 const std::vector<unsigned>&forward_predecessor_node,
434 const std::vector<unsigned>&forward_predecessor_arc,
435 const std::vector<unsigned>&backward_predecessor_node,
436 const std::vector<unsigned>&backward_predecessor_arc
446 bool has_up_part = forward_predecessor_node[shortest_path_meeting_node] !=
invalid_id;
447 bool has_down_part = backward_predecessor_node[shortest_path_meeting_node] !=
invalid_id;
451 if(!has_up_part && !has_down_part) {
453 }
else if(has_up_part && has_down_part) {
456 shortest_path_meeting_node,
457 forward_predecessor_node,
458 forward_predecessor_arc,
459 [&](
unsigned a)->
decltype(shortcut_weights.
get_forward_weight(a)){return shortcut_weights.get_forward_weight(a);},
463 shortest_path_meeting_node,
464 backward_predecessor_node,
465 backward_predecessor_arc,
466 [&](
unsigned a)->decltype(shortcut_weights.
get_backward_weight(a)){return shortcut_weights.get_backward_weight(a);},
470 }
else if(has_up_part) {
472 shortest_path_meeting_node,
473 forward_predecessor_node,
474 forward_predecessor_arc,
475 [&](
unsigned a)->
decltype(shortcut_weights.
get_forward_weight(a)){return shortcut_weights.get_forward_weight(a);},
480 shortest_path_meeting_node,
481 backward_predecessor_node,
482 backward_predecessor_arc,
483 [&](
unsigned a)->
decltype(shortcut_weights.
get_backward_weight(a)){return shortcut_weights.get_backward_weight(a);},
491template<
class ExtraWeight,
class LinkFunction>
493 const ExtraWeight&extra_weight,
494 const LinkFunction&link){
495 assert(
ch &&
"query object must have an attached CH");
501 shortcut_weight, link,
508template<
class Weight>
template<
class InputWeightContainer,
class LinkFunction>
520 forward_weight[xy] = link(
530 backward_weight[xy] = link(
542 template<
class LinkFunction,
class ExtraWeight,
class TmpContainer,
class DistContainer>
544 const std::vector<unsigned>&target_list,
545 unsigned target_count,
548 const std::vector<unsigned>&forward_predecessor_node,
549 const std::vector<unsigned>&predecessor_arc,
551 const ExtraWeight&extra_weight,
552 const std::vector<unsigned>&forward_first_out,
553 const std::vector<unsigned>&forward_head,
554 const std::vector<unsigned>&backward_first_out,
555 const std::vector<unsigned>&backward_head,
557 TmpContainer&source_to_node_distance,
560 DistContainer&output,
562 std::vector<unsigned>&stack,
564 const LinkFunction&link
566 using Weight =
typename ExtraWeight::Weight;
570 unsigned nodes_on_stack_with_forward_precessor_count = 0;
571 unsigned stack_size = 0;
573 auto push = [&](
unsigned x){
574 assert(stack_size < stack.size());
575 stack[stack_size++] = x;
579 assert(stack_size != 0);
580 return stack[--stack_size];
583 auto single_forward_step_expand_distance_to_node = [&](
unsigned x){
584 assert(!has_source_to_node_distance.
is_set(x));
585 assert(has_forward_predecessor.
is_set(x));
586 assert(forward_predecessor_node[x] !=
invalid_id);
588 unsigned a = predecessor_arc[x];
589 unsigned p = forward_predecessor_node[x];
591 if(has_source_to_node_distance.
is_set(p))
592 source_to_node_distance[x] = link(source_to_node_distance[p], extra_weight.get_forward_weight(a));
594 source_to_node_distance[x] = extra_weight.get_forward_weight(a);
595 has_source_to_node_distance.
set(x);
598 auto single_backward_step_expand_distance_to_node = [&](
unsigned x){
599 assert(!has_source_to_node_distance.
is_set(x));
600 assert(!has_forward_predecessor.
is_set(x));
602 unsigned a = predecessor_arc[x];
603 unsigned p = backward_head[a];
605 if(has_source_to_node_distance.
is_set(p))
606 source_to_node_distance[x] = link(source_to_node_distance[p], extra_weight.get_backward_weight(a));
608 source_to_node_distance[x] = extra_weight.get_backward_weight(a);
610 has_source_to_node_distance.
set(x);
613 auto push_non_reached_nodes = [&](
unsigned x){
614 assert(!has_source_to_node_distance.
is_set(x));
615 while(!has_forward_predecessor.
is_set(x)){
617 unsigned y = backward_head[predecessor_arc[x]];
620 if(has_source_to_node_distance.
is_set(x))
623 while(forward_predecessor_node[x] !=
invalid_id){
624 assert(has_forward_predecessor.
is_set(x));
626 ++nodes_on_stack_with_forward_precessor_count;
627 unsigned y = forward_predecessor_node[x];
630 if(has_source_to_node_distance.
is_set(x))
633 source_to_node_distance[x] = Weight{};
636 auto expand_distances_from_source_to_node = [&](
unsigned x){
637 if(!has_source_to_node_distance.
is_set(x)){
638 push_non_reached_nodes(x);
639 while(stack_size != 0){
641 if(nodes_on_stack_with_forward_precessor_count != 0){
642 --nodes_on_stack_with_forward_precessor_count;
643 single_forward_step_expand_distance_to_node(y);
645 single_backward_step_expand_distance_to_node(y);
651 for(
unsigned i=0; i<target_count; ++i){
652 unsigned t = target_list[i];
656 output[i] = Weight{};
658 expand_distances_from_source_to_node(t);
659 output[i] = source_to_node_distance[t];
665template<
class ExtraWeight,
class LinkFunction,
class TmpContainer,
class DistContainer>
667 const ExtraWeight&extra_weight,
668 const LinkFunction&link,
701template<
class ExtraWeight,
class LinkFunction,
class TmpContainer,
class DistContainer>
703 const ExtraWeight&extra_weight,
704 const LinkFunction&link,
721 inverted_shortcut_weight,
bool is_set(uint64_t x) const
void save_file(const std::string &file_name) const
unsigned node_count() const
static ContractionHierarchy build_given_rank(std::vector< unsigned >rank, std::vector< unsigned >tail, std::vector< unsigned >head, std::vector< unsigned >weight, const std::function< void(std::string)> &log_message=std::function< void(std::string)>(), unsigned max_pop_count=default_max_pop_count)
void write(std::function< void(const char *, unsigned long long)>data_sink) const
std::vector< unsigned > order
static const unsigned default_max_pop_count
static ContractionHierarchy read(std::function< void(char *, unsigned long long)>data_source)
static ContractionHierarchy load_file(const std::string &file_name)
static ContractionHierarchy build(unsigned node_count, std::vector< unsigned >tail, std::vector< unsigned >head, std::vector< unsigned >weight, const std::function< void(std::string)> &log_message=std::function< void(std::string)>(), unsigned max_pop_count=default_max_pop_count)
std::vector< unsigned > rank
static ContractionHierarchy build_given_order(std::vector< unsigned >order, std::vector< unsigned >tail, std::vector< unsigned >head, std::vector< unsigned >weight, const std::function< void(std::string)> &log_message=std::function< void(std::string)>(), unsigned max_pop_count=default_max_pop_count)
std::vector< unsigned > get_distances_to_targets()
enum RoutingKit::ContractionHierarchyQuery::InternalState state
ContractionHierarchyQuery()
std::vector< unsigned > backward_predecessor_node
ContractionHierarchyQuery & reset()
std::vector< unsigned > backward_predecessor_arc
unsigned many_to_many_source_or_target_count
std::vector< unsigned > get_distances_to_sources()
std::vector< detail::GetExtraWeightType< ExtraWeight > > get_extra_weight_distances_to_targets(const ExtraWeight &extra_weight, const LinkFunction &link)
ContractionHierarchyQuery & pin_targets(const std::vector< unsigned > &)
unsigned get_pinned_target_count()
std::vector< unsigned > get_node_path()
const ContractionHierarchy * ch
std::vector< unsigned > forward_predecessor_arc
std::vector< unsigned > get_used_sources_to_targets()
ContractionHierarchyQuery & reset_source()
std::vector< unsigned > forward_tentative_distance
ContractionHierarchyQuery & run_to_pinned_targets()
std::vector< unsigned > backward_tentative_distance
detail::GetExtraWeightType< ExtraWeight > get_extra_weight_distance(const ExtraWeight &extra_weight, const LinkFunction &link)
std::vector< unsigned > get_arc_path()
unsigned get_used_source()
ContractionHierarchyQuery & run_to_pinned_sources()
ContractionHierarchyQuery & add_source(unsigned s, unsigned dist_to_s=0)
TimestampFlags was_backward_pushed
unsigned get_used_target()
std::vector< unsigned > get_used_targets_to_sources()
ContractionHierarchyQuery & pin_sources(const std::vector< unsigned > &)
ContractionHierarchyQuery & run()
unsigned shortest_path_meeting_node
ContractionHierarchyQuery & add_target(unsigned t, unsigned dist_to_t=0)
std::vector< unsigned > forward_predecessor_node
unsigned get_pinned_source_count()
TimestampFlags was_forward_pushed
std::vector< detail::GetExtraWeightType< ExtraWeight > > get_extra_weight_distances_to_sources(const ExtraWeight &extra_weight, const LinkFunction &link)
ContractionHierarchyQuery & reset_target()
MinIDQueue backward_queue
bool is_set(unsigned id) const
std::vector< unsigned > tail
ReturnTypeWhenPassedIntOf< GetForwardWeight > get_extra_weight_up_distance(unsigned shortest_path_meeting_node, const std::vector< unsigned > &forward_predecessor_node, const std::vector< unsigned > &forward_predecessor_arc, const GetForwardWeight &get_forward_extra_weight, const LinkFunction &link)
typename GetExtraWeightTypeHelper< T >::type GetExtraWeightType
ShortcutWeights< ExtraWeight, LinkFunction > make_shortcut_weights(const ExtraWeight &extra_weight, const LinkFunction &link, const ContractionHierarchy &ch)
typename std::remove_const< typename std::remove_reference< decltype(std::declval< T >()(1))>::type >::type ReturnTypeWhenPassedIntOf
void extract_distances_to_targets(const std::vector< unsigned > &target_list, unsigned target_count, const TimestampFlags &has_forward_predecessor, const std::vector< unsigned > &forward_predecessor_node, const std::vector< unsigned > &predecessor_arc, const ExtraWeight &extra_weight, const std::vector< unsigned > &forward_first_out, const std::vector< unsigned > &forward_head, const std::vector< unsigned > &backward_first_out, const std::vector< unsigned > &backward_head, TmpContainer &source_to_node_distance, TimestampFlags &has_source_to_node_distance, DistContainer &output, std::vector< unsigned > &stack, const LinkFunction &link)
InverseLinkFunction< LinkFunction > inverse_link_function(const LinkFunction &link)
typename std::remove_const< typename std::remove_reference< decltype(std::declval< T >()[1])>::type >::type ValueTypeOfContainer
ShortcutWeights::Weight internal_get_extra_weight_distance(const ShortcutWeights &shortcut_weights, const LinkFunction &link, unsigned shortest_path_meeting_node, const std::vector< unsigned > &forward_predecessor_node, const std::vector< unsigned > &forward_predecessor_arc, const std::vector< unsigned > &backward_predecessor_node, const std::vector< unsigned > &backward_predecessor_arc)
InvertShorcutWeights< ShortcutWeights > inverse_shortcut_weights(const ShortcutWeights &shortcut_weights)
void check_contraction_hierarchy_for_errors(const ContractionHierarchy &ch)
const unsigned invalid_id
const unsigned inf_weight
std::vector< unsigned > first_out
std::vector< unsigned > weight
std::vector< unsigned > head
std::vector< unsigned > shortcut_first_arc
BitVector is_shortcut_an_original_arc
std::vector< unsigned > shortcut_second_arc
unsigned operator()(unsigned l, unsigned r) const
const LinkFunction & link
InverseLinkFunction(const LinkFunction &link)
auto operator()(L &&l, R &&r) const -> decltype(std::declval< LinkFunction >()(std::forward< R >(r), std::forward< L >(l)))
auto get_backward_weight(unsigned a) const -> decltype(std::declval< ShortcutWeights >().get_forward_weight(a))
InvertShorcutWeights(const ShortcutWeights &shortcut_weights)
auto get_forward_weight(unsigned a) const -> decltype(std::declval< ShortcutWeights >().get_backward_weight(a))
ShortcutWeights::Weight Weight
const ShortcutWeights & shortcut_weights
std::remove_reference< decltype(std::declval< InputWeightContainer >()[0])>::type Weight
Weight get_backward_weight(unsigned a) const
const ContractionHierarchy & ch
ShortcutWeights(const InputWeightContainer &input_weight, const LinkFunction &link, const ContractionHierarchy &ch)
const LinkFunction & link
Weight get_forward_weight(unsigned a) const
const InputWeightContainer & input_weight