5#ifndef DEJAVU_REFINEMENT_H
6#define DEJAVU_REFINEMENT_H
26 static bool bijection_check(
markset& scratch_set,
int n,
const int *p) {
29 for(
int i = 0; i < n && comp; ++i) {
31 comp = !scratch_set.
get(v);
37 static bool cycle_check(
markset& scratch_set,
const int *p,
int supp,
const int *supp_arr) {
40 for(
int i = 0; i < supp && comp; ++i) {
41 const int v = supp_arr[i];
42 if(scratch_set.
get(v))
continue;
44 while(v_next != v && comp) {
45 comp = !scratch_set.
get(v_next);
46 scratch_set.
set(v_next);
56 if(!bijection_check(scratch_set, g->
v_size, p))
return false;
58 for (
int i = 0; i < g->
v_size; ++i) {
59 const int image_i = p[i];
60 if (image_i == i)
continue;
65 const int start_pt = g->
v[i];
66 const int end_pt = g->
v[i] + g->
d[i];
67 for (
int j = start_pt; j < end_pt; ++j) {
68 const int vertex_j = g->
e[j];
69 const int image_j = p[vertex_j];
70 scratch_set.
set(image_j);
73 const int image_start_pt = g->
v[image_i];
74 const int image_end_pt = g->
v[image_i] + g->
d[image_i];
75 for (
int j = image_start_pt; j < image_end_pt; ++j) {
76 const int vertex_j = g->
e[j];
77 if (!scratch_set.
get(vertex_j))
return false;
78 scratch_set.
unset(vertex_j);
81 if (found != 0)
return false;
89 const int *supp_arr) {
91 if(!cycle_check(scratch_set, p, supp, supp_arr))
return false;
93 for (
int f = 0; f < supp; ++f) {
95 const int image_i = p[i];
99 const int start_pt = g->
v[i];
100 const int end_pt = g->
v[i] + g->
d[i];
101 for (
int j = start_pt; j < end_pt; ++j) {
102 const int vertex_j = g->
e[j];
103 const int image_j = p[vertex_j];
104 scratch_set.
set(image_j);
107 const int image_start_pt = g->
v[image_i];
108 const int image_end_pt = g->
v[image_i] + g->
d[image_i];
109 for (
int j = image_start_pt; j < image_end_pt; ++j) {
110 const int vertex_j = g->
e[j];
111 if (!scratch_set.
get(vertex_j)) {
144 bool g_early_out =
false;
145 const std::function<type_split_color_hook>* g_split_hook;
162 const std::function<type_split_color_hook>* split_hook =
nullptr,
163 const std::function<type_worklist_color_hook>* worklist_hook =
nullptr) {
164 assure_initialized(g);
165 cell_todo.reset(queue_pointer);
167 if (init_color < 0) {
170 cell_todo.add_cell(queue_pointer, i);
171 const int col_sz = c->
ptn[i];
176 cell_todo.add_cell(queue_pointer, init_color);
180 g_split_hook = split_hook;
182 while (!cell_todo.empty()) {
183 const int next_color_class = cell_todo.next_cell(queue_pointer, c);
184 const int next_color_class_sz = c->
ptn[next_color_class] + 1;
186 if (worklist_hook && !(*worklist_hook)(next_color_class, next_color_class_sz))
continue;
190 const int test_deg = g->
d[c->
lab[next_color_class]];
191 const bool very_dense = test_deg > (g->
v_size / (next_color_class_sz + 1));
194 if (next_color_class_sz == 1 && !(g->
dense && very_dense)) {
195 refine_color_class_singleton(g, c, next_color_class);
196 }
else if (g->
dense) {
198 refine_color_class_dense_dense(g, c, next_color_class,next_color_class_sz);
203 refine_color_class_dense(g, c, next_color_class, next_color_class_sz);
206 refine_color_class_sparse(g, c, next_color_class, next_color_class_sz);
211 cell_todo.reset(queue_pointer);
217 void report_split_color_class(
coloring* c,
const int old_class,
const int new_class,
const int new_class_sz,
218 const bool is_largest) {
219 c->
cells += (old_class != new_class);
222 if ((g_split_hook !=
nullptr) && !(*g_split_hook)(old_class, new_class, new_class_sz)) {
226 if (!is_largest && old_class != new_class) {
227 cell_todo.add_cell(queue_pointer, new_class);
228 }
else if(is_largest) {
230 int i = queue_pointer.
get(old_class);
231 if (i >= 0) cell_todo.replace_cell(queue_pointer, old_class, new_class);
232 if(old_class != new_class) cell_todo.add_cell(queue_pointer, old_class);
249 int color_class_size = c->
ptn[color];
253 const int vertex_at_pos = c->
lab[color + color_class_size];
254 c->
lab[pos] = vertex_at_pos;
257 c->
lab[color + color_class_size] = v;
262 c->
ptn[color + color_class_size] = 0;
263 c->
ptn[color + color_class_size - 1] = 0;
267 split_hook(color, color + color_class_size, 1);
268 split_hook(color, color, c->
ptn[color] + 1);
271 return color + color_class_size;
285 assure_initialized(g);
286 singleton_hint.
reset();
288 cell_todo.reset(queue_pointer);
290 if (init_color_class < 0) {
292 cell_todo.add_cell(queue_pointer, i);
293 const int col_sz = c->
ptn[i];
300 cell_todo.add_cell(queue_pointer, init_color_class);
303 while (!cell_todo.empty()) {
304 const int next_color_class = cell_todo.next_cell(queue_pointer, c, singleton_hint);
305 const int next_color_class_sz = c->
ptn[next_color_class] + 1;
306 const bool very_dense = (g->
d[c->
lab[next_color_class]] > (g->
v_size / (next_color_class_sz + 1)));
308 if (next_color_class_sz == 1 && !(g->
dense && very_dense)) {
310 refine_color_class_singleton_first(g, c, next_color_class);
311 }
else if (g->
dense) {
313 refine_color_class_dense_dense_first(g, c, next_color_class, next_color_class_sz);
315 refine_color_class_dense_first(g, c, next_color_class, next_color_class_sz);
318 refine_color_class_sparse_first(g, c, next_color_class, next_color_class_sz);
322 cell_todo.reset(queue_pointer);
329 void report_split_color_class_first(
coloring* c,
int old_class,
int new_class,
int new_class_sz,
331 c->
cells += (old_class != new_class);
334 if (!is_largest && old_class != new_class) {
335 cell_todo.add_cell(queue_pointer, new_class);
336 if (new_class_sz == 1) singleton_hint.
push_back(new_class);
337 }
else if(is_largest) {
339 int i = queue_pointer.
get(old_class);
341 cell_todo.replace_cell(queue_pointer, old_class, new_class);
342 if(new_class_sz == 1) singleton_hint.
push_back(new_class);
344 if(old_class != new_class) {
345 cell_todo.add_cell(queue_pointer, old_class);
346 if(c->
ptn[old_class] + 1 == 1) singleton_hint.
push_back(old_class);
363 assure_initialized(g);
380 assure_initialized(g);
386 class cell_worklist {
388 void initialize(
int _domain_size) {
389 arr =
new int[_domain_size];
390 arr_sz = _domain_size;
401 dej_assert(cur_pos >= 0 && cur_pos < arr_sz - 1);
402 _queue_pointer.set(col, cur_pos);
408 int next_cell(
work_set_int& _queue_pointer, coloring *c) {
410 int sm_j = cur_pos - 1;
411 for (
int j = cur_pos - 1; j >= 0 && ((cur_pos - j) <= 12); --j) {
412 if (c->ptn[arr[j]] < c->ptn[arr[sm_j]]) {
414 if (c->ptn[arr[sm_j]] == 0)
420 const int sm_col = arr[sm_j];
421 arr[sm_j] = arr[cur_pos - 1];
422 _queue_pointer.set(arr[sm_j], sm_j);
425 _queue_pointer.set(sm_col, -1);
429 int next_cell(
work_set_int& _queue_pointer, coloring *c, worklist_t<int>& _singleton_hint) {
432 while (!_singleton_hint.empty() && sm_j == -1) {
433 const int next_hint = _singleton_hint.pop_back();
434 sm_j = _queue_pointer.get(next_hint);
440 for (
int j = cur_pos - 1; j >= 0 && ((cur_pos - j) <= 12); --j) {
441 const int size_sm_j = c->ptn[arr[sm_j]];
442 const bool smaller = (c->ptn[arr[j]] < size_sm_j);
443 sm_j = smaller ? j : sm_j;
444 if (size_sm_j - smaller <= 0)
break;
449 const int sm_col = arr[sm_j];
450 arr[sm_j] = arr[cur_pos - 1];
451 _queue_pointer.set(arr[sm_j], sm_j);
454 _queue_pointer.set(sm_col, -1);
458 void replace_cell(
work_set_int& _queue_pointer,
int col_old,
int col) {
459 const int pos = _queue_pointer.get(col_old);
461 dej_assert(_queue_pointer.get(col_old) != -1);
462 _queue_pointer.set(col_old, -1);
463 _queue_pointer.set(col, pos);
467 while (cur_pos > 0) {
469 _queue_pointer.set(arr[cur_pos], -1);
474 return (cur_pos == 0);
488 int domain_size = -1;
492 cell_worklist cell_todo;
493 worklist_t<int> singleton_hint;
497 worklist_t<int> vertex_worklist;
498 workset_t<int> color_vertices_considered;
499 workset_t<int> neighbours;
500 workset_t<int> neighbour_sizes;
501 worklist_t<int> old_color_classes;
504 void assure_initialized(
const sgraph *g) {
505 if (g->v_size > domain_size) {
506 const int n = g->v_size;
508 vertex_worklist.allocate(n * 2);
509 singleton_hint.allocate(n);
510 old_color_classes.allocate(n);
512 neighbour_sizes.initialize(n);
513 queue_pointer.initialize(n);
514 color_vertices_considered.initialize(n);
516 scratch_set.initialize(n);
517 cell_todo.initialize(n * 2);
522 void refine_color_class_sparse(sgraph *g, coloring *c,
int color_class,
525 int i, j, cc, end_cc, largest_color_class_size, acc;
526 int *vertex_to_lab = c->vertex_to_lab;
529 int *vertex_to_col = c->vertex_to_col;
533 old_color_classes.reset();
535 color_vertices_considered.reset();
537 end_cc = color_class + class_size;
538 while (cc < end_cc) {
539 const int vc = lab[cc];
540 const int pe = g->v[vc];
541 const int end_i = pe + g->d[vc];
542 for (i = pe; i < end_i; i++) {
543 const int v = g->e[i];
544 const int col = vertex_to_col[v];
548 neighbours.inc_nr(v);
549 if (neighbours.get(v) == 0) {
550 color_vertices_considered.inc_nr(col);
551 dej_assert(col + color_vertices_considered.get(col) < g->v_size);
552 scratch[col + color_vertices_considered.get(col)] = v;
553 if (color_vertices_considered.get(col) == 0) {
554 old_color_classes.push_back(col);
562 for(j = 0; j < old_color_classes.size(); ++j) {
563 const int _col = old_color_classes[j];
564 const int _col_sz = ptn[_col] + 1;
565 const int vcount = color_vertices_considered.get(_col) + 1;
567 if(vcount == _col_sz) {
568 const int v_first = scratch[_col];
569 const int index_first = neighbours.get(v_first) + 1;
572 for (i = 1; i < vcount; ++i) {
573 const int v = scratch[_col + i];
574 const int index = neighbours.get(v) + 1;
575 splits = index != index_first;
583 const int v = scratch[_col + i];
584 neighbours.set(v, -1);
588 color_vertices_considered.set(_col, -1);
590 old_color_classes[j] = old_color_classes[old_color_classes.size() - 1];
591 old_color_classes.pop_back();
597 old_color_classes.sort();
600 while (!old_color_classes.empty()) {
601 const int _col = old_color_classes.pop_back();
602 const int _col_sz = ptn[_col] + 1;
603 const int vcount = color_vertices_considered.get(_col) + 1;
604 neighbour_sizes.reset();
605 vertex_worklist.reset();
607 for (i = 0; i < vcount; ++i) {
608 const int v = scratch[_col + i];
609 const int index = neighbours.get(v) + 1;
610 if (neighbour_sizes.inc(index) == 0) vertex_worklist.push_back(index);
613 if(vcount == _col_sz && vertex_worklist.cur_pos == 1) {
614 vertex_worklist.reset();
617 const int v = scratch[_col + j];
618 neighbours.set(v, -1);
621 color_vertices_considered.set(_col, -1);
625 vertex_worklist.sort();
629 while (!vertex_worklist.empty()) {
630 const int k = vertex_worklist.pop_back();
631 const int val = neighbour_sizes.get(k) + 1;
633 neighbour_sizes.set(k, val + acc);
635 const int _ncol = _col + _col_sz - (neighbour_sizes.get(k));
642 vertex_worklist.reset();
644 color_vertices_considered.set(_col, -1);
648 const int v = scratch[_col + j];
650 if ((neighbours.get(v) == -1))
652 const int v_new_color = _col + _col_sz - neighbour_sizes.get(neighbours.get(v) + 1);
653 neighbours.set(v, -1);
654 if (v_new_color == _col)
657 const int lab_pt = v_new_color + ptn[v_new_color] + 1;
658 ptn[v_new_color] += 1;
659 ptn[_col] -= (_col != v_new_color);
661 const int vertex_old_pos = vertex_to_lab[v];
662 const int vertex_at_pos = lab[lab_pt];
663 lab[vertex_old_pos] = vertex_at_pos;
664 vertex_to_lab[vertex_at_pos] = vertex_old_pos;
666 vertex_to_col[v] = v_new_color;
667 vertex_to_lab[v] = lab_pt;
671 largest_color_class_size = -1;
672 int largest_color_class = -1;
673 for (i = _col; i < _col + _col_sz;) {
676 const bool new_largest = largest_color_class_size < (ptn[i] + 1);
677 largest_color_class_size = new_largest? (ptn[i] + 1) : largest_color_class_size;
678 largest_color_class = new_largest? i : largest_color_class;
682 dej_assert(largest_color_class < _col + _col_sz);
684 for (i = _col; i < _col + _col_sz;) {
685 const int i_sz = ptn[i] + 1;
686 const bool is_largest = i == largest_color_class;
687 report_split_color_class(c, _col, i, i_sz, is_largest);
692 neighbour_sizes.reset();
693 vertex_worklist.reset();
696 void refine_color_class_dense(sgraph *g, coloring *c,
int color_class,
int class_size) {
697 int i, cc, acc, largest_color_class_size, pos;
702 old_color_classes.reset();
703 vertex_worklist.reset();
705 const int end_cc = color_class + class_size;
708 while (cc < end_cc) {
709 const int vc = c->lab[cc];
710 const int pe = g->v[vc];
711 const int end_i = pe + g->d[vc];
712 for (i = pe; i < end_i; i++) {
713 const int v = g->e[i];
714 const int col = c->vertex_to_col[v];
715 if (c->ptn[col] > 0) {
717 if (!scratch_set.get(col)) {
718 scratch_set.set(col);
719 old_color_classes.push_back(col);
727 for(
int j = 0; j < old_color_classes.size(); ++j) {
728 const int _col = old_color_classes[j];
729 const int _col_sz = c->ptn[_col] + 1;
731 const int v_first = c->lab[_col];
732 const int index_first = neighbours.get(v_first);
735 for (i = 1; i < _col_sz && !splits; ++i) {
736 const int v = c->lab[_col + i];
737 const int index = neighbours.get(v);
738 splits = index != index_first;
743 old_color_classes[j] = old_color_classes[old_color_classes.size() - 1];
744 old_color_classes.pop_back();
747 old_color_classes.sort();
750 while (!old_color_classes.empty()) {
751 const int col = old_color_classes.pop_back();
752 const int col_sz = c->ptn[col] + 1;
753 if (col_sz == 1)
continue;
755 neighbour_sizes.reset();
756 vertex_worklist.reset();
758 const int first_index = neighbours.get(c->lab[col]) + 1;
759 vertex_worklist.push_back(first_index);
761 for (i = col; i < col + col_sz; ++i) {
762 const int v = c->lab[i];
763 int index = neighbours.get(v) + 1;
764 if (index == first_index)
continue;
766 if (neighbour_sizes.inc(index) == 0)
767 vertex_worklist.push_back(index);
770 neighbour_sizes.inc(first_index);
771 neighbour_sizes.set(first_index, col_sz - total - 1);
773 if (vertex_worklist.cur_pos == 1)
continue;
776 vertex_worklist.sort();
781 while (!vertex_worklist.empty()) {
782 const int j = vertex_worklist.pop_back();
783 const int val = neighbour_sizes.get(j) + 1;
785 neighbour_sizes.set(j, val + acc);
787 const int _col = col + col_sz - (neighbour_sizes.get(j));
792 vertex_worklist.reset();
795 memcpy(scratch.get_array(), c->lab + col, col_sz *
sizeof(
int));
801 const int v = scratch[--pos];
802 const int v_new_color = col + col_sz - (neighbour_sizes.get(neighbours.get(v) + 1));
807 c->lab[v_new_color + c->ptn[v_new_color] + 1] = v;
808 c->vertex_to_col[v] = v_new_color;
809 c->vertex_to_lab[v] = v_new_color + c->ptn[v_new_color] + 1;
810 c->ptn[v_new_color] += 1;
813 largest_color_class_size = -1;
814 int largest_color_class = 0;
816 for (i = col; i < col + col_sz;) {
819 const bool new_largest = largest_color_class_size < (c->ptn[i] + 1);
820 largest_color_class_size = new_largest? (c->ptn[i] + 1) : largest_color_class_size;
821 largest_color_class = new_largest? i : largest_color_class;
822 if (i != 0) c->ptn[i - 1] = 0;
826 dej_assert(largest_color_class < col + col_sz);
829 for (i = col; i < col + col_sz;) {
830 const int i_sz = c->ptn[i] + 1;
831 report_split_color_class(c, col, i, i_sz, i == largest_color_class);
839 void refine_color_class_dense_cell(sgraph *g, coloring *c,
int color_class,
int class_size) {
840 int i, cc, acc, largest_color_class_size, pos;
846 old_color_classes.reset();
847 vertex_worklist.reset();
849 const int end_cc = color_class + class_size;
852 while (cc < end_cc) {
853 const int vc = c->lab[cc];
854 const int pe = g->v[vc];
855 const int end_i = pe + g->d[vc];
856 for (i = pe; i < end_i; i++) {
857 const int v = g->e[i];
858 const int col = c->vertex_to_col[v];
860 scratch_set.set(col);
866 for(
int _col = 0; _col < g->v_size;) {
867 const int col_sz = c->ptn[_col] + 1;
868 const int col = _col;
870 if (col_sz == 1 || !scratch_set.get(col))
continue;
872 neighbour_sizes.reset();
873 vertex_worklist.reset();
875 const int first_index = neighbours.get(c->lab[col]) + 1;
876 vertex_worklist.push_back(first_index);
878 for (i = col; i < col + col_sz; ++i) {
879 const int v = c->lab[i];
880 int index = neighbours.get(v) + 1;
881 if (index == first_index)
continue;
883 if (neighbour_sizes.inc(index) == 0)
884 vertex_worklist.push_back(index);
887 neighbour_sizes.inc(first_index);
888 neighbour_sizes.set(first_index, col_sz - total - 1);
890 if (vertex_worklist.cur_pos == 1)
continue;
892 vertex_worklist.sort();
895 while (!vertex_worklist.empty()) {
896 const int j = vertex_worklist.pop_back();
897 const int val = neighbour_sizes.get(j) + 1;
899 neighbour_sizes.set(j, val + acc);
901 const int rcol = col + col_sz - (neighbour_sizes.get(j));
907 memcpy(scratch.get_array(), c->lab + col, col_sz *
sizeof(
int));
914 const int v = scratch[--pos];
915 const int v_new_color = col + col_sz - (neighbour_sizes.get(neighbours.get(v) + 1));
920 c->lab[v_new_color + c->ptn[v_new_color] + 1] = v;
921 c->vertex_to_col[v] = v_new_color;
922 c->vertex_to_lab[v] = v_new_color + c->ptn[v_new_color] + 1;
923 c->ptn[v_new_color] += 1;
926 largest_color_class_size = -1;
927 int largest_color_class = 0;
929 for (i = col; i < col + col_sz;) {
932 const bool new_largest = largest_color_class_size < (c->ptn[i] + 1);
933 largest_color_class_size = new_largest? (c->ptn[i] + 1) : largest_color_class_size;
934 largest_color_class = new_largest? i : largest_color_class;
935 if (i != 0) c->ptn[i - 1] = 0;
939 dej_assert(largest_color_class < col + col_sz);
942 for (i = col; i < col + col_sz;) {
943 const int i_sz = c->ptn[i] + 1;
944 report_split_color_class(c, col, i, i_sz, i == largest_color_class);
952 void refine_color_class_dense_dense(sgraph *g, coloring *c,
int color_class,
int class_size) {
953 int i, j, acc, cc, largest_color_class_size;
959 const int end_cc = color_class + class_size;
960 while (cc < end_cc) {
961 const int vc = c->lab[cc];
962 const int pe = g->v[vc];
964 const int end_i = pe + deg - (deg==g->v_size-1?deg:0);
966 for (i = pe; i < end_i; i++) {
967 const int v = g->e[i];
968 neighbours.inc_nr(v);
973 if(class_size == 1 && deg == g->v_size-1)
return;
977 for (j = 0; j < g->v_size;) {
979 const int col_sz = c->ptn[col] + 1;
981 if (col_sz == 1)
continue;
983 neighbour_sizes.reset();
984 vertex_worklist.reset();
986 const int first_index = neighbours.get(c->lab[col]) + 1;
987 vertex_worklist.push_back(first_index);
989 for (i = col; i < col + col_sz; ++i) {
990 const int v = c->lab[i];
991 const int index = neighbours.get(v) + 1;
992 if (index == first_index)
continue;
994 if (neighbour_sizes.inc(index) == 0)
995 vertex_worklist.push_back(index);
998 neighbour_sizes.inc(first_index);
999 neighbour_sizes.set(first_index, col_sz - total - 1);
1001 if (vertex_worklist.cur_pos == 1)
continue;
1003 vertex_worklist.sort();
1006 while (!vertex_worklist.empty()) {
1007 const int k = vertex_worklist.pop_back();
1008 const int val = neighbour_sizes.get(k) + 1;
1010 neighbour_sizes.set(k, val + acc);
1012 const int _col = col + col_sz - (neighbour_sizes.get(k));
1017 vertex_worklist.reset();
1020 memcpy(vertex_worklist.get_array(), c->lab + col, col_sz *
sizeof(
int));
1021 vertex_worklist.cur_pos = col_sz;
1025 while (!vertex_worklist.empty()) {
1026 const int v = vertex_worklist.pop_back();
1029 const int v_new_color = col + col_sz - (neighbour_sizes.get(neighbours.get(v) + 1));
1034 c->lab[v_new_color + c->ptn[v_new_color] + 1] = v;
1035 c->vertex_to_col[v] = v_new_color;
1036 c->vertex_to_lab[v] = v_new_color + c->ptn[v_new_color] + 1;
1037 c->ptn[v_new_color] += 1;
1040 largest_color_class_size = -1;
1041 int largest_color_class = 0;
1044 for (i = col; i < col + col_sz;) {
1047 const bool new_largest = largest_color_class_size < (c->ptn[i] + 1);
1048 largest_color_class_size = new_largest? (c->ptn[i] + 1) : largest_color_class_size;
1049 largest_color_class = new_largest? i : largest_color_class;
1050 if (i != 0) c->ptn[i - 1] = 0;
1054 dej_assert(largest_color_class < col + col_sz);
1057 for (i = col; i < col + col_sz;) {
1058 const int i_sz = c->ptn[i] + 1;
1059 report_split_color_class(c, col, i, i_sz, i == largest_color_class);
1064 neighbours.reset_hard();
1067 void refine_color_class_singleton(sgraph *g, coloring *c,
int color_class) {
1068 int i, cc, deg1_write_pos, deg1_read_pos;
1072 vertex_worklist.reset();
1073 old_color_classes.reset();
1075 const int vc = c->lab[cc];
1076 const int pe = g->v[vc];
1077 const int deg= g->d[vc];
1078 const int end_i = pe + deg;
1080 for (i = pe; i < end_i; i++) {
1081 const int v = g->e[i];
1082 const int col = c->vertex_to_col[v];
1085 if (c->ptn[col] == 0)
continue;
1087 if(neighbours.get(col) == -1) {
1088 old_color_classes.push_back(col);
1090 neighbours.set(col, col);
1093 scratch[neighbours.get(col)] = v;
1094 neighbours.inc_nr(col);
1116 old_color_classes.sort();
1118 for(
int j = 0; j < old_color_classes.cur_pos; ++j) {
1119 const int deg0_col = old_color_classes[j];
1120 const int deg1_col_sz = neighbours.get(deg0_col) - deg0_col;
1121 const int deg0_col_sz = (c->ptn[deg0_col] + 1) - deg1_col_sz;
1122 const int deg1_col = deg0_col + deg0_col_sz;
1124 dej_assert(c->vertex_to_col[c->lab[deg0_col]] == deg0_col);
1127 if (deg0_col == deg1_col) {
1128 neighbours.set(deg1_col, -1);
1129 dej_assert(c->vertex_to_col[c->lab[deg0_col]] == deg0_col);
1133 dej_assert(deg0_col_sz + deg1_col_sz - 1 == c->ptn[deg0_col]);
1136 c->ptn[deg0_col] = deg0_col_sz - 1;
1137 c->ptn[deg1_col] = deg1_col_sz - 1;
1138 c->ptn[deg1_col - 1] = 0;
1140 deg1_write_pos = deg1_col;
1141 deg1_read_pos = neighbours.get(deg0_col) - 1;
1148 while (deg1_read_pos >= deg0_col) {
1149 const int v = scratch[deg1_read_pos];
1150 const int vertex_at_pos = c->lab[deg1_write_pos];
1151 const int lab_pos = c->vertex_to_lab[v];
1153 c->lab[deg1_write_pos] = v;
1154 c->vertex_to_lab[v] = deg1_write_pos;
1155 c->vertex_to_col[v] = deg1_col;
1157 c->lab[lab_pos] = vertex_at_pos;
1158 c->vertex_to_lab[vertex_at_pos] = lab_pos;
1164 dej_assert(c->vertex_to_col[c->lab[deg0_col]] == deg0_col);
1165 dej_assert(c->vertex_to_col[c->lab[deg1_col]] == deg1_col);
1168 const bool leq = deg1_col_sz > deg0_col_sz;
1170 report_split_color_class(c, deg0_col, deg0_col, deg0_col_sz, !leq);
1171 report_split_color_class(c, deg0_col, deg1_col, deg1_col_sz, leq);
1174 neighbours.set(deg0_col, -1);
1177 old_color_classes.reset();
1180 void refine_color_class_singleton_first(sgraph *g, coloring *c,
int color_class) {
1181 int i, cc, deg1_write_pos, deg1_read_pos;
1185 scratch_set.reset();
1186 vertex_worklist.reset();
1187 old_color_classes.reset();
1189 const int vc = c->lab[cc];
1190 const int pe = g->v[vc];
1191 const int end_i = pe + g->d[vc];
1192 for (i = pe; i < end_i; i++) {
1193 const int v = g->e[i];
1194 const int col = c->vertex_to_col[v];
1196 if (c->ptn[col] == 0)
1199 if (!scratch_set.get(col)) {
1200 scratch_set.set(col);
1201 old_color_classes.push_back(col);
1204 neighbours.set(col, col);
1207 scratch[neighbours.get(col)] = v;
1208 neighbours.inc_nr(col);
1212 for(
int j = 0; j < old_color_classes.cur_pos; ++j) {
1213 const int deg0_col = old_color_classes[j];
1214 const int deg1_col_sz = neighbours.get(deg0_col) - deg0_col;
1215 const int deg0_col_sz = (c->ptn[deg0_col] + 1) - deg1_col_sz;
1216 const int deg1_col = deg0_col + deg0_col_sz;
1219 if (deg0_col == deg1_col) {
1220 neighbours.set(deg1_col, -1);
1225 c->ptn[deg0_col] = deg0_col_sz - 1;
1226 c->ptn[deg1_col] = deg1_col_sz - 1;
1227 c->ptn[deg1_col - 1] = 0;
1229 deg1_write_pos = deg1_col;
1230 deg1_read_pos = neighbours.get(deg0_col) - 1;
1233 while (deg1_read_pos >= deg0_col) {
1234 const int v = scratch[deg1_read_pos];
1235 const int vertex_at_pos = c->lab[deg1_write_pos];
1236 const int lab_pos = c->vertex_to_lab[v];
1238 c->lab[deg1_write_pos] = v;
1239 c->vertex_to_lab[v] = deg1_write_pos;
1240 c->vertex_to_col[v] = deg1_col;
1241 c->lab[lab_pos] = vertex_at_pos;
1242 c->vertex_to_lab[vertex_at_pos] = lab_pos;
1249 const bool leq = deg1_col_sz > deg0_col_sz;
1251 report_split_color_class_first(c, deg0_col, deg0_col, deg0_col_sz, !leq);
1252 report_split_color_class_first(c, deg0_col, deg1_col, deg1_col_sz, leq);
1255 neighbours.set(deg0_col, -1);
1258 old_color_classes.reset();
1261 void refine_color_class_dense_first(sgraph *g, coloring *c,
int color_class,
int class_size) {
1262 int i, cc, acc, largest_color_class_size, pos;
1266 scratch_set.reset();
1267 old_color_classes.reset();
1269 const int end_cc = color_class + class_size;
1270 while (cc < end_cc) {
1271 const int vc = c->lab[cc];
1272 const int pe = g->v[vc];
1273 const int end_i = pe + g->d[vc];
1275 for (i = pe; i < end_i; i++) {
1276 const int v = g->e[i];
1277 const int col = c->vertex_to_col[v];
1278 if (c->ptn[col] == 0)
1282 if (!scratch_set.get(col)) {
1283 scratch_set.set(col);
1284 old_color_classes.push_back(col);
1290 while (!old_color_classes.empty()) {
1291 const int col = old_color_classes.pop_back();
1292 const int col_sz = c->ptn[col] + 1;
1295 const int v_degree = neighbours.get(c->lab[col]) + 1;
1300 neighbour_sizes.reset();
1301 vertex_worklist.reset();
1303 const int first_index = neighbours.get(c->lab[col]) + 1;
1304 vertex_worklist.push_back(first_index);
1306 for (i = col; i < col + col_sz; ++i) {
1307 const int v = c->lab[i];
1308 const int index = neighbours.get(v) + 1;
1309 if (index == first_index)
1312 if (neighbour_sizes.inc(index) == 0)
1313 vertex_worklist.push_back(index);
1316 neighbour_sizes.inc(first_index);
1317 neighbour_sizes.set(first_index, col_sz - total - 1);
1319 if (vertex_worklist.cur_pos == 1) {
1325 while (!vertex_worklist.empty()) {
1326 const int k = vertex_worklist.pop_back();
1327 const int val = neighbour_sizes.get(k) + 1;
1329 neighbour_sizes.set(k, val + acc);
1331 const int _col = col + col_sz - (neighbour_sizes.get(k));
1337 memcpy(scratch.get_array(), c->lab + col, col_sz *
sizeof(
int));
1343 const int v = scratch[--pos];
1344 const int v_new_color = col + col_sz - (neighbour_sizes.get(neighbours.get(v) + 1));
1349 c->lab[v_new_color + c->ptn[v_new_color] + 1] = v;
1350 c->vertex_to_col[v] = v_new_color;
1351 c->vertex_to_lab[v] = v_new_color + c->ptn[v_new_color] + 1;
1352 c->ptn[v_new_color] += 1;
1355 largest_color_class_size = -1;
1356 int largest_color_class = -1;
1359 for (i = col; i < col + col_sz;) {
1362 const bool new_largest = largest_color_class_size < (c->ptn[i] + 1);
1363 largest_color_class_size = new_largest? (c->ptn[i] + 1) : largest_color_class_size;
1364 largest_color_class = new_largest? i : largest_color_class;
1365 if (i != 0) c->ptn[i - 1] = 0;
1370 for (i = col; i < col + col_sz;) {
1371 const int i_sz = c->ptn[i] + 1;
1372 report_split_color_class_first(c, col, i, i_sz, i == largest_color_class);
1378 void refine_color_class_dense_dense_first(sgraph *g, coloring *c,
int color_class,
int class_size) {
1380 int i, j, cc, acc, largest_color_class_size, pos;
1384 old_color_classes.reset();
1386 const int end_cc = color_class + class_size;
1387 while (cc < end_cc) {
1388 const int vc = c->lab[cc];
1389 const int pe = g->v[vc];
1390 const int end_i = pe + g->d[vc];
1391 for (i = pe; i < end_i; i++) {
1392 const int v = g->e[i];
1393 neighbours.inc_nr(v);
1399 for (j = 0; j < g->v_size;) {
1401 const int c_ptn = c->ptn[j];
1403 const int col_sz = c_ptn + 1;
1408 neighbour_sizes.reset();
1409 vertex_worklist.reset();
1411 const int first_index = neighbours.get(c->lab[col]) + 1;
1412 vertex_worklist.push_back(first_index);
1414 for (i = col; i < col + col_sz; ++i) {
1415 const int v = c->lab[i];
1416 const int index = neighbours.get(v) + 1;
1417 if (index == first_index)
1420 if (neighbour_sizes.inc(index) == 0)
1421 vertex_worklist.push_back(index);
1424 neighbour_sizes.inc(first_index);
1425 neighbour_sizes.set(first_index, col_sz - total - 1);
1427 if (vertex_worklist.cur_pos == 1) {
1433 while (!vertex_worklist.empty()) {
1434 const int k = vertex_worklist.pop_back();
1435 const int val = neighbour_sizes.get(k) + 1;
1437 neighbour_sizes.set(k, val + acc);
1439 const int _col = col + col_sz - (neighbour_sizes.get(k));
1445 memcpy(scratch.get_array(), c->lab + col, col_sz *
sizeof(
int));
1451 const int v = scratch[--pos];
1452 const int v_new_color = col + col_sz - (neighbour_sizes.get(neighbours.get(v) + 1));
1456 c->lab[v_new_color + c->ptn[v_new_color] + 1] = v;
1457 c->vertex_to_col[v] = v_new_color;
1458 c->vertex_to_lab[v] = v_new_color + c->ptn[v_new_color] + 1;
1459 c->ptn[v_new_color] += 1;
1462 largest_color_class_size = -1;
1463 int largest_color_class = 0;
1466 for (i = col; i < col + col_sz;) {
1469 const bool new_largest = largest_color_class_size < (c->ptn[i] + 1);
1470 largest_color_class_size = new_largest? (c->ptn[i] + 1) : largest_color_class_size;
1471 largest_color_class = new_largest? i : largest_color_class;
1472 if (i != 0) c->ptn[i - 1] = 0;
1477 for (i = col; i < col + col_sz;) {
1478 const int i_sz = c->ptn[i] + 1;
1479 report_split_color_class_first(c, col, i, i_sz, i == largest_color_class);
1484 neighbours.reset_hard();
1757 void refine_color_class_sparse_first(sgraph *g, coloring *c,
int color_class,
int class_size) {
1758 int v_new_color, cc, largest_color_class_size, acc;
1761 scratch_set.reset();
1762 old_color_classes.reset();
1764 color_vertices_considered.reset();
1766 const int end_cc = color_class + class_size;
1767 while (cc < end_cc) {
1768 const int vc = c->lab[cc];
1769 const int pe = g->v[vc];
1770 const int end_i = pe + g->d[vc];
1771 for (
int i = pe; i < end_i; i++) {
1772 const int v = g->e[i];
1773 const int col = c->vertex_to_col[v];
1775 if (c->ptn[col] == 0)
1778 neighbours.inc_nr(v);
1779 if (neighbours.get(v) == 0) {
1780 color_vertices_considered.inc_nr(col);
1781 dej_assert(col + color_vertices_considered.get(col) < g->v_size);
1782 scratch[col + color_vertices_considered.get(col)] = v;
1783 if (!scratch_set.get(col)) {
1784 old_color_classes.push_back(col);
1785 scratch_set.set(col);
1793 while (!old_color_classes.empty()) {
1794 const int _col = old_color_classes.pop_back();
1795 const int _col_sz = c->ptn[_col] + 1;
1797 neighbour_sizes.reset();
1798 vertex_worklist.reset();
1800 for (
int i = 0; i < color_vertices_considered.get(_col) + 1; ++i) {
1801 const int v = scratch[_col + i];
1802 int index = neighbours.get(v) + 1;
1803 if (neighbour_sizes.inc(index) == 0)
1804 vertex_worklist.push_back(index);
1809 while (!vertex_worklist.empty()) {
1810 const int i = vertex_worklist.pop_back();
1811 const int val = neighbour_sizes.get(i) + 1;
1813 neighbour_sizes.set(i, val + acc);
1819 vertex_worklist.reset();
1821 for (
int i = 0; i < color_vertices_considered.get(_col) + 1; ++i) {
1822 const int v = scratch[_col + i];
1823 if (neighbours.get(v) == -1) {
1828 v_new_color = _col + _col_sz - neighbour_sizes.get(neighbours.get(v) + 1);
1830 if (v_new_color != _col) {
1831 vertex_worklist.push_back(v_new_color);
1832 vertex_worklist.push_back(v);
1833 c->ptn[v_new_color] = -1;
1835 neighbours.set(v, -1);
1838 color_vertices_considered.set(_col, -1);
1841 while (!vertex_worklist.empty()) {
1842 const int v = vertex_worklist.pop_back();
1843 const int v_new_color2 = vertex_worklist.pop_back();
1845 const int vertex_old_pos = c->vertex_to_lab[v];
1846 const int vertex_at_pos = c->lab[v_new_color2 + c->ptn[v_new_color2] + 1];
1847 c->lab[vertex_old_pos] = vertex_at_pos;
1848 c->vertex_to_lab[vertex_at_pos] = vertex_old_pos;
1850 c->lab[v_new_color2 + c->ptn[v_new_color2] + 1] = v;
1851 c->vertex_to_col[v] = v_new_color2;
1852 c->vertex_to_lab[v] = v_new_color2 + c->ptn[v_new_color2] + 1;
1853 c->ptn[v_new_color2] += 1;
1855 if (_col != v_new_color2) {
1863 largest_color_class_size = -1;
1864 int largest_color_class = -1;
1866 for (i = _col; i < _col + _col_sz;) {
1869 const bool new_largest = largest_color_class_size < (c->ptn[i] + 1);
1870 largest_color_class_size = new_largest? (c->ptn[i] + 1) : largest_color_class_size;
1871 largest_color_class = new_largest? i : largest_color_class;
1872 if (i != 0) c->ptn[i - 1] = 0;
1875 if (i != 0) c->ptn[i - 1] = 0;
1878 for (i = _col; i < _col + _col_sz;) {
1879 const int i_sz = c->ptn[i] + 1;
1880 report_split_color_class_first(c, _col, i, i_sz, i == largest_color_class);
1885 neighbour_sizes.reset();
1886 vertex_worklist.reset();
Vertex coloring for a graph.
Set specialized for quick resets.
void initialize(int size)
static bool certify_automorphism_sparse(markset &scratch_set, const sgraph *g, const int *p, int supp, const int *supp_arr)
static bool certify_automorphism(markset &scratch_set, sgraph *g, const int *p)
Color refinement and related algorithms.
bool certify_automorphism(sgraph *g, const int *p)
static int individualize_vertex(coloring *c, int v, const std::function< type_split_color_hook > &split_hook=nullptr)
void refine_coloring_first(sgraph *g, coloring *c, int init_color_class=-1)
bool certify_automorphism_sparse(const sgraph *g, const int *p, int supp, const int *supp_arr)
void refine_coloring(sgraph *g, coloring *c, int init_color=-1, int color_limit=-1, const std::function< type_split_color_hook > *split_hook=nullptr, const std::function< type_worklist_color_hook > *worklist_hook=nullptr)
Internal graph data structure.
workset_t< int > work_set_int
bool type_worklist_color_hook(const int, const int)
bool type_split_color_hook(const int, const int, const int)