42 unsigned arc_count = head.size();
46 unsigned non_loop_arc_count = 0;
47 for(
unsigned i=0; i<arc_count; ++i)
48 if(
tail[i] != head[i])
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);
57 for(
unsigned i=0; i<arc_count; ++i){
58 if(
tail[i] != head[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;
91 is_arc_saturated(fragment.arc_count(), false),
92 is_arc_blocked(fragment.arc_count(),
BitVector::uninitialized),
93 is_finished_flag(false)
113 std::vector<unsigned>queue(fragment.
node_count());
114 unsigned queue_begin = 0;
115 unsigned queue_end = 0;
117 for(
unsigned x=0; x<fragment.
node_count(); ++x)
119 queue[queue_end++] = x;
120 unsigned queue_current_level_end = queue_end;
122 bool is_a_target_node_reachable =
false;
124 while(queue_begin != queue_end){
126 for(
unsigned i=queue_begin; i<queue_current_level_end; ++i){
127 is_on_same_level_or_lower.set(queue[i]);
130 for(
unsigned i=queue_begin; i<queue_current_level_end; ++i){
131 unsigned x = queue[i];
133 if(is_arc_saturated.
is_set(xy)){
134 is_arc_blocked.
set(xy);
136 unsigned y = fragment.
head[xy];
137 if(is_on_same_level_or_lower.is_set(y)){
138 is_arc_blocked.
set(xy);
141 is_a_target_node_reachable =
true;
143 if(!was_node_pushed.is_set(y)){
144 queue[queue_end++] = y;
145 was_node_pushed.set(y);
153 queue_begin = queue_current_level_end;
154 queue_current_level_end = queue_end;
156 return is_a_target_node_reachable;
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());
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))
170 unsigned augmented_path_count = 0;
172 for(
unsigned s=0; s<fragment.node_count(); ++s){
174 current_path_node[0] = s;
175 current_path_arc[0] = s;
176 unsigned current_path_arc_count = 0;
178 unsigned x = current_path_node[current_path_arc_count];
179 unsigned xy = find_first_non_block_outgoing_arc_of_node(x);
181 if(current_path_arc_count == 0)
183 --current_path_arc_count;
184 is_arc_blocked.set(current_path_arc[current_path_arc_count]);
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;
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);
196 unsigned b = fragment.back_arc[a];
197 if(is_arc_saturated.is_set(b))
198 is_arc_saturated.reset(b);
200 is_arc_saturated.set(a);
202 current_path_arc_count = 0;
203 ++augmented_path_count;
209 return augmented_path_count;
223 unsigned stack_end = 0;
227 stack[stack_end++] = s;
232 while(stack_end != 0){
233 unsigned x = stack[--stack_end];
238 stack[stack_end++] = y;
258 unsigned stack_end = 0;
262 stack[stack_end++] = t;
268 while(stack_end != 0){
269 unsigned x = stack[--stack_end];
274 stack[stack_end++] = y;
295 unsigned source_reachable_count = 0;
296 unsigned target_reachable_count = 0;
299 unsigned stack_end = 0;
301 std::vector<unsigned>potential_source_piercing_node(arc_count);
302 unsigned potential_source_piercing_node_end = 0;
304 std::vector<unsigned>potential_target_piercing_node(arc_count);
305 unsigned potential_target_piercing_node_end = 0;
307 auto enlarge_source_side = [&]{
308 while(stack_end != 0){
309 ++source_reachable_count;
310 unsigned x = stack[--stack_end];
314 potential_source_piercing_node[potential_source_piercing_node_end++] = y;
316 if(!is_source_reachable.
is_set(y)){
317 is_source_reachable.
set(y);
318 stack[stack_end++] = y;
327 auto enlarge_target_side = [&]{
328 while(stack_end != 0){
329 ++target_reachable_count;
330 unsigned x = stack[--stack_end];
334 potential_target_piercing_node[potential_target_piercing_node_end++] = y;
336 if(!is_target_reachable.
is_set(y)){
337 stack[stack_end++] = y;
338 is_target_reachable.
set(y);
347 auto add_source_nodes_to_stack = [&]{
350 stack[stack_end++] = x;
353 auto add_target_nodes_to_stack = [&]{
356 stack[stack_end++] = x;
359 add_source_nodes_to_stack();
360 enlarge_source_side();
362 add_target_nodes_to_stack();
363 enlarge_target_side();
368 if(source_reachable_count <= target_reachable_count){
371 if(potential_source_piercing_node_end == 0){
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))
382 is_source_reachable.
set(pierce_node);
383 stack[stack_end++] = pierce_node;
384 enlarge_source_side();
388 if(potential_target_piercing_node_end == 0){
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))
399 is_target_reachable.
set(pierce_node);
400 stack[stack_end++] = pierce_node;
401 enlarge_target_side();
420 template<
class GetKey>
421 BitVector mark_first_n_elements(
unsigned n,
unsigned total_element_count,
const GetKey&sort_key){
428 std::nth_element(begin, mid, end, [&](
unsigned l,
unsigned r){
return sort_key(l) < sort_key(r);});
430 BitVector r(total_element_count,
false);
438 struct SourceTargetResult{
442 template<
class GetKey>
443 SourceTargetResult select_source_and_target(
unsigned n,
unsigned node_count,
const GetKey&sort_key){
448 source_end = v.begin() + n,
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);});
455 SourceTargetResult ret;
457 ret.is_source.reset_all();
459 while(begin != source_end){
460 ret.is_source.set(*begin);
465 ret.is_target.reset_all();
467 while(target_begin != end){
468 ret.is_target.set(*target_begin);
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
492 long long last_report = 0;
493 long long start_time = 0;
494 bool first_report =
true;
498 last_report = start_time;
503 unsigned side_size = (
node_count*min_balance)/100;
507 auto horizontal_source_target = select_source_and_target(side_size,
node_count, [&](
unsigned x){
return latitude[g.
global_node_id[x]];});
510 std::move(horizontal_source_target.is_source),
511 std::move(horizontal_source_target.is_target)
514 auto vertical_source_target = select_source_and_target(side_size,
node_count, [&](
unsigned x){
return longitude[g.
global_node_id[x]];});
517 std::move(vertical_source_target.is_source),
518 std::move(vertical_source_target.is_target)
524 std::move(main_diagonal_source_target.is_source),
525 std::move(main_diagonal_source_target.is_target)
531 std::move(next_diagonal_source_target.is_source),
532 std::move(next_diagonal_source_target.is_target)
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()
542 return horizontal_cutter;
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()
547 return vertical_cutter;
549 main_diagonal_cutter.get_current_flow_intensity() <= next_diagonal_cutter.get_current_flow_intensity()
551 return main_diagonal_cutter;
553 return next_diagonal_cutter;
558 auto&c = get_next_cutter();
559 if(!c.is_finished()){
563 if(now - last_report > 1000000){
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.");
569 log_message(
"Smallest cutter has reached a cut of "+std::to_string(c.get_current_flow_intensity())+
" arcs.");
575 auto cut = c.get_balanced_cut();
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.");
588 const std::vector<float>&latitude,
const std::vector<float>&longitude,
589 const std::function<
void(
const std::string&)>&log_message
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);
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)
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)
616 unsigned arc_count = fragment.
arc_count();
618 unsigned component_count = 0;
621 std::vector<unsigned>inv_pseudo_preorder(
node_count);
627 component[r] = component_count;
628 unsigned stack_end = 1;
630 while(stack_end != 0){
631 unsigned x = stack[--stack_end];
632 inv_pseudo_preorder[x] = pos++;
634 unsigned y=fragment.
head[xy];
636 stack[stack_end++] = y;
637 component[y] = component_count;
662 std::vector<GraphFragment>part_list;
664 auto generate_part = [&](
unsigned component_node_begin,
unsigned component_node_end,
unsigned component_arc_begin,
unsigned component_arc_end){
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;
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;
676 if(part_arc_count != 0)
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;
683 if(part_arc_count != 0)
686 part.
back_arc = std::vector<unsigned>(fragment.
back_arc.begin()+component_arc_begin, fragment.
back_arc.begin()+component_arc_end);
688 x -= component_arc_begin;
690 if(part_arc_count != 0)
699 part_list.push_back(std::move(part));
702 unsigned component_node_begin = 0;
703 unsigned component_arc_begin = 0;
704 unsigned component_node_end = 1;
705 unsigned component_arc_end = 0;
707 unsigned current_component = 0;
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]]);
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];
719 ++component_node_end;
721 generate_part(component_node_begin, component_node_end, component_arc_begin, arc_count);
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);
737 return is_separator_node;
742 const std::function<
void(
const std::string&)>&log_message
752 decomp.
tree.push_back({0, 0, 0, 1});
757 unsigned order_begin = 0, order_end = fragment.
node_count();
759 decomp.
tree.push_back({0, 0, 0, order_end});
763 log_message(
"Start decomposing top-level graph");
769 log_message(
"Finished decomposing top-level graph, needed "+std::to_string(timer)+
"musec and found "+std::to_string(part_list.size())+
" connected components");
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];
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");
780 log_message(
"Start computing top level separator");
782 auto is_separator_node = compute_separator(part);
783 if(log_message && part.node_count() > 1000){
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");
791 return !is_separator_node.is_set(part.tail[a]) && !is_separator_node.is_set(part.head[a]);
801 for(
auto&x:part.back_arc)
805 part.first_out =
invert_vector(part.tail, part.node_count());
810 const unsigned part_node_count = part.node_count();
811 if(log_message && part_node_count > 1000){
813 log_message(
"Start computing remaining separator decomposition using recursion");
816 if(log_message && part_node_count > 1000){
818 log_message(
"Finished recursion, needed "+std::to_string(timer)+
"musec");
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;
830 decomp.
tree[pred].left_child = decomp.
tree.size();
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();
839 decomp.
tree[0].first_separator_vertex = order_begin;
847 const std::function<
void(
const std::string&)>&log_message
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
861 log_message(
"Start making graph fragment");
866 log_message(
"Finished making graph fragment, needed "+std::to_string(timer)+
"musec");
870 auto c =
inertial_flow(fragment, latitude, longitude, log_message);
872 return std::move(c.is_node_on_side);
void resize(uint64_t size, Uninitialized)
uint64_t population_count() const
bool is_set(uint64_t x) const
CutSide get_balanced_cut()
const GraphFragment * fragment
BitVector is_arc_saturated
uint64_t to_local(uint64_t global_id) const
std::vector< unsigned > tail
void assert_fragment_is_valid(const GraphFragment &fragment)
void inplace_apply_permutation_to_elements_of(const std::vector< unsigned > &p, std::vector< unsigned > &v)
void inplace_keep_element_of_vector_if(const BitVector &keep_filter, std::vector< T > &vec)
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)
long long get_micro_time()
const T & max_element_of(const std::vector< T > &v)
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)
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)
const unsigned invalid_id
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 &){})
unsigned node_on_side_count
BitVector is_node_on_side
std::vector< unsigned > tail
std::vector< unsigned > head
std::vector< unsigned > first_out
std::vector< unsigned > back_arc
unsigned arc_count() const
unsigned node_count() const
std::vector< unsigned > global_node_id
std::vector< unsigned > order