25 template<
class OnNewArc>
26 unsigned compute_chordal_supergraph(
unsigned node_count,
const std::vector<unsigned>&
tail,
const std::vector<unsigned>&head,
const OnNewArc&on_new_arc){
27 std::vector<std::vector<unsigned>> nodes(
node_count);
28 for(
unsigned i = 0; i <
tail.size(); ++i){
29 if(
tail[i] < head[i]) {
30 nodes[
tail[i]].push_back(head[i]);
35 std::sort(nodes[n].begin(), nodes[n].end());
36 auto it = std::unique(nodes[n].begin(), nodes[n].end());
37 nodes[n].resize(std::distance(nodes[n].begin(), it));
40 size_t max_upward_degree = 0;
42 if(nodes[n].size() == 0){
continue; }
43 const unsigned lowest_neighbor = nodes[n][0];
45 std::vector<unsigned> merged(nodes[n].size() + nodes[lowest_neighbor].size() - 1);
46 std::merge(++nodes[n].begin(), nodes[n].end(), nodes[lowest_neighbor].begin(), nodes[lowest_neighbor].end(), merged.begin());
47 auto it = std::unique(merged.begin(), merged.end());
48 merged.resize(std::distance(merged.begin(), it));
49 nodes[lowest_neighbor] = std::move(merged);
51 for(
unsigned neighbor : nodes[n]){
52 on_new_arc(n, neighbor);
54 max_to(max_upward_degree, nodes[n].size());
56 return max_upward_degree;
69 bool forall_upper_triangles_of_arc(
const CustomizableContractionHierarchy&
cch,
unsigned x,
unsigned y,
unsigned xy,
const F&f){
70 unsigned x_up_arc = xy+1;
76 while(x_up_arc != x_up_arc_end && y_up_arc != y_up_arc_end){
83 if(!f(xy, x_up_arc, y_up_arc, x, y, z))
93 bool forall_upper_triangles_of_arc(
const CustomizableContractionHierarchy&
cch,
unsigned xy,
const F&f){
98 bool forall_intermediate_triangles_of_arc(
const CustomizableContractionHierarchy&
cch,
unsigned x,
unsigned y,
unsigned xy,
const F&f){
100 unsigned x_up_arc_end = xy;
105 while(x_up_arc != x_up_arc_end && y_down_arc != y_down_arc_end){
122 bool forall_intermediate_triangles_of_arc(
const CustomizableContractionHierarchy&
cch,
unsigned xy,
const F&f){
127 bool forall_lower_triangles_of_arc(
const CustomizableContractionHierarchy&
cch,
unsigned x,
unsigned y,
unsigned xy,
const F&f){
134 while(x_down_arc != x_down_arc_end && y_down_arc != y_down_arc_end){
151 bool forall_lower_triangles_of_arc(
const CustomizableContractionHierarchy&
cch,
unsigned xy,
const F&f){
156 struct TriangleVerifier{
159 explicit TriangleVerifier(
const CustomizableContractionHierarchy&cch):
cch(&
cch){}
162 unsigned bottom_arc,
unsigned mid_arc,
unsigned top_arc,
163 unsigned bottom_node,
unsigned mid_node,
unsigned top_node
166 assert(bottom_node != top_node);
169 assert(bottom_arc != mid_arc);
170 assert(bottom_arc != top_arc);
171 assert(mid_arc != top_arc);
176 assert(bottom_arc < mid_arc);
177 assert(mid_arc < top_arc);
179 assert(
cch->up_tail[bottom_arc] == bottom_node);
182 assert(
cch->up_tail[mid_arc] == bottom_node);
183 assert(
cch->up_head[mid_arc] == top_node);
186 assert(
cch->up_head[top_arc] == top_node);
191 const CustomizableContractionHierarchy*
cch;
197 std::vector<unsigned>arg_order,
198 std::vector<unsigned>input_tail,
199 std::vector<unsigned>input_head,
200 std::function<
void(
const std::string&)>log_message,
201 bool filter_always_inf_arcs
203 order(
std::move(arg_order))
211 log_message(
"Building CCH");
218 std::vector<unsigned> raw_input_tail = input_tail;
219 std::vector<unsigned> raw_input_head = input_head;
224 log_message(
"Start reordering nodes according to order");
233 log_message(
"Finished reordering nodes, needed "+std::to_string(timer)+
"musec");
236 std::vector<unsigned>input_arc_id;
239 log_message(
"Start sorting arcs");
250 log_message(
"Finished sorting arcs, needed "+std::to_string(timer)+
"musec");
255 assert(
rank[raw_input_head[input_arc_id[input_arc]]] == input_head[input_arc]);
256 assert(
rank[raw_input_tail[input_arc_id[input_arc]]] == input_tail[input_arc]);
263 log_message(
"Start building chordal supergraph");
270 std::copy(input_tail.begin(), input_tail.end(), symmetric_tail.begin());
271 std::copy(input_head.begin(), input_head.end(), symmetric_head.begin());
272 std::copy(input_tail.begin(), input_tail.end(), symmetric_head.begin()+
input_arc_count);
273 std::copy(input_head.begin(), input_head.end(), symmetric_tail.begin()+
input_arc_count);
282 filter.
set(0, symmetric_tail[0] != symmetric_head[0]);
284 filter.
set(i, (symmetric_head[i] != symmetric_head[i-1] || symmetric_tail[i] != symmetric_tail[i-1]) && (symmetric_tail[i] != symmetric_head[i]));
289 unsigned upper_treewidth_bound = compute_chordal_supergraph(
291 [&](
unsigned x,
unsigned y){
294 log_message(
"CCH Construction aborted because chordal supergraph contains 2^32 or more arcs");
295 throw std::runtime_error(
"CCH must contain at most 2^32-1 arcs");
303 log_message(
"The treewidth of the input graph is bounded by "+std::to_string(upper_treewidth_bound));
321 log_message(
"Finished building chordal supergraph, needed "+std::to_string(timer)+
"musec");
322 log_message(
"Chordal supergraph contains "+std::to_string(
cch_arc_count)+
" arcs");
328 log_message(
"Start computing mapping from input arcs to CCH arcs");
340 unsigned cch_up_arc = 0;
342 if(input_tail[input_arc] < input_head[input_arc]){
343 while(input_tail[input_arc] !=
up_tail[cch_up_arc] || input_head[input_arc] !=
up_head[cch_up_arc]){
347 assert(input_tail[input_arc] ==
up_tail[cch_up_arc]);
348 assert(input_head[input_arc] ==
up_head[cch_up_arc]);
351 }
else if(input_tail[input_arc] == input_head[input_arc]){
365 unsigned cch_up_arc = 0;
367 if(input_tail[input_arc] < input_head[input_arc]){
368 while(input_tail[input_arc] !=
up_tail[cch_up_arc] || input_head[input_arc] !=
up_head[cch_up_arc]){
380 log_message(
"Finished computing mapping, needed "+std::to_string(timer)+
"musec");
384 log_message(
"Start computing elimination tree");
416 log_message(
"Finished computing elimination tree, needed "+std::to_string(timer)+
"musec");
420 std::vector<unsigned>
424 for(
unsigned x=
node_count-1; x!=(unsigned)-1; --x){
429 nodes_in_search_space[x] = 1;
430 arcs_in_search_space[x] = 0;
434 unsigned max_nodes_in_search_space = 0;
435 unsigned max_arcs_in_search_space = 0;
436 unsigned long long nodes_in_search_space_sum = 0;
437 unsigned long long arcs_in_search_space_sum = 0;
440 max_to(max_nodes_in_search_space, nodes_in_search_space[x]);
441 max_to(max_arcs_in_search_space, arcs_in_search_space[x]);
442 nodes_in_search_space_sum += nodes_in_search_space[x];
443 arcs_in_search_space_sum += arcs_in_search_space[x];
445 log_message(
"The average number of nodes in a search space is "+std::to_string(nodes_in_search_space_sum/
node_count));
446 log_message(
"The maximum number of nodes in a search space is "+std::to_string(max_nodes_in_search_space));
447 log_message(
"The average number of arcs in a search space is "+std::to_string(arcs_in_search_space_sum/
node_count));
448 log_message(
"The maximum number of arcs in a search space is "+std::to_string(max_arcs_in_search_space));
452 if(!filter_always_inf_arcs)
453 log_message(
"Not filtering upward arcs");
457 log_message(
"Start filtering upward arcs");
473 can_forward_weight_be_non_inf.set(cch_arc);
475 can_backward_weight_be_non_inf.
set(cch_arc);
480 unsigned long long triangle_count = 0;
483 forall_upper_triangles_of_arc(
486 unsigned bottom_arc,
unsigned mid_arc,
unsigned top_arc,
487 unsigned bottom_node,
unsigned mid_node,
unsigned top_node
489 (void) bottom_node; (void)
mid_node; (void) top_node;
493 if(!can_forward_weight_be_non_inf.is_set(top_arc)){
494 if(can_backward_weight_be_non_inf.
is_set(bottom_arc) && can_forward_weight_be_non_inf.is_set(mid_arc))
495 can_forward_weight_be_non_inf.set(top_arc);
498 if(!can_backward_weight_be_non_inf.
is_set(top_arc)){
499 if(can_forward_weight_be_non_inf.is_set(bottom_arc) && can_backward_weight_be_non_inf.
is_set(mid_arc))
500 can_backward_weight_be_non_inf.
set(top_arc);
509 BitVector must_keep_arc = can_forward_weight_be_non_inf | can_backward_weight_be_non_inf;
522 log_message(
"Finished filtering upward arcs, needed "+std::to_string(timer)+
"musec");
524 log_message(
"The number of triangles before filtering was "+std::to_string(triangle_count)+
". (The value after filtering was not determined.)");
531 log_message(
"Start computing downward arcs");
547 log_message(
"Finished computing downward arcs, needed "+std::to_string(timer)+
"musec");
551 log_message(
"Start computing mapping from CCH arcs to input arcs");
612 [](
unsigned x){return x;}
628 [](
unsigned x){return x;}
643 log_message(
"Finished computing mapping, needed "+std::to_string(timer)+
"musec");
686 void extract_initial_metric(
const CustomizableContractionHierarchy&
cch, CustomizableContractionHierarchyMetric&
metric){
688 extract_initial_metric_of_cch_arc(
cch,
metric, cch_arc);
692 struct LowerTriangleRelaxer{
694 LowerTriangleRelaxer(){}
695 explicit LowerTriangleRelaxer(CustomizableContractionHierarchyMetric&metric):
metric(&
metric){}
698 unsigned bottom_arc,
unsigned mid_arc,
unsigned top_arc,
699 unsigned bottom_node,
unsigned mid_node,
unsigned top_node
709 CustomizableContractionHierarchyMetric*
metric;
713 struct LowerTriangleInequalityVerifier{
715 LowerTriangleInequalityVerifier(){}
716 explicit LowerTriangleInequalityVerifier(CustomizableContractionHierarchyMetric&metric):
metric(&
metric){}
719 unsigned bottom_arc,
unsigned mid_arc,
unsigned top_arc,
720 unsigned bottom_node,
unsigned mid_node,
unsigned top_node
725 assert(
metric->forward[top_arc] <=
metric->backward[bottom_arc] +
metric->forward[mid_arc]);
726 assert(
metric->backward[top_arc] <=
metric->forward[bottom_arc] +
metric->backward[mid_arc]);
730 CustomizableContractionHierarchyMetric*
metric;
750 assert(
cch &&
"Need to be attached to a CCH");
757 assert(input_weight_ !=
nullptr &&
"Input weight pointer must not be null");
768 assert(input_weight_ !=
nullptr &&
"Input weight pointer must not be null");
774 assert(
input_weight !=
nullptr &&
"Metric must be connected to a weight vector");
776 extract_initial_metric(*
cch, *
this);
782 for(
unsigned xz_up =
cch->
up_first_out[x]; xz_up < xz_up_end; ++xz_up){
787 for(
unsigned xy_down =
cch->
down_first_out[x]; xy_down < xy_down_end; ++xy_down){
791 for(
unsigned yz_up_reversed =
cch->
up_first_out[y+1]; yz_up_reversed > yz_up_end_reversed; --yz_up_reversed){
792 const unsigned yz_up = yz_up_reversed-1;
794 if (z <= x) {
break; }
795 LowerTriangleRelaxer(*
this)(yx_up, yz_up, arc_id_cache[z], y, x, z);
802 forall_upper_triangles_of_arc(*
cch, a, LowerTriangleInequalityVerifier(*
this));
809 void atomic_min_to(T&x,
const T&y){
811 while(y < z && !__sync_bool_compare_and_swap(&x, z, y))
815 struct AtomicLowerTriangleRelaxer{
817 AtomicLowerTriangleRelaxer(){}
818 explicit AtomicLowerTriangleRelaxer(CustomizableContractionHierarchyMetric&metric):
metric(&
metric){}
821 unsigned bottom_arc,
unsigned mid_arc,
unsigned top_arc,
822 unsigned bottom_node,
unsigned mid_node,
unsigned top_node
827 atomic_min_to(
metric->forward[top_arc],
metric->backward[bottom_arc] +
metric->forward[mid_arc] );
828 atomic_min_to(
metric->backward[top_arc],
metric->forward[bottom_arc] +
metric->backward[mid_arc]);
832 CustomizableContractionHierarchyMetric*
metric;
840 unsigned level_count;
843 std::vector<unsigned>zero_lock_list(
node_count);
844 unsigned zero_lock_count = 0;
848 zero_lock_list[zero_lock_count] = x;
854 std::vector<unsigned>next_zero_lock_list(
node_count);
855 while(zero_lock_count != 0){
856 unsigned next_zero_lock_count = 0;
857 for(
unsigned i=0; i<zero_lock_count; ++i){
858 unsigned x = zero_lock_list[i];
859 node_level[x] = level_count;
864 next_zero_lock_list[next_zero_lock_count] = y;
865 ++next_zero_lock_count;
870 std::swap(next_zero_lock_list, zero_lock_list);
871 zero_lock_count = next_zero_lock_count;
877 std::vector<unsigned>arc_level(arc_count);
886 arc_level[j] = node_level[x];
910 assert(thread_count != 0);
911 assert(
metric.input_weight !=
nullptr &&
"Metric must be connected to a weight vector");
913 if(thread_count == 1){
917 #pragma omp parallel num_threads(thread_count)
924 extract_initial_metric_of_cch_arc(*
cch,
metric, cch_arc);
929 #pragma omp for schedule(dynamic,256)
941 forall_upper_triangles_of_arc(*
cch, a, LowerTriangleInequalityVerifier(
metric));
948 q(cch_.cch_arc_count()),
976 assert(
metric.input_weight !=
nullptr &&
"Metric must be connected to a weight vector");
979 unsigned xy =
q.
pop();
981 unsigned old_forward =
metric.forward[xy];
982 unsigned old_backward =
metric.backward[xy];
987 extract_initial_metric_of_cch_arc(*
cch,
metric, xy);
989 forall_lower_triangles_of_arc(
991 LowerTriangleRelaxer(
metric)
994 unsigned new_forward =
metric.forward[xy];
995 unsigned new_backward =
metric.backward[xy];
997 if(old_forward != new_forward || old_backward != new_backward){
998 forall_intermediate_triangles_of_arc(
1001 unsigned bottom_arc,
unsigned mid_arc,
unsigned top_arc,
1002 unsigned bottom_node,
unsigned mid_node,
unsigned top_node
1004 assert(mid_arc == xy);
1006 metric.backward[bottom_arc] + old_forward ==
metric.forward[top_arc] ||
1007 metric.forward[bottom_arc] + old_backward ==
metric.backward[top_arc] ||
1008 metric.backward[bottom_arc] + new_forward <
metric.forward[top_arc] ||
1009 metric.forward[bottom_arc] + new_backward <
metric.backward[top_arc]
1016 forall_upper_triangles_of_arc(
1019 unsigned bottom_arc,
unsigned mid_arc,
unsigned top_arc,
1020 unsigned bottom_node,
unsigned mid_node,
unsigned top_node
1022 assert(bottom_arc == xy);
1024 metric.forward[mid_arc] + old_backward ==
metric.forward[top_arc] ||
1025 metric.backward[mid_arc] + old_forward ==
metric.backward[top_arc] ||
1026 metric.forward[mid_arc] + new_backward <
metric.forward[top_arc] ||
1027 metric.backward[mid_arc] + new_forward <
metric.backward[top_arc]
1038 forall_upper_triangles_of_arc(*
cch, a, LowerTriangleInequalityVerifier(
metric));
1044 const unsigned query_state_initialized = 0;
1045 const unsigned query_state_run = 1;
1046 const unsigned query_state_source_pinned = 2;
1047 const unsigned query_state_source_run = 3;
1048 const unsigned query_state_target_pinned = 4;
1049 const unsigned query_state_target_run = 5;
1055 void forall_ancestors(
const std::vector<unsigned>&parent,
unsigned x,
unsigned stop_at,
const F&f){
1056 assert(x < parent.size());
1057 assert(stop_at < parent.size() || stop_at ==
invalid_id);
1059 while(x != stop_at){
1060 assert(x < parent.size() &&
"stop_at is not an ancestor of x");
1063 assert(parent[x] > x);
1069 void forall_ancestors(
const std::vector<unsigned>&parent,
unsigned x,
const F&f){
1074 void reset_source_list(
1075 const std::vector<unsigned>&elimination_tree_parent,
1076 std::vector<unsigned>&source_node, std::vector<unsigned>&source_elimination_tree_end,
1079 for(
unsigned i=0; i<source_node.size(); ++i){
1081 elimination_tree_parent,
1082 source_node[i], source_elimination_tree_end[i],
1084 in_forward_search_space[x] =
false;
1090 source_node.clear();
1091 source_elimination_tree_end.clear();
1105 state(query_state_initialized){}
1108 void internal_add_source(
1109 unsigned external_s,
unsigned dist_to_s,
1110 const std::vector<unsigned>&rank,
1111 const std::vector<unsigned>&elimination_tree_parent,
1113 std::vector<unsigned>&forward_predecessor_node,
1114 std::vector<bool>&in_forward_search_space,
1115 std::vector<unsigned>&source_node,
1116 std::vector<unsigned>&source_elimination_tree_end
1118 unsigned s = rank[external_s];
1122 source_node.push_back(s);
1127 elimination_tree_parent, s,
1129 if(!in_forward_search_space[x]){
1130 in_forward_search_space[x] =
true;
1133 source_elimination_tree_end.push_back(x);
1138 if(source_elimination_tree_end.size() != source_node.size())
1139 source_elimination_tree_end.push_back(
invalid_id);
1151 assert(
state == query_state_initialized ||
state == query_state_target_pinned);
1152 internal_add_source(
1153 external_s, dist_to_s,
1167 assert(
state == query_state_initialized ||
state == query_state_source_pinned);
1168 internal_add_source(
1169 external_t, dist_to_t,
1182 template<
class SetPred>
1183 void relax_outgoing_arcs(
1184 const std::vector<unsigned>&first_out,
1185 const std::vector<unsigned>&head,
1186 const std::vector<unsigned>&
weight,
1187 std::vector<unsigned>&tentative_distance,
1188 const SetPred&set_node_predecessor,
1192 for(
unsigned xy=first_out[x]; xy<first_out[x+1]; ++xy){
1193 unsigned y=head[xy];
1194 if(tentative_distance[x] +
weight[xy] < tentative_distance[y]){
1195 tentative_distance[y] = tentative_distance[x] +
weight[xy];
1196 set_node_predecessor(y, x);
1201 template<
class SetPred>
1202 void relax_incoming_arcs(
1203 const std::vector<unsigned>&first_out,
1204 const std::vector<unsigned>&head,
1205 const std::vector<unsigned>&
weight,
1206 std::vector<unsigned>&tentative_distance,
1207 const SetPred&set_node_predecessor,
1210 for(
unsigned xy=first_out[x]; xy<first_out[x+1]; ++xy){
1211 unsigned y=head[xy];
1212 if(tentative_distance[y] +
weight[xy] < tentative_distance[x]){
1213 tentative_distance[x] = tentative_distance[y] +
weight[xy];
1214 set_node_predecessor(x, y);
1222 assert(
state == query_state_initialized);
1224 for(
unsigned i =
source_node.size()-1; i!=(unsigned)-1; --i){
1230 relax_outgoing_arcs(
1231 cch->up_first_out, cch->up_head, metric->forward,
1232 forward_tentative_distance, [&](unsigned a, unsigned b){forward_predecessor_node[a] = b;},
1250 for(
unsigned i = target_node.size()-1; i!=(unsigned)-1; --i){
1253 target_node[i], target_elimination_tree_end[i],
1255 relax_outgoing_arcs(
1256 cch->up_first_out, cch->up_head, metric->backward,
1257 backward_tentative_distance, [&](unsigned a, unsigned b){backward_predecessor_node[a] = b;},
1260 if(in_forward_search_space[x]){
1262 if(l < shortest_path_length){
1263 shortest_path_length = l;
1264 shortest_path_meeting_node = x;
1277 state = query_state_run;
1281unsigned CustomizableContractionHierarchyQuery::get_distance(){
1282 assert(state == query_state_run);
1289unsigned CustomizableContractionHierarchyQuery::get_used_source(){
1290 assert(state == query_state_run);
1291 if(shortest_path_meeting_node ==
invalid_id) {
1294 unsigned x = shortest_path_meeting_node;
1295 while(forward_predecessor_node[x] !=
invalid_id){
1296 x = forward_predecessor_node[x];
1298 return cch->order[x];
1302unsigned CustomizableContractionHierarchyQuery::get_used_target(){
1303 assert(state == query_state_run);
1304 if(shortest_path_meeting_node ==
invalid_id) {
1307 unsigned x = shortest_path_meeting_node;
1308 while(backward_predecessor_node[x] !=
invalid_id){
1309 x = backward_predecessor_node[x];
1311 return cch->order[x];
1316 struct TriangleUnpacker{
1317 TriangleUnpacker(){}
1318 TriangleUnpacker(
unsigned&bottom_node,
unsigned&bottom_arc,
unsigned&mid_arc):
1321 unsigned bottom_arc,
unsigned mid_arc,
unsigned top_arc,
1322 unsigned bottom_node,
unsigned mid_node,
unsigned top_node
1325 if((*
forward)[top_arc] == (*backward)[bottom_arc] + (*forward)[mid_arc]){
1342 template<
class OnNewSegment>
1344 const CustomizableContractionHierarchy&
cch,
const CustomizableContractionHierarchyMetric&
metric,
1346 unsigned x,
unsigned y,
unsigned xy,
1347 const OnNewSegment&on_new_segment
1349 assert(x ==
cch.up_tail[xy]);
1350 assert(y ==
cch.up_head[xy]);
1357 auto unpacker = [&](
1359 unsigned bottom_node_,
unsigned mid_node_,
unsigned top_node_
1361 (void)top_node_; (void)mid_node_;
1377 forall_lower_triangles_of_arc(
cch, x, y, xy, unpacker);
1378 if(bottom_node == invalid_id){
1380 on_new_segment(x, xy,
true);
1382 on_new_segment(y, xy,
false);
1385 unpack_arc(
cch,
metric,
false, bottom_node, x, bottom_arc, on_new_segment);
1386 unpack_arc(
cch,
metric,
true, bottom_node, y, mid_arc, on_new_segment);
1388 unpack_arc(
cch,
metric,
false, bottom_node, y, mid_arc, on_new_segment);
1389 unpack_arc(
cch,
metric,
true, bottom_node, x, bottom_arc, on_new_segment);
1394 template<
class OnNewSegment>
1395 unsigned unpack_shortest_path(
1396 const CustomizableContractionHierarchy&
cch,
const CustomizableContractionHierarchyMetric&
metric,
const CustomizableContractionHierarchyQuery&query,
1397 const OnNewSegment&on_new_segment
1399 if(query.shortest_path_meeting_node == invalid_id)
1403 std::vector<unsigned>up_path = {query.shortest_path_meeting_node};
1405 unsigned x = query.shortest_path_meeting_node;
1406 while(query.forward_predecessor_node[x] != invalid_id){
1407 x = query.forward_predecessor_node[x];
1408 up_path.push_back(x);
1411 for(
unsigned i=up_path.size()-1; i!=0; --i){
1421 unsigned x = query.shortest_path_meeting_node;
1422 unsigned y = query.backward_predecessor_node[x];
1423 while(y != invalid_id){
1431 y = query.backward_predecessor_node[y];
1438std::vector<unsigned>CustomizableContractionHierarchyQuery::get_node_path(){
1439 assert(state == query_state_run);
1440 std::vector<unsigned>path;
1441 unsigned last = unpack_shortest_path(
1443 [&](
unsigned cch_node,
unsigned cch_arc,
bool forward){
1444 path.push_back(
cch->order[cch_node]);
1450 path.push_back(
cch->order[last]);
1458 unsigned unpack_original_forward_arc(
1462 if(
cch.does_cch_arc_have_input_arc.is_set(cch_arc)){
1463 unsigned i =
cch.does_cch_arc_have_input_arc_mapper.to_local(cch_arc);
1464 if(
cch.forward_input_arc_of_cch[i] != invalid_id){
1465 unsigned original_arc =
cch.forward_input_arc_of_cch[i];
1466 if(
metric.forward[cch_arc] ==
metric.input_weight[original_arc])
1467 return original_arc;
1469 if(
cch.does_cch_arc_have_extra_input_arc.is_set(cch_arc)){
1470 unsigned j =
cch.does_cch_arc_have_extra_input_arc_mapper.to_local(cch_arc);
1471 for(
unsigned k =
cch.first_extra_forward_input_arc_of_cch[j]; k <
cch.first_extra_forward_input_arc_of_cch[j+1]; ++k){
1472 unsigned original_arc =
cch.extra_forward_input_arc_of_cch[k];
1473 if(
metric.forward[cch_arc] ==
metric.input_weight[original_arc])
1474 return original_arc;
1482 unsigned unpack_original_backward_arc(
1483 const CustomizableContractionHierarchy&
cch,
const CustomizableContractionHierarchyMetric&
metric,
1486 if(
cch.does_cch_arc_have_input_arc.is_set(cch_arc)){
1487 unsigned i =
cch.does_cch_arc_have_input_arc_mapper.to_local(cch_arc);
1488 if(
cch.backward_input_arc_of_cch[i] != invalid_id){
1489 unsigned original_arc =
cch.backward_input_arc_of_cch[i];
1490 if(
metric.backward[cch_arc] ==
metric.input_weight[original_arc])
1491 return original_arc;
1492 if(
cch.does_cch_arc_have_extra_input_arc.is_set(cch_arc)){
1493 unsigned j =
cch.does_cch_arc_have_extra_input_arc_mapper.to_local(cch_arc);
1494 for(
unsigned k =
cch.first_extra_backward_input_arc_of_cch[j]; k <
cch.first_extra_backward_input_arc_of_cch[j+1]; ++k){
1495 unsigned original_arc =
cch.extra_backward_input_arc_of_cch[k];
1496 if(
metric.backward[cch_arc] ==
metric.input_weight[original_arc])
1497 return original_arc;
1506 unsigned unpack_original_arc(
1507 const CustomizableContractionHierarchy&
cch,
const CustomizableContractionHierarchyMetric&
metric,
1508 unsigned cch_arc,
bool is_forward
1511 return unpack_original_forward_arc(
cch,
metric, cch_arc);
1513 return unpack_original_backward_arc(
cch,
metric, cch_arc);
1517std::vector<unsigned>CustomizableContractionHierarchyQuery::get_arc_path(){
1518 assert(state == query_state_run);
1519 std::vector<unsigned>path;
1520 unpack_shortest_path(
1522 [&](
unsigned cch_node,
unsigned cch_arc,
bool is_forward){
1525 assert(cch_node ==
cch->up_tail[cch_arc]);
1527 assert(cch_node ==
cch->up_head[cch_arc]);
1531 unsigned arc = unpack_original_arc(*
cch, *
metric, cch_arc, is_forward);
1533 path.push_back(arc);
1540 void internal_pin_targets(
1541 std::vector<unsigned>&target_node,
1542 std::vector<unsigned>&target_elimination_tree_end,
1543 std::vector<bool>&in_backward_search_space,
1544 const std::vector<unsigned>&elimination_tree_parent,
1545 const std::vector<unsigned>&rank,
1546 const std::vector<unsigned>&target_list
1548 target_node.resize(target_list.size());
1549 target_elimination_tree_end.resize(target_list.size());
1551 for(
unsigned i=0; i<target_list.size(); ++i){
1552 target_node[i] = rank[target_list[i]];
1555 elimination_tree_parent, target_node[i],
1557 if(!in_backward_search_space[x]){
1558 in_backward_search_space[x] =
true;
1561 target_elimination_tree_end[i] = x;
1571 assert(state == query_state_initialized);
1572 internal_pin_targets(target_node, target_elimination_tree_end, in_backward_search_space,
cch->elimination_tree_parent,
cch->rank, target_list);
1573 state = query_state_target_pinned;
1578 assert(state == query_state_initialized);
1579 internal_pin_targets(source_node, source_elimination_tree_end, in_forward_search_space,
cch->elimination_tree_parent,
cch->rank, source_list);
1580 state = query_state_source_pinned;
1585 void reset_target_distances(
1586 const std::vector<unsigned>&elimination_tree_parent,
1587 const std::vector<unsigned>&target_node,
1588 const std::vector<unsigned>&target_elimination_tree_end,
1591 for(
unsigned i = target_node.size()-1; i!=(unsigned)-1; --i){
1593 elimination_tree_parent,
1594 target_node[i], target_elimination_tree_end[i],
1605 assert(state == query_state_target_pinned || state == query_state_target_run);
1607 reset_source_list(
cch->elimination_tree_parent, source_node, source_elimination_tree_end, in_forward_search_space,
forward_tentative_distance);
1610 state = query_state_target_pinned;
1615 assert(state == query_state_source_pinned || state == query_state_source_run);
1617 reset_source_list(
cch->elimination_tree_parent, target_node, target_elimination_tree_end, in_backward_search_space,
backward_tentative_distance);
1620 state = query_state_source_pinned;
1625 void internal_run_to_pinned_targets(
1627 const std::vector<unsigned>&forward_weight,
const std::vector<unsigned>&backward_weight,
1629 const std::vector<unsigned>&source_node,
const std::vector<unsigned>&source_elimination_tree_end,
1630 const std::vector<unsigned>&target_node,
const std::vector<unsigned>&target_elimination_tree_end
1632 for(
unsigned i = source_node.size()-1; i!=(unsigned)-1; --i){
1634 cch.elimination_tree_parent,
1635 source_node[i], source_elimination_tree_end[i],
1637 relax_outgoing_arcs(
1638 cch.up_first_out, cch.up_head, forward_weight,
1639 forward_tentative_distance, [](unsigned,unsigned){},
1648 unsigned stack_end = 0;
1649 for(
unsigned i = target_node.size()-1; i!=(unsigned)-1; --i){
1651 cch.elimination_tree_parent,
1652 target_node[i], target_elimination_tree_end[i],
1654 stack[stack_end++] = x;
1660 while(stack_end != 0){
1662 unsigned x = stack[stack_end];
1664 relax_incoming_arcs(
1665 cch.up_first_out,
cch.up_head, backward_weight,
1674 assert(state == query_state_target_pinned);
1675 internal_run_to_pinned_targets(
1679 source_node, source_elimination_tree_end,
1680 target_node, target_elimination_tree_end
1682 state = query_state_target_run;
1687 assert(state == query_state_source_pinned);
1688 internal_run_to_pinned_targets(
1692 target_node, target_elimination_tree_end,
1693 source_node, source_elimination_tree_end
1695 state = query_state_source_run;
1700 assert(state == query_state_target_run);
1701 for(
unsigned i=0; i<target_node.size(); ++i)
1706std::vector<unsigned> CustomizableContractionHierarchyQuery::get_distances_to_targets(){
1707 assert(state == query_state_target_run);
1708 std::vector<unsigned>v(target_node.size());
1709 get_distances_to_targets(&v[0]);
1714 assert(state == query_state_source_run);
1715 for(
unsigned i=0; i<source_node.size(); ++i)
1720std::vector<unsigned> CustomizableContractionHierarchyQuery::get_distances_to_sources(){
1721 assert(state == query_state_source_run);
1722 std::vector<unsigned>v(source_node.size());
1723 get_distances_to_sources(&v[0]);
1727ContractionHierarchy CustomizableContractionHierarchyMetric::build_contraction_hierarchy_using_perfect_witness_search(){
1731 keep_forward_arc(
cch->cch_arc_count(),
true),
1732 keep_backward_arc(
cch->cch_arc_count(),
true);
1734 for(
unsigned a=0; a<
cch->cch_arc_count(); ++a)
1736 keep_forward_arc.reset(a);
1738 for(
unsigned a=0; a<
cch->cch_arc_count(); ++a)
1740 keep_backward_arc.
reset(a);
1742 for(
unsigned a=
cch->cch_arc_count()-1; a!=(unsigned)-1; --a){
1743 forall_upper_triangles_of_arc(
1746 unsigned bottom_arc,
unsigned mid_arc,
unsigned top_arc,
1747 unsigned bottom_node,
unsigned mid_node,
unsigned top_node
1751 keep_forward_arc.reset(bottom_arc);
1756 keep_backward_arc.
reset(bottom_arc);
1761 keep_forward_arc.reset(mid_arc);
1766 keep_backward_arc.
reset(mid_arc);
1774 for(
unsigned a=0; a<
cch->cch_arc_count(); ++a)
1775 forall_upper_triangles_of_arc(
1778 unsigned bottom_arc,
unsigned mid_arc,
unsigned top_arc,
1779 unsigned bottom_node,
unsigned mid_node,
unsigned top_node
1821 for(
unsigned cch_arc=0; cch_arc<
cch->cch_arc_count(); ++cch_arc){
1822 if(keep_forward_arc.is_set(cch_arc)){
1823 unsigned forward_ch_arc = forward_map.
to_local(cch_arc);
1824 unsigned forward_original_arc = unpack_original_forward_arc(*
cch, *
this, cch_arc);
1830 bool was_forward_not_found = forall_lower_triangles_of_arc(
1833 unsigned bottom_arc,
unsigned mid_arc,
unsigned top_arc,
1834 unsigned bottom_node,
unsigned mid_node,
unsigned top_node
1840 if(keep_backward_arc.
is_set(bottom_arc) && keep_forward_arc.is_set(mid_arc)){
1850 (void) was_forward_not_found;
1851 assert(!was_forward_not_found);
1854 if(keep_backward_arc.
is_set(cch_arc)){
1855 unsigned backward_ch_arc = backward_map.
to_local(cch_arc);
1856 unsigned backward_original_arc = unpack_original_backward_arc(*
cch, *
this, cch_arc);
1862 bool was_backward_not_found = forall_lower_triangles_of_arc(
1865 unsigned bottom_arc,
unsigned mid_arc,
unsigned top_arc,
1866 unsigned bottom_node,
unsigned mid_node,
unsigned top_node
1872 if(keep_backward_arc.
is_set(mid_arc) && keep_forward_arc.is_set(bottom_arc)){
1882 (void) was_backward_not_found;
1883 assert(!was_backward_not_found);
1895 if(state == query_state_target_pinned || state == query_state_target_run){
1897 }
else if(state == query_state_source_pinned || state == query_state_source_run){
1900 reset_source_list(
cch->elimination_tree_parent, source_node, source_elimination_tree_end, in_forward_search_space,
forward_tentative_distance);
1901 reset_source_list(
cch->elimination_tree_parent, target_node, target_elimination_tree_end, in_backward_search_space,
backward_tentative_distance);
1902 state = query_state_initialized;
1907 if(this->cch ==
metric.cch) {
1913 state = query_state_initialized;
static constexpr Uninitialized uninitialized
void resize(uint64_t size, Uninitialized)
bool is_set(uint64_t x) const
std::vector< unsigned > order
std::vector< unsigned > rank
unsigned id_count() const
bool empty() const
Checks whether the queue contains any element.
void clear()
Removes all elements from the queue.
uint64_t local_id_count() const
uint64_t to_local(uint64_t global_id) const
std::vector< unsigned > tail
std::vector< unsigned > forward_tentative_distance
std::vector< unsigned > backward_tentative_distance
const std::vector< unsigned > * backward
CustomizableContractionHierarchyMetric * metric
const CustomizableContractionHierarchy * cch
const std::vector< unsigned > * forward
std::vector< unsigned > compute_stable_sort_permutation_using_key(const std::vector< T > &v, unsigned key_count, const K &get_key)
void check_contraction_hierarchy_for_errors(const ContractionHierarchy &ch)
unsigned find_arc_given_sorted_head(const std::vector< unsigned > &first_out, const std::vector< unsigned > &head, unsigned x, unsigned y)
void inplace_keep_element_of_vector_if(const BitVector &keep_filter, std::vector< T > &vec)
std::vector< unsigned > compute_sort_permutation_first_by_tail_then_by_head_and_apply_sort_to_tail(unsigned node_count, std::vector< unsigned > &tail, const std::vector< unsigned > &head)
std::vector< T > apply_permutation(const std::vector< unsigned > &p, const std::vector< T > &v)
std::vector< T > apply_inverse_permutation(const std::vector< unsigned > &p, const std::vector< T > &v)
long long get_micro_time()
void min_to(T &x, const T &y)
std::vector< T > keep_element_of_vector_if(const BitVector &keep_filter, std::vector< T >vec)
std::vector< unsigned > invert_vector(const std::vector< unsigned > &v, unsigned element_count)
void max_to(T &x, const T &y)
std::vector< unsigned > invert_permutation(const std::vector< unsigned > &p)
std::vector< unsigned > compute_inverse_sort_permutation_first_by_tail_then_by_head_and_apply_sort_to_tail(unsigned node_count, std::vector< unsigned > &tail, const std::vector< unsigned > &head)
std::vector< unsigned > compute_inverse_stable_sort_permutation_using_key(const std::vector< T > &v, unsigned key_count, const K &get_key)
std::vector< unsigned > apply_permutation_to_elements_of(const std::vector< unsigned > &p, const std::vector< unsigned > &v)
const unsigned invalid_id
const unsigned inf_weight
NLOHMANN_BASIC_JSON_TPL_DECLARATION void swap(nlohmann::NLOHMANN_BASIC_JSON_TPL &j1, nlohmann::NLOHMANN_BASIC_JSON_TPL &j2) noexcept(//NOLINT(readability-inconsistent-declaration-parameter-name) is_nothrow_move_constructible< nlohmann::NLOHMANN_BASIC_JSON_TPL >::value &&//NOLINT(misc-redundant-expression) is_nothrow_move_assignable< nlohmann::NLOHMANN_BASIC_JSON_TPL >::value)
exchanges the values of two JSON objects
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
std::vector< unsigned > down_head
BitVector is_input_arc_upward
std::vector< unsigned > first_extra_forward_input_arc_of_cch
std::vector< unsigned > extra_forward_input_arc_of_cch
BitVector does_cch_arc_have_extra_input_arc
std::vector< unsigned > up_first_out
std::vector< unsigned > extra_backward_input_arc_of_cch
std::vector< unsigned > up_head
CustomizableContractionHierarchy()
std::vector< unsigned > backward_input_arc_of_cch
unsigned cch_arc_count() const
BitVector does_cch_arc_have_input_arc
std::vector< unsigned > down_first_out
std::vector< unsigned > elimination_tree_parent
LocalIDMapper does_cch_arc_have_extra_input_arc_mapper
unsigned node_count() const
std::vector< unsigned > down_to_up
std::vector< unsigned > input_arc_to_cch_arc
LocalIDMapper does_cch_arc_have_input_arc_mapper
unsigned input_arc_count() const
std::vector< unsigned > order
std::vector< unsigned > up_tail
std::vector< unsigned > first_extra_backward_input_arc_of_cch
std::vector< unsigned > forward_input_arc_of_cch
std::vector< unsigned > rank
CustomizableContractionHierarchyMetric()
CustomizableContractionHierarchyMetric & customize()
const unsigned * input_weight
std::vector< unsigned > forward
const CustomizableContractionHierarchy * cch
std::vector< unsigned > backward
CustomizableContractionHierarchyMetric & reset(const CustomizableContractionHierarchy &cch, const unsigned *input_weight)
std::vector< unsigned > first_arc_of_level
CustomizableContractionHierarchyParallelization()
std::vector< unsigned > arcs_ordered_by_level
const CustomizableContractionHierarchy * cch
CustomizableContractionHierarchyParallelization & customize(CustomizableContractionHierarchyMetric &metric)
CustomizableContractionHierarchyPartialCustomization & customize(CustomizableContractionHierarchyMetric &metric)
CustomizableContractionHierarchyPartialCustomization()
const CustomizableContractionHierarchy * cch
CustomizableContractionHierarchyPartialCustomization & update_arc(unsigned xy)
CustomizableContractionHierarchyPartialCustomization & reset()
std::vector< unsigned > source_node
std::vector< unsigned > forward_tentative_distance
std::vector< bool > in_forward_search_space
CustomizableContractionHierarchyQuery & run()
std::vector< unsigned > backward_predecessor_node
std::vector< unsigned > forward_predecessor_node
std::vector< unsigned > source_elimination_tree_end
std::vector< unsigned > target_node
std::vector< bool > in_backward_search_space
std::vector< unsigned > target_elimination_tree_end
CustomizableContractionHierarchyQuery()
CustomizableContractionHierarchyQuery & add_source(unsigned s, unsigned dist_to_s=0)
CustomizableContractionHierarchyQuery & add_target(unsigned t, unsigned dist_to_t=0)
std::vector< unsigned > backward_tentative_distance
const CustomizableContractionHierarchy * cch