Eclipse SUMO - Simulation of Urban MObility
Loading...
Searching...
No Matches
nested_dissection.cpp
Go to the documentation of this file.
6#include <routingkit/filter.h>
9#include <routingkit/timer.h>
10
11#include <assert.h>
12
13namespace RoutingKit{
14
16 #ifndef NDEBUG
17// unsigned node_count = fragment.node_count();
18// unsigned arc_count = fragment.arc_count();
19
20// assert(fragment.tail.size() == arc_count);
21// assert(fragment.head.size() == arc_count);
22// assert(fragment.back_arc.size() == arc_count);
23// assert(fragment.global_node_id.size() == node_count);
24
25// if(arc_count != 0){
26// assert(max_element_of(fragment.tail) < node_count);
27// assert(max_element_of(fragment.head) < node_count);
28// }
29
30// assert(invert_inverse_vector(fragment.first_out) == fragment.tail);
31
32// for(unsigned a=0; a<arc_count; ++a){
33// assert(fragment.back_arc[a] < arc_count);
34// assert(fragment.back_arc[fragment.back_arc[a]] == a);
35// assert(fragment.tail[a] == fragment.head[fragment.back_arc[a]]);
36// assert(fragment.head[a] == fragment.tail[fragment.back_arc[a]]);
37// }
38 #endif
39}
40
41GraphFragment make_graph_fragment(unsigned node_count, const std::vector<unsigned>&tail, const std::vector<unsigned>&head){
42 unsigned arc_count = head.size();
43
44 GraphFragment fragment;
45
46 unsigned non_loop_arc_count = 0;
47 for(unsigned i=0; i<arc_count; ++i)
48 if(tail[i] != head[i])
49 ++non_loop_arc_count;
50
51 fragment.tail.resize(2*non_loop_arc_count);
52 fragment.head.resize(2*non_loop_arc_count);
53 fragment.back_arc.resize(2*non_loop_arc_count);
54
55 {
56 unsigned j = 0;
57 for(unsigned i=0; i<arc_count; ++i){
58 if(tail[i] != head[i]){
59 fragment.tail[j] = tail[i];
60 fragment.tail[j+non_loop_arc_count] = head[i];
61 fragment.head[j] = head[i];
62 fragment.head[j+non_loop_arc_count] = tail[i];
63 fragment.back_arc[j] = j+non_loop_arc_count;
64 fragment.back_arc[j+non_loop_arc_count] = j;
65 ++j;
66 }
67 }
68 }
69
70 {
72 fragment.head = apply_inverse_permutation(p, fragment.head);
73 fragment.back_arc = apply_inverse_permutation(p, fragment.back_arc);
75 fragment.first_out = invert_vector(fragment.tail, node_count);
76 }
77
79
81
82 return fragment;
83}
84
86 const GraphFragment&fragment, BitVector is_source_, BitVector is_target_
87):
88 fragment(&fragment), is_source(std::move(is_source_)), is_target(std::move(is_target_)),
89
90 flow_intensity(0),
91 is_arc_saturated(fragment.arc_count(), false),
92 is_arc_blocked(fragment.arc_count(), BitVector::uninitialized),
93 is_finished_flag(false)
94{
95 #ifndef NDEBUG
97 assert(is_source.size() == fragment.node_count());
98 assert(is_target.size() == fragment.node_count());
99 assert(is_source.population_count() > 0);
100 assert(is_target.population_count() > 0);
101 for(unsigned x=0; x<fragment.node_count(); ++x)
102 assert((!is_target.is_set(x) || !is_source.is_set(x)) && "a source node can not also be a target node");
103 #endif
104}
105
106namespace{
107 bool compute_blocking_flow(const GraphFragment&fragment, const BitVector&is_source, const BitVector&is_target, const BitVector&is_arc_saturated, BitVector&is_arc_blocked){
108 BitVector is_on_same_level_or_lower(fragment.node_count(), false);
109 BitVector was_node_pushed(fragment.node_count(), false);
110
111 is_arc_blocked.reset_all();
112
113 std::vector<unsigned>queue(fragment.node_count());
114 unsigned queue_begin = 0;
115 unsigned queue_end = 0;
116
117 for(unsigned x=0; x<fragment.node_count(); ++x)
118 if(is_source.is_set(x))
119 queue[queue_end++] = x;
120 unsigned queue_current_level_end = queue_end;
121
122 bool is_a_target_node_reachable = false;
123
124 while(queue_begin != queue_end){
125
126 for(unsigned i=queue_begin; i<queue_current_level_end; ++i){
127 is_on_same_level_or_lower.set(queue[i]);
128 }
129
130 for(unsigned i=queue_begin; i<queue_current_level_end; ++i){
131 unsigned x = queue[i];
132 for(unsigned xy=fragment.first_out[x]; xy<fragment.first_out[x+1]; ++xy){
133 if(is_arc_saturated.is_set(xy)){
134 is_arc_blocked.set(xy);
135 } else {
136 unsigned y = fragment.head[xy];
137 if(is_on_same_level_or_lower.is_set(y)){
138 is_arc_blocked.set(xy);
139 } else {
140 if(is_target.is_set(y)){
141 is_a_target_node_reachable = true;
142 } else {
143 if(!was_node_pushed.is_set(y)){
144 queue[queue_end++] = y;
145 was_node_pushed.set(y);
146 }
147 }
148 }
149 }
150 }
151 }
152
153 queue_begin = queue_current_level_end;
154 queue_current_level_end = queue_end;
155 }
156 return is_a_target_node_reachable;
157 }
158
159 unsigned augment_all_non_blocked_path(const GraphFragment&fragment, const BitVector&is_source, const BitVector&is_target, BitVector&is_arc_saturated, BitVector&is_arc_blocked){
160 std::vector<unsigned>current_path_node(fragment.node_count());
161 std::vector<unsigned>current_path_arc(fragment.node_count());
162
163 auto find_first_non_block_outgoing_arc_of_node = [&](unsigned x){
164 for(unsigned xy=fragment.first_out[x]; xy<fragment.first_out[x+1]; ++xy)
165 if(!is_arc_blocked.is_set(xy))
166 return xy;
167 return invalid_id;
168 };
169
170 unsigned augmented_path_count = 0;
171
172 for(unsigned s=0; s<fragment.node_count(); ++s){
173 if(is_source.is_set(s)){
174 current_path_node[0] = s;
175 current_path_arc[0] = s;
176 unsigned current_path_arc_count = 0;
177 for(;;){
178 unsigned x = current_path_node[current_path_arc_count];
179 unsigned xy = find_first_non_block_outgoing_arc_of_node(x);
180 if(xy == invalid_id){
181 if(current_path_arc_count == 0)
182 break;
183 --current_path_arc_count;
184 is_arc_blocked.set(current_path_arc[current_path_arc_count]);
185 } else {
186 auto y = fragment.head[xy];
187 current_path_arc[current_path_arc_count] = xy;
188 ++current_path_arc_count;
189 current_path_node[current_path_arc_count] = y;
190 if(is_target.is_set(y)){
191 for(unsigned i=0; i<current_path_arc_count; ++i){
192 unsigned a = current_path_arc[i];
193 assert(!is_arc_saturated.is_set(a));
194 is_arc_blocked.set(a);
195
196 unsigned b = fragment.back_arc[a];
197 if(is_arc_saturated.is_set(b))
198 is_arc_saturated.reset(b);
199 else
200 is_arc_saturated.set(a);
201 }
202 current_path_arc_count = 0;
203 ++augmented_path_count;
204 }
205 }
206 }
207 }
208 }
209 return augmented_path_count;
210 }
211}
212
213
215 assert(is_finished_flag);
216
217 CutSide side;
218
219 side.is_node_on_side.resize(fragment->node_count(), false);
221 side.node_on_side_count = 0;
222
223 unsigned stack_end = 0;
224 std::vector<unsigned>stack(fragment->node_count());
225 for(unsigned s=0; s<fragment->node_count(); ++s)
226 if(is_source.is_set(s)){
227 stack[stack_end++] = s;
228 side.is_node_on_side.set(s);
229 ++side.node_on_side_count;
230 }
231
232 while(stack_end != 0){
233 unsigned x = stack[--stack_end];
234 for(unsigned xy=fragment->first_out[x]; xy<fragment->first_out[x+1]; ++xy){
235 if(!is_arc_saturated.is_set(xy)){
236 unsigned y = fragment->head[xy];
237 if(!side.is_node_on_side.is_set(y)){
238 stack[stack_end++] = y;
239 side.is_node_on_side.set(y);
240 ++side.node_on_side_count;
241 }
242 }
243 }
244 }
245
246 return side; // NVRO
247}
248
250 assert(is_finished_flag);
251
252 CutSide side;
253
254 side.is_node_on_side.resize(fragment->node_count(), false);
256 side.node_on_side_count = 0;
257
258 unsigned stack_end = 0;
259 std::vector<unsigned>stack(fragment->node_count());
260 for(unsigned t=0; t<fragment->node_count(); ++t)
261 if(is_target.is_set(t)){
262 stack[stack_end++] = t;
263 side.is_node_on_side.set(t);
264 ++side.node_on_side_count;
265 }
266
267
268 while(stack_end != 0){
269 unsigned x = stack[--stack_end];
270 for(unsigned xy=fragment->first_out[x]; xy<fragment->first_out[x+1]; ++xy){
272 unsigned y = fragment->head[xy];
273 if(!side.is_node_on_side.is_set(y)){
274 stack[stack_end++] = y;
275 side.is_node_on_side.set(y);
276 ++side.node_on_side_count;
277 }
278 }
279 }
280 }
281
282 return side; // NVRO
283}
284
286 assert(is_finished_flag);
287
288 unsigned node_count = fragment->node_count();
289 unsigned arc_count = fragment->arc_count();
290
291
292 BitVector is_source_reachable = is_source;
293 BitVector is_target_reachable = is_target;
294
295 unsigned source_reachable_count = 0;
296 unsigned target_reachable_count = 0;
297
298 std::vector<unsigned>stack(node_count);
299 unsigned stack_end = 0;
300
301 std::vector<unsigned>potential_source_piercing_node(arc_count); // arc_count is no typo, nodes may be multiple times in the vector
302 unsigned potential_source_piercing_node_end = 0;
303
304 std::vector<unsigned>potential_target_piercing_node(arc_count);
305 unsigned potential_target_piercing_node_end = 0;
306
307 auto enlarge_source_side = [&]{
308 while(stack_end != 0){
309 ++source_reachable_count;
310 unsigned x = stack[--stack_end];
311 for(unsigned xy = fragment->first_out[x]; xy < fragment->first_out[x+1]; ++xy){
312 unsigned y = fragment->head[xy];
313 if(is_arc_saturated.is_set(xy)){
314 potential_source_piercing_node[potential_source_piercing_node_end++] = y;
315 } else {
316 if(!is_source_reachable.is_set(y)){
317 is_source_reachable.set(y);
318 stack[stack_end++] = y;
319 }
320 }
321
322 }
323 }
324 assert(source_reachable_count == is_source_reachable.population_count());
325 };
326
327 auto enlarge_target_side = [&]{
328 while(stack_end != 0){
329 ++target_reachable_count;
330 unsigned x = stack[--stack_end];
331 for(unsigned xy = fragment->first_out[x]; xy < fragment->first_out[x+1]; ++xy){
332 unsigned y = fragment->head[xy];
334 potential_target_piercing_node[potential_target_piercing_node_end++] = y;
335 } else {
336 if(!is_target_reachable.is_set(y)){
337 stack[stack_end++] = y;
338 is_target_reachable.set(y);
339 }
340 }
341
342 }
343 }
344 assert(target_reachable_count == is_target_reachable.population_count());
345 };
346
347 auto add_source_nodes_to_stack = [&]{
348 for(unsigned x=0; x<node_count; ++x)
349 if(is_source.is_set(x))
350 stack[stack_end++] = x;
351 };
352
353 auto add_target_nodes_to_stack = [&]{
354 for(unsigned x=0; x<node_count; ++x)
355 if(is_target.is_set(x))
356 stack[stack_end++] = x;
357 };
358
359 add_source_nodes_to_stack();
360 enlarge_source_side();
361
362 add_target_nodes_to_stack();
363 enlarge_target_side();
364
365 CutSide side;
366
367 for(;;){
368 if(source_reachable_count <= target_reachable_count){
369 unsigned pierce_node = invalid_id;
370 while(pierce_node == invalid_id){
371 if(potential_source_piercing_node_end == 0){
372 side.is_node_on_side = std::move(is_source_reachable);
374 side.node_on_side_count = source_reachable_count;
375 return side; // NVRO
376 } else {
377 unsigned y = potential_source_piercing_node[--potential_source_piercing_node_end];
378 if(!is_source_reachable.is_set(y) && !is_target_reachable.is_set(y))
379 pierce_node = y;
380 }
381 }
382 is_source_reachable.set(pierce_node);
383 stack[stack_end++] = pierce_node;
384 enlarge_source_side();
385 }else{
386 unsigned pierce_node = invalid_id;
387 while(pierce_node == invalid_id){
388 if(potential_target_piercing_node_end == 0){
389 side.is_node_on_side = std::move(is_target_reachable);
391 side.node_on_side_count = target_reachable_count;
392 return side; // NVRO
393 } else {
394 unsigned y = potential_target_piercing_node[--potential_target_piercing_node_end];
395 if(!is_source_reachable.is_set(y) && !is_target_reachable.is_set(y))
396 pierce_node = y;
397 }
398 }
399 is_target_reachable.set(pierce_node);
400 stack[stack_end++] = pierce_node;
401 enlarge_target_side();
402 }
403 }
404
405 return side; // NVRO
406}
407
410 flow_intensity += augment_all_non_blocked_path(*fragment, is_source, is_target, is_arc_saturated, is_arc_blocked);
411 is_finished_flag = false;
412 }else{
413 is_finished_flag = true;
414 }
415}
416
417
418
419namespace{
420 template<class GetKey>
421 BitVector mark_first_n_elements(unsigned n, unsigned total_element_count, const GetKey&sort_key){
422 auto v = identity_permutation(total_element_count);
423 auto
424 begin = v.begin(),
425 mid = v.begin() + n,
426 end = v.end();
427
428 std::nth_element(begin, mid, end, [&](unsigned l, unsigned r){return sort_key(l) < sort_key(r);});
429
430 BitVector r(total_element_count, false);
431 while(begin != mid){
432 r.set(*begin);
433 ++begin;
434 }
435 return r;
436 }
437
438 struct SourceTargetResult{
440 };
441
442 template<class GetKey>
443 SourceTargetResult select_source_and_target(unsigned n, unsigned node_count, const GetKey&sort_key){
444 assert(n <= node_count/2);
446 auto
447 begin = v.begin(),
448 source_end = v.begin() + n,
449 target_begin = v.begin() + node_count - n,
450 end = v.end();
451
452 std::nth_element(begin, source_end, end, [&](unsigned l, unsigned r){return sort_key(l) < sort_key(r);});
453 std::nth_element(source_end, target_begin, end, [&](unsigned l, unsigned r){return sort_key(l) < sort_key(r);});
454
455 SourceTargetResult ret;
456 ret.is_source.resize(node_count);
457 ret.is_source.reset_all();
458
459 while(begin != source_end){
460 ret.is_source.set(*begin);
461 ++begin;
462 }
463
464 ret.is_target.resize(node_count);
465 ret.is_target.reset_all();
466
467 while(target_begin != end){
468 ret.is_target.set(*target_begin);
469 ++target_begin;
470 }
471
472 return ret; // NVRO
473 }
474}
475
483
485 const GraphFragment&g,
486 unsigned min_balance,
487 const std::vector<float>&latitude, const std::vector<float>&longitude,
488 const std::function<void(const std::string&)>&log_message
489){
491
492 long long last_report = 0;
493 long long start_time = 0;
494 bool first_report = true;
495
496 if(log_message){
497 start_time = get_micro_time();
498 last_report = start_time;
499 }
500
501 const unsigned node_count = g.node_count();
502
503 unsigned side_size = (node_count*min_balance)/100;
504 if(side_size == 0)
505 side_size = 1;
506
507 auto horizontal_source_target = select_source_and_target(side_size, node_count, [&](unsigned x){return latitude[g.global_node_id[x]];});
508 BlockingFlow horizontal_cutter(
509 g,
510 std::move(horizontal_source_target.is_source),
511 std::move(horizontal_source_target.is_target)
512 );
513
514 auto vertical_source_target = select_source_and_target(side_size, node_count, [&](unsigned x){return longitude[g.global_node_id[x]];});
515 BlockingFlow vertical_cutter(
516 g,
517 std::move(vertical_source_target.is_source),
518 std::move(vertical_source_target.is_target)
519 );
520
521 auto main_diagonal_source_target = select_source_and_target(side_size, node_count, [&](unsigned x){return latitude[g.global_node_id[x]]+longitude[g.global_node_id[x]];});
522 BlockingFlow main_diagonal_cutter(
523 g,
524 std::move(main_diagonal_source_target.is_source),
525 std::move(main_diagonal_source_target.is_target)
526 );
527
528 auto next_diagonal_source_target = select_source_and_target(side_size, node_count, [&](unsigned x){return latitude[g.global_node_id[x]]-longitude[g.global_node_id[x]];});
529 BlockingFlow next_diagonal_cutter(
530 g,
531 std::move(next_diagonal_source_target.is_source),
532 std::move(next_diagonal_source_target.is_target)
533 );
534
535
536 auto get_next_cutter = [&]()->BlockingFlow&{
537 if(
538 horizontal_cutter.get_current_flow_intensity() <= vertical_cutter.get_current_flow_intensity() &&
539 horizontal_cutter.get_current_flow_intensity() <= main_diagonal_cutter.get_current_flow_intensity() &&
540 horizontal_cutter.get_current_flow_intensity() <= next_diagonal_cutter.get_current_flow_intensity()
541 ){
542 return horizontal_cutter;
543 }else if(
544 vertical_cutter.get_current_flow_intensity() <= main_diagonal_cutter.get_current_flow_intensity() &&
545 vertical_cutter.get_current_flow_intensity() <= next_diagonal_cutter.get_current_flow_intensity()
546 ){
547 return vertical_cutter;
548 }else if(
549 main_diagonal_cutter.get_current_flow_intensity() <= next_diagonal_cutter.get_current_flow_intensity()
550 ){
551 return main_diagonal_cutter;
552 }else{
553 return next_diagonal_cutter;
554 }
555 };
556
557 for(;;){
558 auto&c = get_next_cutter();
559 if(!c.is_finished()){
560
561 if(log_message){
562 long long now = get_micro_time();
563 if(now - last_report > 1000000){
564 if(first_report){
565 first_report = false;
566 log_message("Start running Inertial Flow with imbalance "+std::to_string(min_balance)+"% on graph with "+std::to_string(g.node_count()) +" nodes and "+std::to_string(g.arc_count())+" arcs.");
567 }
568 last_report = now;
569 log_message("Smallest cutter has reached a cut of "+std::to_string(c.get_current_flow_intensity())+" arcs.");
570 }
571 }
572
573 c.advance();
574 }else{
575 auto cut = c.get_balanced_cut();
576 if(log_message){
577 if(!first_report){
578 log_message("Inertial Flow is finished and needed "+std::to_string(get_micro_time()-start_time)+"musec. The cut has "+std::to_string(cut.cut_size)+" arcs and the smaller side has "+std::to_string(cut.node_on_side_count)+" nodes.");
579 }
580 }
581 return cut; // NRVO
582 }
583 }
584}
585
587 const GraphFragment&g,
588 const std::vector<float>&latitude, const std::vector<float>&longitude,
589 const std::function<void(const std::string&)>&log_message
590){
592
593 auto c25 = inertial_flow(g, 25, latitude, longitude, log_message);
594 auto c33 = inertial_flow(g, 33, latitude, longitude, log_message);
595 auto c40 = inertial_flow(g, 40, latitude, longitude, log_message);
596
597 if(
598 static_cast<unsigned long long>(c25.cut_size) * static_cast<unsigned long long>(c33.node_on_side_count) < static_cast<unsigned long long>(c33.cut_size) * static_cast<unsigned long long>(c25.node_on_side_count) &&
599 static_cast<unsigned long long>(c25.cut_size) * static_cast<unsigned long long>(c40.node_on_side_count) < static_cast<unsigned long long>(c40.cut_size) * static_cast<unsigned long long>(c25.node_on_side_count)
600 )
601 return c25; // NVRO
602 else if(
603 static_cast<unsigned long long>(c33.cut_size) * static_cast<unsigned long long>(c40.node_on_side_count) < static_cast<unsigned long long>(c40.cut_size) * static_cast<unsigned long long>(c33.node_on_side_count)
604 )
605 return c33; // NVRO
606 else
607 return c40; // NVRO
608
609}
610
611
613 assert_fragment_is_valid(fragment);
614
615 unsigned node_count = fragment.node_count();
616 unsigned arc_count = fragment.arc_count();
617
618 unsigned component_count = 0;
619 std::vector<unsigned>component(node_count, invalid_id);
620 {
621 std::vector<unsigned>inv_pseudo_preorder(node_count);
622 {
623 std::vector<unsigned>stack(node_count);
624 unsigned pos = 0;
625 for(unsigned r=0; r<node_count; ++r){
626 if(component[r] == invalid_id){
627 component[r] = component_count;
628 unsigned stack_end = 1;
629 stack[0] = r;
630 while(stack_end != 0){
631 unsigned x = stack[--stack_end];
632 inv_pseudo_preorder[x] = pos++;
633 for(unsigned xy=fragment.first_out[x]; xy<fragment.first_out[x+1]; ++xy){
634 unsigned y=fragment.head[xy];
635 if(component[y] == invalid_id){
636 stack[stack_end++] = y;
637 component[y] = component_count;
638 }
639 }
640 }
641 ++component_count;
642 }
643 }
644 }
645
646 inplace_apply_permutation_to_elements_of(inv_pseudo_preorder, fragment.tail);
647 inplace_apply_permutation_to_elements_of(inv_pseudo_preorder, fragment.head);
648 fragment.global_node_id = apply_inverse_permutation(inv_pseudo_preorder, fragment.global_node_id);
649 component = apply_inverse_permutation(inv_pseudo_preorder, component);
650 }
651
652 {
654 fragment.head = apply_inverse_permutation(p, fragment.head);
655 fragment.back_arc = apply_inverse_permutation(p, fragment.back_arc);
657 fragment.first_out = invert_vector(fragment.tail, node_count);
658 }
659
660 assert_fragment_is_valid(fragment);
661
662 std::vector<GraphFragment>part_list;
663
664 auto generate_part = [&](unsigned component_node_begin, unsigned component_node_end, unsigned component_arc_begin, unsigned component_arc_end){
665 GraphFragment part;
666
667 unsigned part_node_count = component_node_end - component_node_begin;
668 unsigned part_arc_count = component_arc_end - component_arc_begin;
669 (void)part_node_count; (void)part_arc_count;
670
671
672 part.tail = std::vector<unsigned>(fragment.tail.begin()+component_arc_begin, fragment.tail.begin()+component_arc_end);
673 for(auto&x:part.tail)
674 x -= component_node_begin;
675
676 if(part_arc_count != 0)
677 assert(max_element_of(part.tail) < part_node_count);
678
679 part.head = std::vector<unsigned>(fragment.head.begin()+component_arc_begin, fragment.head.begin()+component_arc_end);
680 for(auto&x:part.head)
681 x -= component_node_begin;
682
683 if(part_arc_count != 0)
684 assert(max_element_of(part.head) < part_node_count);
685
686 part.back_arc = std::vector<unsigned>(fragment.back_arc.begin()+component_arc_begin, fragment.back_arc.begin()+component_arc_end);
687 for(auto&x:part.back_arc)
688 x -= component_arc_begin;
689
690 if(part_arc_count != 0)
691 assert(max_element_of(part.back_arc) < part_arc_count);
692
693 part.global_node_id = std::vector<unsigned>(fragment.global_node_id.begin()+component_node_begin, fragment.global_node_id.begin()+component_node_end);
694
695 part.first_out = invert_vector(part.tail, part_node_count);
696
698
699 part_list.push_back(std::move(part));
700 };
701
702 unsigned component_node_begin = 0;
703 unsigned component_arc_begin = 0;
704 unsigned component_node_end = 1;
705 unsigned component_arc_end = 0;
706
707 unsigned current_component = 0;
708 while(component_node_end<node_count){
709 if(component[component_node_end] != current_component){
710 while(component_arc_end != arc_count && component[fragment.tail[component_arc_end]] == current_component){
711 assert(component[fragment.tail[component_arc_end]] == component[fragment.head[component_arc_end]]);
712 ++component_arc_end;
713 }
714 generate_part(component_node_begin, component_node_end, component_arc_begin, component_arc_end);
715 component_node_begin = component_node_end;
716 component_arc_begin = component_arc_end;
717 current_component = component[component_node_end];
718 }
719 ++component_node_end;
720 }
721 generate_part(component_node_begin, component_node_end, component_arc_begin, arc_count);
722
723 return part_list; // NVRO
724}
725
727 assert_fragment_is_valid(fragment);
728
729 bool small_side = cut.population_count() <= fragment.node_count()/2;
730 BitVector is_separator_node(fragment.node_count(), false);
731
732 for(unsigned xy=0; xy<fragment.arc_count(); ++xy){
733 unsigned x = fragment.tail[xy], y = fragment.head[xy];
734 if(cut.is_set(x) == small_side && cut.is_set(y) != small_side)
735 is_separator_node.set(y);
736 }
737 return is_separator_node; // NVRO
738}
739
741 GraphFragment fragment, const std::function<BitVector(const GraphFragment&)>&compute_separator,
742 const std::function<void(const std::string&)>&log_message
743){
744 assert_fragment_is_valid(fragment);
745
746 long long timer = 0;
747
749 decomp.order.resize(fragment.node_count());
750
751 if(fragment.node_count() == 1){
752 decomp.tree.push_back({0, 0, 0, 1});
753 decomp.order = std::move(fragment.global_node_id);
754 }else{
755
756 unsigned pred = 0;
757 unsigned order_begin = 0, order_end = fragment.node_count();
758
759 decomp.tree.push_back({0, 0, 0, order_end});
760
761 if(log_message){
762 timer = -get_micro_time();
763 log_message("Start decomposing top-level graph");
764 }
765 auto part_list = decompose_graph_fragment_into_connected_components(std::move(fragment));
766 fragment = GraphFragment(); // release memory
767 if(log_message){
768 timer += get_micro_time();
769 log_message("Finished decomposing top-level graph, needed "+std::to_string(timer)+"musec and found "+std::to_string(part_list.size())+" connected components");
770 }
771
772 for(auto&part:part_list){
773 assert(part.node_count() != 0);
774 if(part.node_count() == 1){
775 decomp.order[--order_end] = part.global_node_id[0];
776 }else{
777 if(log_message && part.node_count() > 1000){
778 log_message("Computing decomposition for top level component with "+std::to_string(part.node_count())+" nodes");
779 timer = -get_micro_time();
780 log_message("Start computing top level separator");
781 }
782 auto is_separator_node = compute_separator(part);
783 if(log_message && part.node_count() > 1000){
784 timer += get_micro_time();
785 log_message("Finished computing top level separator, its size is "+std::to_string(is_separator_node.population_count())+" nodes needed "+std::to_string(timer)+"musec");
786 }
787
789 part.arc_count(),
790 [&](unsigned a){
791 return !is_separator_node.is_set(part.tail[a]) && !is_separator_node.is_set(part.head[a]);
792 }
793 );
794
797 inplace_keep_element_of_vector_if(f, part.back_arc);
798
799 {
800 LocalIDMapper map(f);
801 for(auto&x:part.back_arc)
802 x = map.to_local(x);
803 }
804
805 part.first_out = invert_vector(part.tail, part.node_count());
806
808
809
810 const unsigned part_node_count = part.node_count(); // Capture before move
811 if(log_message && part_node_count > 1000){
812 timer = -get_micro_time();
813 log_message("Start computing remaining separator decomposition using recursion");
814 }
815 auto sub_decomp = compute_separator_decomposition(std::move(part), compute_separator);
816 if(log_message && part_node_count > 1000){
817 timer += get_micro_time();
818 log_message("Finished recursion, needed "+std::to_string(timer)+"musec");
819 }
820
821 for(auto&node:sub_decomp.tree){
822 if(node.left_child != 0)
823 node.left_child += decomp.tree.size();
824 if(node.right_sibling != 0)
825 node.right_sibling += decomp.tree.size();
826 node.first_separator_vertex += order_begin;
827 node.last_separator_vertex += order_begin;
828 }
829 if(pred == 0)
830 decomp.tree[pred].left_child = decomp.tree.size();
831 else
832 decomp.tree[pred].right_sibling = decomp.tree.size();
833 pred = decomp.tree.size();
834 decomp.tree.insert(decomp.tree.end(), sub_decomp.tree.begin(), sub_decomp.tree.end());
835 std::copy(sub_decomp.order.begin(), sub_decomp.order.end(), decomp.order.begin() + order_begin);
836 order_begin += sub_decomp.order.size();
837 }
838 }
839 decomp.tree[0].first_separator_vertex = order_begin;
840 }
841
842 return decomp; // NVRO
843}
844
846 GraphFragment fragment, const std::function<BitVector(const GraphFragment&)>&compute_separator,
847 const std::function<void(const std::string&)>&log_message
848){
849 return compute_separator_decomposition(std::move(fragment), compute_separator, log_message).order;
850}
851
853 unsigned node_count, const std::vector<unsigned>&tail, const std::vector<unsigned>&head,
854 const std::vector<float>&latitude, const std::vector<float>&longitude,
855 const std::function<void(const std::string&)>&log_message
856){
857 long long timer = 0;
858
859 if(log_message){
860 timer = -get_micro_time();
861 log_message("Start making graph fragment");
862 }
863 auto g = make_graph_fragment(node_count, tail, head);
864 if(log_message){
865 timer += get_micro_time();
866 log_message("Finished making graph fragment, needed "+std::to_string(timer)+"musec");
867 }
868
869 auto compute_cut = [&](const GraphFragment&fragment)->BitVector{
870 auto c = inertial_flow(fragment, latitude, longitude, log_message);
872 return std::move(c.is_node_on_side);
873 };
874
875 auto compute_separator = [&](const GraphFragment&fragment)->BitVector{
876 return derive_separator_from_cut(fragment, compute_cut(fragment));
877 };
878
879 return compute_nested_node_dissection_order(std::move(g), compute_separator, log_message);
880}
881
882} // RoutingKit
883
void set(uint64_t x)
Definition bit_vector.h:42
uint64_t size() const
Definition bit_vector.h:26
void resize(uint64_t size, Uninitialized)
uint64_t population_count() const
bool is_set(uint64_t x) const
Definition bit_vector.h:34
const GraphFragment * fragment
uint64_t to_local(uint64_t global_id) const
Definition id_mapper.cpp:86
unsigned node
std::vector< unsigned > tail
unsigned node_count
void assert_fragment_is_valid(const GraphFragment &fragment)
void inplace_apply_permutation_to_elements_of(const std::vector< unsigned > &p, std::vector< unsigned > &v)
Definition permutation.h:96
void inplace_keep_element_of_vector_if(const BitVector &keep_filter, std::vector< T > &vec)
Definition filter.h:13
std::vector< GraphFragment > decompose_graph_fragment_into_connected_components(GraphFragment fragment)
std::vector< T > apply_inverse_permutation(const std::vector< unsigned > &p, const std::vector< T > &v)
Definition permutation.h:72
long long get_micro_time()
Definition timer.cpp:14
const T & max_element_of(const std::vector< T > &v)
Definition min_max.h:56
BitVector derive_separator_from_cut(const GraphFragment &fragment, const BitVector &cut)
std::vector< unsigned > invert_vector(const std::vector< unsigned > &v, unsigned element_count)
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_nested_node_dissection_order(GraphFragment fragment, const std::function< BitVector(const GraphFragment &)> &compute_separator, const std::function< void(const std::string &)> &log_message=[](const std::string &){})
BitVector make_bit_vector(uint64_t size, const F &f)
Definition bit_vector.h:123
std::vector< unsigned > compute_nested_node_dissection_order_using_inertial_flow(unsigned node_count, const std::vector< unsigned > &tail, const std::vector< unsigned > &head, const std::vector< float > &latitude, const std::vector< float > &longitude, const std::function< void(const std::string &)> &log_message=[](const std::string &){})
SeparatorDecomposition compute_separator_decomposition(GraphFragment fragment, const std::function< BitVector(const GraphFragment &)> &compute_separator, const std::function< void(const std::string &)> &log_message=[](const std::string &){})
void pick_smaller_side(CutSide &cut)
std::vector< unsigned > identity_permutation(unsigned n)
GraphFragment make_graph_fragment(unsigned node_count, const std::vector< unsigned > &tail, const std::vector< unsigned > &head)
CutSide inertial_flow(const GraphFragment &fragment, unsigned min_balance, const std::vector< float > &latitude, const std::vector< float > &longitude, const std::function< void(const std::string &)> &log_message=[](const std::string &){})
Definition json.hpp:4471
BitVector is_source
BitVector is_target
std::vector< unsigned > tail
std::vector< unsigned > head
std::vector< unsigned > first_out
std::vector< unsigned > back_arc
std::vector< unsigned > global_node_id