31 static void reset_automorphism(
int *automorphism,
worklist *support) {
32 for (
int i = 0; i < support->
cur_pos; ++i) {
33 automorphism[(*support)[i]] = (*support)[i];
50 static void color_diff_automorphism(
int domain_size,
const int *vertex_to_col,
const int *col_to_vertex,
51 int *automorphism,
worklist *support) {
53 for (
int v1 = 0; v1 < domain_size; ++v1) {
54 const int col = vertex_to_col[v1];
55 const int v2 = col_to_vertex[col];
57 automorphism[v1] = v2;
72 bool support01 =
false;
75 bool have_inverse_automorphism =
false;
80 void update_inverse_automorphism() {
81 if(!have_inverse_automorphism) {
82 for (
int i = 0; i < domain_size; ++i) {
83 const int j = automorphism[i];
84 inverse_automorphism[j] = i;
86 have_inverse_automorphism =
true;
93 void invalidate_inverse_automorphism() {
94 have_inverse_automorphism =
false;
104 for (
int i = 0; i < domain_sz; ++i) {
107 automorphism_supp.
allocate(domain_sz);
108 inverse_automorphism.
allocate(domain_sz);
109 invalidate_inverse_automorphism();
110 this->domain_size = domain_sz;
119 automorphism.
resize(new_domain_size);
120 for (
int i = 0; i < new_domain_size; ++i) {
123 automorphism_supp.
resize(new_domain_size);
124 automorphism_supp.
reset();
125 inverse_automorphism.
resize(new_domain_size);
126 invalidate_inverse_automorphism();
127 this->domain_size = new_domain_size;
138 return automorphism[point];
149 this->support01 = new_support01;
161 color_diff_automorphism(domain_size, vertex_to_col, col_to_vertex, automorphism.
get_array(),
163 invalidate_inverse_automorphism();
172 automorphism_supp.
reset();
173 for (
int i = 0; i < domain_size; ++i) {
174 if (i != automorphism[i])
178 automorphism_supp.
reset();
180 for (i = 0; i < domain_size; ++i) {
181 if (i != automorphism[i])
break;
183 automorphism_supp.
cur_pos = (i != domain_size);
197 #ifndef dej_nothreadlocal
198 thread_local worklist scratch_apply1;
199 thread_local worklist scratch_apply2;
200 thread_local markset scratch_apply3;
206 scratch_apply1.
allocate(domain_size);
207 scratch_apply2.
allocate(domain_size);
210 apply(scratch_apply1, scratch_apply2, scratch_apply3, other, pwr);
227 if(!other.support01 && other.
nsupp() <= domain_size / 4) {
228 apply_sparse(scratch_apply1, scratch_apply2, scratch_apply3, other.
p(), other.
supp(),
231 apply(scratch_apply1, scratch_apply2, scratch_apply3, other.
p(), pwr);
249 const int *
p,
int pwr = 1) {
250 if (pwr == 0)
return;
253 for (
int i = 0; i < domain_size; ++i) automorphism[i] =
p[automorphism[i]];
255 for (
int i = 0; i < domain_size; ++i) automorphism[i] =
p[
p[automorphism[i]]];
257 for (
int i = 0; i < domain_size; ++i) automorphism[i] =
p[
p[
p[automorphism[i]]]];
259 for (
int i = 0; i < domain_size; ++i) automorphism[i] =
p[
p[
p[
p[automorphism[i]]]]];
261 for (
int i = 0; i < domain_size; ++i) automorphism[i] =
p[
p[
p[
p[
p[automorphism[i]]]]]];
262 }
else if (pwr <= 19) {
264 for (
int j = 0; j < domain_size; ++j) {
265 scratch_apply1[j] =
p[
p[
p[j]]];
267 for (; pwr >= 6; pwr -= 6)
268 for (
int j = 0; j < domain_size; ++j)
269 automorphism[j] = scratch_apply1[scratch_apply1[automorphism[j]]];
272 for (
int i = 0; i < domain_size; ++i) automorphism[i] =
p[automorphism[i]];
274 for (
int i = 0; i < domain_size; ++i) automorphism[i] =
p[
p[automorphism[i]]];
276 for (
int i = 0; i < domain_size; ++i) automorphism[i] = scratch_apply1[automorphism[i]];
278 for (
int i = 0; i < domain_size; ++i) automorphism[i] =
p[scratch_apply1[automorphism[i]]];
280 for (
int i = 0; i < domain_size; ++i) automorphism[i] =
p[
p[scratch_apply1[automorphism[i]]]];
284 scratch_apply3.
reset();
285 for (
int i = 0; i < domain_size; ++i) {
286 if (scratch_apply3.
get(i))
continue;
288 scratch_apply2[i] = i;
291 scratch_apply1[0] = i;
292 for (
int j =
p[i]; j != i; j =
p[j]) {
293 scratch_apply1[cyclen++] = j;
294 scratch_apply3.
set(j);
296 int kk = pwr % cyclen;
297 for (
int j = 0; j < cyclen; ++j) {
298 scratch_apply2[scratch_apply1[j]] = scratch_apply1[kk];
299 if (++kk == cyclen) kk = 0;
303 for (
int i = 0; i < domain_size; ++i) automorphism[i] = scratch_apply2[automorphism[i]];
304 scratch_apply3.
reset();
309 invalidate_inverse_automorphism();
313 const int *
p,
const int* support,
const int nsupport,
int pwr = 1) {
314 if (pwr == 0)
return;
318 update_inverse_automorphism();
319 scratch_apply1.
reset();
320 scratch_apply2.
reset();
324 for (
int k = 0; k < nsupport; ++k) {
325 const int i = support[k];
326 dej_assert(automorphism[inverse_automorphism[i]] == i);
327 const int inv_i = inverse_automorphism[i];
328 const int p_i =
p[i];
329 automorphism[inv_i] = p_i;
335 for (
int k = 0; k < nsupport; ++k) {
336 const int i = support[k];
337 dej_assert(automorphism[inverse_automorphism[i]] == i);
338 const int inv_i = inverse_automorphism[i];
339 const int p_i =
p[
p[i]];
340 automorphism[inv_i] = p_i;
346 for (
int k = 0; k < nsupport; ++k) {
347 const int i = support[k];
348 dej_assert(automorphism[inverse_automorphism[i]] == i);
349 const int inv_i = inverse_automorphism[i];
350 const int p_i =
p[
p[
p[i]]];
351 automorphism[inv_i] = p_i;
357 for (
int k = 0; k < nsupport; ++k) {
358 const int i = support[k];
359 dej_assert(automorphism[inverse_automorphism[i]] == i);
360 const int inv_i = inverse_automorphism[i];
361 const int p_i =
p[
p[
p[
p[i]]]];
362 automorphism[inv_i] = p_i;
368 for (
int k = 0; k < nsupport; ++k) {
369 const int i = support[k];
370 dej_assert(automorphism[inverse_automorphism[i]] == i);
371 const int inv_i = inverse_automorphism[i];
372 const int p_i =
p[
p[
p[
p[
p[i]]]]];
373 automorphism[inv_i] = p_i;
379 for (
int k = 0; k < nsupport; ++k) {
380 const int i = support[k];
381 dej_assert(automorphism[inverse_automorphism[i]] == i);
382 const int inv_i = inverse_automorphism[i];
383 const int p_i =
p[
p[
p[
p[
p[
p[i]]]]]];
384 automorphism[inv_i] = p_i;
395 for (
int k = 0; k < scratch_apply1.
size(); ++k)
396 inverse_automorphism[scratch_apply2[k]] = scratch_apply1[k];
397 scratch_apply1.
reset();
398 scratch_apply2.
reset();
401 apply(scratch_apply1, scratch_apply2, scratch_apply3,
p, pwr);
420 void write_singleton(
const std::vector<int> *singletons1,
const std::vector<int> *singletons2,
421 const int pos_start,
const int pos_end) {
422 for (
int i = pos_start; i < pos_end; ++i) {
423 const int from = (*singletons1)[i];
424 const int to = (*singletons2)[i];
428 automorphism[from] = to;
431 invalidate_inverse_automorphism();
441 for(
int i = 0; i < automorphism_supp.
size(); ++i) {
442 const int v = automorphism_supp[i];
443 if(scratch_set.
get(v))
continue;
444 int v_next = automorphism[v];
446 if(scratch_set.
get(v_next))
break;
447 scratch_set.
set(v_next);
448 if(v_next == automorphism[v_next]) {
450 automorphism[v_next] = v;
452 v_next = automorphism[v_next];
455 invalidate_inverse_automorphism();
467 automorphism[from] = to;
469 invalidate_inverse_automorphism();
476 invalidate_inverse_automorphism();
477 reset_automorphism(automorphism.
get_array(), &automorphism_supp);
498 return automorphism_supp.
cur_pos;
526 next_map = map_arr[last_map];
527 }
while(next_map != last_map);
528 map_arr[v] = next_map;
551 return v == map_arr[v];
568 if(orbit1 == orbit2)
return;
569 if(orbit1 < orbit2) {
570 map_arr[orbit2] = orbit1;
571 orb_sz[orbit1] += orb_sz[orbit2];
573 map_arr[orbit1] = orbit2;
574 orb_sz[orbit2] += orb_sz[orbit1];
591 if(v1 == v2)
return true;
594 return (orbit1 == orbit2);
602 for(
int v = 0; v < sz; ++v) {
614 for (
int i = 0; i < nsupp; ++i) {
625 const int nsupp = aut.
nsupp();
626 const int* supp = aut.
supp();
627 const int* p = aut.
p();
628 for (
int i = 0; i < nsupp; ++i) {
639 if(sz == domain_size) {
646 for(
int i = 0; i < domain_size; ++i) {
664 map_arr = other.map_arr;
665 orb_sz = other.orb_sz;
671 bool comp = (other_orbit.sz == sz) ;
672 for(
int i = 0; i < sz && comp; ++i)
684 int *loaded_automorphism =
nullptr;
687 loaded_automorphism = automorphism;
691 return loaded_automorphism;
727 int first_of_cycle = 0;
728 for (
int i = 0; i < data.
size(); ++i) {
729 const int j = abs(data[i]) - 1;
730 const bool is_last = data[i] < 0;
734 first_of_cycle = i + 1;
740 loader.
load(space.
p());
749 automorphism.
reset();
750 int first_of_cycle = 0;
751 for (
int i = 0; i < data.
size(); ++i) {
752 const int j = abs(data[i]) - 1;
753 const bool is_last = data[i] < 0;
757 first_of_cycle = i + 1;
764 automorphism.
reset();
765 for(
int i = 0; i < domain_size; ++i) {
766 const int v_from = i;
779 domain_size = new_domain_size;
783 for (
int i = 0; i < domain_size; ++i) support += (automorphism.
p()[i] != i);
786 if (support < domain_size / 4) {
791 for (
int i = 0; i < domain_size; ++i) {
792 if (automorphism.
p()[i] == i)
continue;
794 if (helper.
get(j))
continue;
796 int map_j = automorphism.
p()[j];
798 while (!helper.
get(map_j)) {
801 map_j = automorphism.
p()[map_j];
812 memcpy(data.
get_array(), automorphism.
p(), domain_size *
sizeof(
int));
855 std::vector<stored_automorphism *> generators;
870 this->domain_size = new_domain_size;
882 const auto num = generators.size() - 1;
883 generators[num]->store(domain_size, automorphism, w.
scratch2);
890 return static_cast<int>(num);
896 delete generators[num];
897 generators[num] =
nullptr;
907 for(
int test_pt : fix_points) {
908 for(
size_t j = 0; j < generators.size(); ++j) {
909 const auto gen = generators[j];
910 if(gen ==
nullptr)
continue;
923 std::vector<stored_automorphism *> new_gens;
924 for(
auto gen : generators) {
925 if(gen) new_gens.push_back(gen);
927 generators.swap(new_gens);
937 return generators[num];
948 return static_cast<int>(generators.size());
952 for(
auto & generator : generators) {
973 int sz_upb = INT32_MAX;
975 bool finished =
false;
977 std::vector<int> fixed_orbit;
978 std::vector<int> fixed_orbit_to_perm;
979 std::vector<int> fixed_orbit_to_pwr;
990 for (
int p : fixed_orbit) {
1004 void add_to_fixed_orbit(
const int vertex,
const int perm,
const int pwr) {
1005 fixed_orbit.push_back(vertex);
1006 fixed_orbit_to_perm.push_back(perm);
1007 fixed_orbit_to_pwr.push_back(pwr);
1026 auto generator = generators[gen_num];
1049 return (
int) fixed_orbit.size();
1053 sz_upb = new_sz_upb;
1066 for (
size_t i = 0; i < fixed_orbit.size(); ++i) {
1067 if (p == fixed_orbit[i]) {
1081 load_orbit_to_scratch(w);
1082 int back_swap = (int) selection.size() - 1;
1084 for (front_pt = 0; front_pt <= back_swap;) {
1088 selection[front_pt] = selection[back_swap];
1092 selection.resize(front_pt);
1115 return fixed_orbit_to_perm;
1125 void initialize(
const int fixed_vertex,
const int new_level,
const int new_sz_upb) {
1128 fixed = fixed_vertex;
1129 this->level = new_level;
1130 this->sz_upb = new_sz_upb;
1131 add_to_fixed_orbit(fixed_vertex, -1, 0);
1143 if (finished)
return false;
1146 load_orbit_to_scratch(w);
1147 bool changed =
false;
1151 for (
int i = 0; i < static_cast<int>(fixed_orbit.size()); ++i) {
1152 const int p = fixed_orbit[i];
1153 int j = automorphism.
p()[p];
1158 for (
int jj = j; !w.
scratch1.
get(jj); jj = automorphism.
p()[jj]) {
1167 if (gen_num == -1) gen_num = generators.
add_generator(w, automorphism);
1170 add_to_fixed_orbit(j, gen_num, pwr);
1174 j = automorphism.
p()[j];
1180 if (sz_upb == (
int) fixed_orbit.size() && !finished) {
1184 dej_assert(sz_upb >= (
int) fixed_orbit.size());
1200 int fixed_map = automorphism.
p()[fixed];
1204 while (fixed != fixed_map) {
1207 const int perm = fixed_orbit_to_perm[pos];
1208 const int pwr = fixed_orbit_to_pwr[pos];
1209 apply_perm(w, automorphism, generators, perm, pwr);
1210 fixed_map = automorphism.
p()[fixed];
1213 return automorphism.
nsupp() == 0;
1226 int domain_size = -1;
1227 int finished_up_to = -1;
1230 std::vector<shared_transversal> transversals;
1231 std::vector<int> stabilized_generators;
1262 void initialize(
const int new_domain_size, std::vector<int> &base, std::vector<int> &base_sizes,
1263 int stop = INT32_MAX) {
1264 stop = std::min(
static_cast<int>(base.size()), stop);
1265 dej_assert(
static_cast<int>(base.size()) >= stop);
1266 domain_size = new_domain_size;
1270 transversals.reserve(stop);
1271 transversals.clear();
1272 finished_up_to = -1;
1274 for (
int i = 0; i < stop && i < static_cast<int>(base.size()); ++i) {
1275 transversals.emplace_back();
1276 transversals[i].initialize(base[i], i, base_sizes[i]);
1282 std::vector<int> &new_base,
int err = 10,
bool resift_generators =
false) {
1284 const int old_size =
static_cast<int>(transversals.size());
1285 const int new_size =
static_cast<int>(new_base.size());
1289 for (; keep_until < old_size && keep_until < new_size; ++keep_until) {
1290 if (transversals[keep_until].get_fixed_point() != new_base[keep_until])
break;
1293 if (keep_until == new_size)
return;
1295 finished_up_to = -1;
1296 transversals.resize(new_size);
1299 for (
int i = 0; i < keep_until; ++i) { transversals[i].set_size_upper_bound(INT32_MAX); }
1300 for (
int i = keep_until; i < new_size; ++i) {
1303 transversals[i].initialize(new_base[i], i, INT32_MAX);
1306 std::vector<int> stabilized_generators_copy;
1307 stabilized_generators_copy.swap(stabilized_generators);
1308 stabilized_generators.clear();
1310 if(resift_generators) {
1311 for (
int gen_id : stabilized_generators_copy)
sift_generator(w, automorphism, gen_id,
true);
1319 bool any_changed =
false;
1321 const bool sift_changed =
sift_random(w, automorphism, rng,
true);
1322 any_changed = sift_changed || any_changed;
1323 fail -= !sift_changed;
1336 std::vector<int> &new_base_sizes,
const int stop,
bool keep_old,
bool remove_generators,
1337 std::vector<int> &global_fixed_points) {
1338 const int old_size =
static_cast<int>(transversals.size());
1339 if(!init || new_domain_size != domain_size) {
1340 initialize(new_domain_size, new_base, new_base_sizes, stop);
1343 const int new_size = stop;
1347 if(remove_generators) generators.
clear();
1349 for (; keep_until < old_size && keep_until < new_size; ++keep_until) {
1350 if (transversals[keep_until].get_fixed_point() != new_base[keep_until])
break;
1354 generators.
filter(w, global_fixed_points);
1357 if(keep_until == new_size && new_size == old_size)
return false;
1359 finished_up_to = -1;
1361 transversals.resize(new_size);
1365 for(
int i = 0; i < keep_until; ++i) {
1366 transversals[i].set_size_upper_bound(new_base_sizes[i]);
1368 for (
int i = keep_until; i < stop; ++i) {
1372 transversals[i].initialize(new_base[i], i, new_base_sizes[i]);
1375 stabilized_generators.clear();
1389 for (
int i =
base_size()-1; i >= 0; --i) {
1390 const int corresponding_root_color_sz =
1391 root_coloring->
ptn[root_coloring->
vertex_to_col[transversals[i].get_fixed_point()]] + 1;
1392 if(transversals[i].size() >= corresponding_root_color_sz && corresponding_root_color_sz > 1) {
1393 save_to_individualize->emplace_back(transversals[i].get_fixed_point(), corresponding_root_color_sz);
1403 return transversals[pos].get_fixed_point();
1410 return static_cast<int>(transversals.size());
1421 if (base_pos >=
base_size())
return false;
1422 if(v < 0)
return false;
1425 const int search = transversals[base_pos].find_point(v);
1426 return search != -1;
1432 return transversals[base_pos].get_fixed_orbit();
1438 return transversals[base_pos].get_generators();
1442 return stabilized_generators;
1446 if (base_pos >=
static_cast<int>(transversals.size()))
return 0;
1447 return transversals[base_pos].size();
1459 transversals[base_pos].reduce_to_unfinished(w, selection);
1469 return transversals[base_pos].is_finished();
1480 bool keep_at_end =
false) {
1481 bool changed =
false;
1484 for (
int level = 0; level < static_cast<int>(transversals.size()); ++level) {
1486 changed = transversals[level].extend_with_automorphism(w, generators, automorphism)
1490 const bool identity = transversals[level].fix_automorphism(w, generators, automorphism);
1491 if (identity)
break;
1494 if(automorphism.
nsupp() != 0 && keep_at_end) {
1495 const int gen_id = generators.
add_generator(w, automorphism);
1496 stabilized_generators.push_back(gen_id);
1500 for (
int level = finished_up_to + 1; level < static_cast<int>(transversals.size()); ++level) {
1501 if (finished_up_to == level - 1 && transversals[level].
is_finished()) {
1511 automorphism.
reset();
1527 automorphism.
reset();
1529 const int random_mult =
static_cast<int>(rng() % 7);
1530 const int num_mult = 1 + (random_mult);
1531 for(
int i = 0; i < num_mult; ++i) {
1533 const int next_gen_num =
static_cast<int>(rng() % generators.
size());
1536 auto next_gen = generators[next_gen_num];
1547 auto next_gen = generators[generator];
1548 next_gen->load(automorphism);
1560 if(generators.
size() <= 0)
return false;
1561 automorphism.
reset();
1564 const bool added_generator =
sift(w, automorphism,
false, keep_at_end);
1565 return added_generator;
1569 bool keep_at_end =
false) {
1570 if(generators.
size() <= 0)
return false;
1571 automorphism.
reset();
1574 const bool added_generator =
sift(w, automorphism,
false, keep_at_end);
1575 return added_generator;
1620 return finished_up_to;
1630 for (
auto & transversal : transversals)
s_grp_sz.
multiply(transversal.size());
1645 int h_domain_size = -1;
1654 int h_error_bound = 10;
1684 explicit random_schreier(
int domain_size,
int error = 10,
bool true_random =
false,
int seed = 0) :
1685 ws_auto(domain_size), ws_schreier(domain_size), rng(true_random, seed),
1686 auxiliary_set(domain_size) {
1687 h_error_bound = error;
1688 h_domain_size = domain_size;
1696 void set_base(std::vector<int> &new_base,
bool resift_generators =
false) {
1698 std::vector<int> base_sizes;
1699 base_sizes.reserve(new_base.size());
1700 for(
int i = 0; i < static_cast<int>(new_base.size()); ++i) base_sizes.push_back(INT32_MAX);
1701 schreier.
initialize(h_domain_size, new_base, base_sizes);
1703 }
else schreier.
set_base(ws_schreier, ws_auto, rng, new_base, h_error_bound, resift_generators);
1711 schreier.
sift_random(ws_schreier, ws_auto, rng, h_error_bound);
1767 auxiliary_set.
reset();
1768 orbit_partition.
reset();
1771 for(
int j = base_pos; j < schreier.
base_size(); ++j) {
1773 for (
auto i: generators) {
1774 if (i < 0)
continue;
1776 if (auxiliary_set.
get(i))
continue;
1777 auxiliary_set.
set(i);
1799 auxiliary_set.
reset();
1800 std::vector<int> all_generators;
1803 for(
int j = base_pos; j < schreier.
base_size(); ++j) {
1805 for (
auto i: generators) {
1806 if (i < 0)
continue;
1808 if (auxiliary_set.
get(i))
continue;
1809 auxiliary_set.
set(i);
1810 all_generators.push_back(i);
1815 if (auxiliary_set.
get(i))
continue;
1816 auxiliary_set.
set(i);
1817 all_generators.push_back(i);
1820 return all_generators;
1833 return sift(h_domain_size, automorphism.
p(), automorphism.
nsupp(), automorphism.
supp(), known_in_group);
1845 bool sift(
int,
const int *p,
int nsupp,
const int *supp,
bool known_in_group =
false) {
1847 for(
int i = 0; i < h_domain_size; ++i)
dej_assert(ws_auto.
p()[i] == i);
1849 for(
int i = 0; i < nsupp; ++i) {
1850 const int v_from = supp[i];
1851 const int v_to = p[v_from];
1855 const bool result = schreier.
sift(ws_schreier, ws_auto,
false, !known_in_group);
1875 std::vector<int> map_to_small;
1876 std::vector<int> map_to_big;
1877 bool do_compress =
false;
1878 int s_vertices_active = 0;
1879 int domain_size = 0;
1883 do_compress =
false;
1901 color_was_added.
reset();
1902 test_vertices_active.
reset();
1904 s_vertices_active = 0;
1906 for(
int i = 0; i < stop; ++i) {
1907 const int base_vertex = base[i];
1909 if(!color_was_added.
get(col)) {
1910 color_was_added.
set(col);
1911 const int col_sz = c.
ptn[col] + 1;
1912 s_vertices_active += col_sz;
1913 for(
int j = 0; j < col_sz; ++j) {
1914 const int add_v = c.
lab[col + j];
1915 test_vertices_active.
set(add_v);
1921 map_to_big.resize(s_vertices_active);
1922 int next_active_v_maps_to = 0;
1924 if(test_vertices_active.
get(v)) {
1925 map_to_small[v] = next_active_v_maps_to;
1926 map_to_big[next_active_v_maps_to] = v;
1927 ++next_active_v_maps_to;
1929 map_to_small[v] = -1;
1940 return s_vertices_active;
1956 if(!do_compress)
return v;
1957 return map_to_small[v];
1966 if(!do_compress)
return v;
1967 return map_to_big[v];
1981 std::vector<int> original_base;
1982 std::vector<int> original_base_sizes;
2011 std::vector<int> &new_base, std::vector<int> &new_base_sizes,
const int stop,
bool keep_old,
2012 std::vector<int> &global_fixed_points) {
2013 bool remove_generators = (compressor !=
nullptr);
2015 compressor = new_compressor;
2018 if(compressor !=
nullptr &&
2021 remove_generators = remove_generators || (compressor !=
nullptr);
2023 if(compressor !=
nullptr) {
2025 original_base = new_base;
2026 original_base_sizes = new_base_sizes;
2029 std::vector<int> new_basec;
2030 new_basec.reserve(new_base.size());
2031 for (
int i = 0; i < static_cast<int>(new_base.size()); ++i)
2032 new_basec.push_back(compressor->
compress(new_base[i]));
2036 new_base_sizes, stop, keep_old, remove_generators,
2037 global_fixed_points);
2041 return internal_schreier.
reset(new_domain_size, w, new_base,
2042 new_base_sizes, stop, keep_old, remove_generators,
2043 global_fixed_points);
2056 if(compressor ==
nullptr) {
2061 for (
int i =
base_size()-1; i >= 0; --i) {
2062 const int corresponding_root_color_sz = root_coloring->
ptn[root_coloring->
vertex_to_col[original_base[i]]] + 1;
2063 if(internal_schreier.
get_fixed_orbit_size(i) >= corresponding_root_color_sz && corresponding_root_color_sz > 1) {
2064 save_to_individualize->emplace_back(original_base[i], corresponding_root_color_sz);
2074 if(compressor !=
nullptr) {
2075 return original_base[pos];
2096 int v_translate = compressor !=
nullptr? compressor->
compress(v) : v;
2109 if(compressor !=
nullptr) {
2110 for(
int i = 0; i < static_cast<int>(selection.size()); ++i) {
2112 selection[i] = compressor->
compress(selection[i]);
2116 if(compressor !=
nullptr) {
2117 for(
int i = 0; i < static_cast<int>(selection.size()); ++i) {
2118 selection[i] = compressor->
decompress(selection[i]);
2126 automorphism_compress.
reset();
2128 const int support = automorphism.
nsupp();
2129 for(
int i = 0; i < support; ++i) {
2130 const int vsupport = automorphism.
supp()[i];
2131 const int vsupportc = compressor->
compress(vsupport);
2132 const int vmapsto = automorphism.
p()[vsupport];
2133 const int vmapstoc = compressor->
compress(vmapsto);
2134 if(vsupportc >= 0) {
2149 if(compressor !=
nullptr) {
2151 return internal_schreier.
sift(w, compressed_automorphism, uniform);
2153 return internal_schreier.
sift(w, automorphism, uniform);
2166 if(compressor !=
nullptr) {
2167 return internal_schreier.
sift_random(w, compressed_automorphism, rng);
2169 return internal_schreier.
sift_random(w, automorphism, rng);
void multiply(int number)
Vertex coloring for a graph.
Set specialized for quick resets.
void initialize(int size)
dej_nodiscard bool empty() const
void set_size(const int size)
void resize(const int size)
dej_nodiscard int size() const
Fixed-size integer array, 0-initialized.
void resize(const int size)
Workspace for sparse automorphisms.
void set_support01(const bool new_support01)
void cycle_completion(markset &scratch_set)
void write_color_diff(const int *vertex_to_col, const int *col_to_vertex)
dej_nodiscard int nsupp() const
void apply_sparse(worklist &scratch_apply1, worklist &scratch_apply2, markset &scratch_apply3, const int *p, const int *support, const int nsupport, int pwr=1)
dej_nodiscard int * p() const
void apply(worklist &scratch_apply1, worklist &scratch_apply2, markset &scratch_apply3, automorphism_workspace &other, int pwr=1)
void apply(worklist &scratch_apply1, worklist &scratch_apply2, markset &scratch_apply3, const int *p, int pwr=1)
dej_nodiscard int * supp() const
int & operator[](int point) const
void resize(int new_domain_size)
void apply(automorphism_workspace &other, int pwr=1)
void write_singleton(const std::vector< int > *singletons1, const std::vector< int > *singletons2, const int pos_start, const int pos_end)
void write_single_map(const int from, const int to)
automorphism_workspace(int domain_sz=0)
Compressed Schreier structure.
bool reset(domain_compressor *new_compressor, int new_domain_size, schreier_workspace &w, std::vector< int > &new_base, std::vector< int > &new_base_sizes, const int stop, bool keep_old, std::vector< int > &global_fixed_points)
double s_compression_ratio
dej_nodiscard bool deterministic_abort_criterion() const
void determine_potential_individualization(std::vector< std::pair< int, int > > *save_to_individualize, coloring *root_coloring)
bool sift(schreier_workspace &w, automorphism_workspace &automorphism, bool uniform=false)
dej_nodiscard int base_size() const
void compute_group_size()
bool is_in_base_orbit(const int base_pos, const int v)
dej_nodiscard int get_consecutive_success() const
dej_nodiscard big_number get_group_size() const
dej_nodiscard int base_point(int pos) const
double h_min_compression_ratio
bool sift_random(schreier_workspace &w, automorphism_workspace &automorphism, random_source &rng)
dej_nodiscard bool any_abort_criterion() const
dej_nodiscard int s_densegen() const
void reset_probabilistic_criterion()
void compress_automorphism(automorphism_workspace &automorphism, automorphism_workspace &automorphism_compress)
dej_nodiscard bool probabilistic_abort_criterion() const
dej_nodiscard int finished_up_to_level() const
void set_error_bound(int error_bound)
dej_nodiscard int s_sparsegen() const
void reduce_to_unfinished(schreier_workspace &w, std::vector< int > &selection, int base_pos)
Stores a link to an automorphism.
void load(int *automorphism)
Compresses vertex set to smaller window.
double s_compression_ratio
dej_nodiscard int decompressed_domain_size() const
dej_nodiscard int compressed_domain_size() const
void determine_compression_map(coloring &c, std::vector< int > &base, int stop)
void compact_generators()
int add_generator(schreier_workspace &w, automorphism_workspace &automorphism)
void filter(schreier_workspace &w, std::vector< int > &fix_points)
generating_set(const generating_set &)=delete
dej_nodiscard int size() const
stored_automorphism * operator[](const size_t num) const
dej_nodiscard stored_automorphism * get_generator(const size_t num) const
void initialize(int new_domain_size)
generating_set & operator=(const generating_set &)=delete
void remove_generator(size_t num)
bool are_in_same_orbit(const int v1, const int v2)
int orbit_size(const int v)
void initialize(int domain_size)
void combine_orbits(const int v1, const int v2)
void add_automorphism_to_orbit(groups::automorphism_workspace &aut)
dej_nodiscard bool represents_orbit(const int v) const
int find_orbit(const int v)
orbit(const orbit &other)
bool operator==(orbit &other_orbit)
void add_automorphism_to_orbit(const int *p, const int nsupp, const int *supp)
void compute_group_size()
void sift_random(schreier_workspace &w, automorphism_workspace &automorphism, random_source &rng, int err)
const std::vector< int > & get_stabilized_generators()
bool sift_generator(schreier_workspace &w, automorphism_workspace &automorphism, int generator, bool keep_at_end=false)
dej_nodiscard int base_point(int pos) const
void determine_potential_individualization(std::vector< std::pair< int, int > > *save_to_individualize, coloring *root_coloring)
dej_nodiscard bool probabilistic_abort_criterion() const
dej_nodiscard int base_size() const
dej_nodiscard int finished_up_to_level() const
void reset_probabilistic_criterion()
int s_consecutive_success
void record_sift_result(const bool changed)
dej_nodiscard int get_fixed_orbit_size(const int base_pos)
const std::vector< int > & get_stabilizer_generators(const int base_pos)
dej_nodiscard int s_densegen() const
bool sift(schreier_workspace &w, automorphism_workspace &automorphism, bool uniform=false, bool keep_at_end=false)
bool is_in_fixed_orbit(const int base_pos, const int v)
bool sift_random(schreier_workspace &w, automorphism_workspace &automorphism, random_source &rng, bool keep_at_end=false)
dej_nodiscard int s_sparsegen() const
void set_base(schreier_workspace &w, automorphism_workspace &automorphism, random_source &rng, std::vector< int > &new_base, int err=10, bool resift_generators=false)
const std::vector< int > & get_fixed_orbit(const int base_pos)
dej_nodiscard bool is_finished(const int base_pos) const
bool reset(int new_domain_size, schreier_workspace &w, std::vector< int > &new_base, std::vector< int > &new_base_sizes, const int stop, bool keep_old, bool remove_generators, std::vector< int > &global_fixed_points)
void generate_random(schreier_workspace &w, automorphism_workspace &automorphism, random_source &rng)
void initialize(const int new_domain_size, std::vector< int > &base, std::vector< int > &base_sizes, int stop=INT32_MAX)
void load_generator(automorphism_workspace &automorphism, int generator)
void reduce_to_unfinished(schreier_workspace &w, std::vector< int > &selection, int base_pos)
dej_nodiscard bool deterministic_abort_criterion() const
API for the dejavu Schreier structure.
std::vector< int > get_stabilizer_generators(int base_pos)
const std::vector< int > & get_fixed_orbit(const int base_pos)
void get_stabilizer_orbit(int base_pos, orbit &orbit_partition)
void get_generator(int i, automorphism_workspace &automorphism)
dej_nodiscard int get_fixed_orbit_size(const int base_pos)
bool sift(int, const int *p, int nsupp, const int *supp, bool known_in_group=false)
random_schreier(int domain_size, int error=10, bool true_random=false, int seed=0)
bool is_in_fixed_orbit(const int base_pos, const int v)
bool sift(automorphism_workspace &automorphism, bool known_in_group=false)
dej_nodiscard int get_fixed_point(int pos) const
dej_nodiscard int get_number_of_generators() const
dej_nodiscard int base_size() const
void set_base(std::vector< int > &new_base, bool resift_generators=false)
Auxiliary workspace used for Schreier computations.
dense_sparse_arbiter loader
schreier_workspace(int new_domain_size)
automorphism_workspace scratch_auto
A transversal in a Schreier structure.
void set_size_upper_bound(const int new_sz_upb)
dej_nodiscard const std::vector< int > & get_generators()
bool fix_automorphism(schreier_workspace &w, generating_set &generators, automorphism_workspace &automorphism) const
dej_nodiscard bool is_finished() const
dej_nodiscard const std::vector< int > & get_fixed_orbit()
dej_nodiscard int get_fixed_point() const
void reduce_to_unfinished(schreier_workspace &w, std::vector< int > &selection)
void initialize(const int fixed_vertex, const int new_level, const int new_sz_upb)
dej_nodiscard int find_point(const int p) const
bool extend_with_automorphism(schreier_workspace &w, generating_set &generators, automorphism_workspace &automorphism)
dej_nodiscard int size() const
dej_nodiscard int get_size_upper_bound() const
Stores an automorphism in a dense or sparse manner, dynamically.
@ STORE_SPARSE
stored in minimal encoding size of automorphism
@ STORE_DENSE
stored densely, in size O(domain_size)
stored_automorphism_type get_store_type()
void store(int new_domain_size, automorphism_workspace &automorphism, markset &helper)
void load(dense_sparse_arbiter &loader, automorphism_workspace &space)
void load(automorphism_workspace &automorphism)
Random number generation.
General-purpose datastructures.