Orbiter 2022
Combinatorial Objects
action_indexing_cosets.cpp
Go to the documentation of this file.
1// action_indexing_cosets.cpp
2//
3// Anton Betten
4// July 8, 2003
5//
6// moved here from action.cpp: June 6, 2016
7
9#include "group_actions.h"
10
11using namespace std;
12
13
14namespace orbiter {
15namespace layer3_group_actions {
16namespace actions {
17
18
20 long int rank, int *Elt, int verbose_level)
21{
22 int f_v = (verbose_level >= 1);
23 long int i, base_idx = 0, base_pt, rank0, nb, len, k, elt_k;
24 int rem_int;
25 int *Elt_gk, *Elt1, *Elt2;
27 ring_theory::longinteger_object G0_order, G_order;
28 ring_theory::longinteger_object U_order, index, rem, a, b, c, d, Uk_order;
29 groups::schreier G_orb, U_orb;
31
32 if (f_v) {
33 cout << "action::coset_unrank rank=" << rank << endl;
34 cout << "in action:" << endl;
35 print_info();
36 cout << "verbose_level=" << verbose_level << endl;
37 }
38 Elt_gk = NEW_int(elt_size_in_int);
41
42 G->group_order(G_order);
43
44 U->group_order(U_order);
45
46 D.integral_division(G_order, U_order, index, rem, 0);
47
48 if (f_v) {
49 cout << "The full group has order " << G_order << endl;
50 cout << "The subgroup has order " << U_order << endl;
51 cout << "The index is " << index << endl;
52 }
53
54#if 0
55 if (!test_if_lex_least_base(verbose_level)) {
56 cout << "base is not lexleast" << endl;
57 exit(1);
58 }
59 if (f_v) {
60 cout << "the base is lexleast" << endl;
61 }
62#endif
63
64
65
66 if (f_v) {
67 G->print_transversal_lengths();
69 }
70
71 G_orb.init(this, verbose_level - 2);
72 G_orb.initialize_tables(); // not needed, already done in init
73 G_orb.init_generators(G->gens, verbose_level - 2);
74
75 // G_orb is used to determine representatives of the double cosets
76
77 U_orb.init(this, verbose_level - 2);
78 U_orb.initialize_tables(); // not needed, already done in init
79 U_orb.init_generators(U->gens, verbose_level - 2);
80
81 for (i = 0; i < base_len(); i++) {
82 if (G->get_orbit_length(i) > 1 /*U->orbit_len[i]*/) {
83 base_idx = i;
84 break;
85 }
86 }
87 if (i == base_len()) {
88 if (f_v) {
89 cout << "the groups are equal" << endl;
90 }
91 if (rank) {
92 cout << "the groups are equal but rank is not zero" << endl;
93 exit(1);
94 }
95#if 0
96 G->element_unrank_int(rank, Elt);
97 if (f_v) {
98 cout << "the element with rank " << rank << " is:" << endl;
99 element_print_quick(Elt, cout);
100 }
101#endif
102 element_one(Elt, 0);
103 goto done;
104 }
105 base_pt = base_i(base_idx);
106 if (f_v) {
107 cout << "base_idx = " << base_idx << endl;
108 cout << "base_pt = " << base_pt << endl;
109 cout << "G->orbit_len[base_idx]=" << G->get_orbit_length(base_idx) << endl;
110 cout << "U->orbit_len[base_idx]=" << U->get_orbit_length(base_idx) << endl;
111 }
112
113 D.integral_division_by_int(G_order, G->get_orbit_length(base_idx), G0_order, rem_int);
114
115 if (f_v) {
116 cout << "G0_order=" << G0_order << endl;
117 }
118
119 int *orbit;
120 int orbit_len;
121
122 orbit_len = G->get_orbit_length(base_idx);
123
124
125 // orbit is the G-orbit of base_pt
126
127 orbit = NEW_int(orbit_len);
128 for (int t = 0; t < orbit_len; t++) {
129 orbit[t] = G->get_orbit(base_idx, t);
130 }
131 //int_vec_copy(G->orbit[base_idx], orbit, orbit_len);
132 Sorting.int_vec_heapsort(orbit, orbit_len);
133
134 if (f_v) {
135 cout << "orbit of length " << orbit_len << ":";
136 Int_vec_print(cout, orbit, orbit_len);
137 cout << endl;
138 }
139
140 int nb_U_orbits_on_subset;
141
142 G_orb.compute_point_orbit(base_pt, 0 /* verbose_level - 2*/);
143 if (f_v) {
144 cout << "orbit of base_pt under G has length " << G_orb.orbit_len[0] << endl;
145 }
146
147 if (G_orb.orbit_len[0] != orbit_len) {
148 cout << "action::coset_unrank G_orb.orbit_len[0] != orbit_len" << endl;
149 exit(1);
150 }
151
152 U_orb.orbits_on_invariant_subset_fast(orbit_len, orbit, verbose_level - 2);
153 nb_U_orbits_on_subset = U_orb.nb_orbits;
154 if (f_v) {
155 cout << "U-orbits: ";
157 cout << endl;
158 cout << "in order:" << endl;
159 U_orb.print_orbit_lengths(cout);
160 cout << endl;
161 U_orb.print_and_list_orbits(cout);
162 }
163
164 rank0 = 0;
165 for (k = 0; k < nb_U_orbits_on_subset; k++) {
166 len = U_orb.orbit_len[k];
167 b.create(len, __FILE__, __LINE__);
168 D.mult(G0_order, b, c);
169 D.integral_division(c, U_order, d, rem, 0);
170 if (!rem.is_zero()) {
171 cout << "action::coset_unrank: remainder is not zero, "
172 "something is wrong" << endl;
173 exit(1);
174 }
175 nb = d.as_int();
176
177 // nb = length of k-th U-orbit * |G0| / |U|
178
179 elt_k = U_orb.orbit[U_orb.orbit_first[k]];
180 if (f_v) {
181 cout << "double coset k=" << k << " elt_k=" << elt_k
182 << " nb=" << nb << endl;
183 }
184 if (rank0 + nb > rank) {
185 if (f_v) {
186 cout << "we are in double coset " << k << endl;
187 cout << "reduced rank is " << rank - rank0 << endl;
188 }
189
190
191 if (f_v) {
192 G_orb.print_and_list_orbits(cout);
193 }
194 //G->coset_rep(base_idx, G->orbit_inv[base_idx][elt_k], 0/* verbose_level*/);
195 G_orb.coset_rep(G_orb.orbit_inv[elt_k], 0 /* verbose_level */);
196 element_move(G_orb.cosetrep, Elt_gk, 0);
197
198 if (f_v) {
199 cout << "gk (before)=" << endl;
200 element_print_quick(Elt_gk, cout);
201 element_print_as_permutation(Elt_gk, cout);
202 }
203
204 minimize_base_images(base_idx + 1, G, Elt_gk, verbose_level);
205 if (f_v) {
206 cout << "gk (after)=" << endl;
207 element_print_quick(Elt_gk, cout);
208 element_print_as_permutation(Elt_gk, cout);
209 }
210
211 if (element_image_of(base_pt, Elt_gk, 0) != elt_k) {
212 cout << "image of base point under gk is not as expected!" << endl;
213 cout << "base_pt=" << base_pt << endl;
214 cout << "elt_k=" << elt_k << endl;
215 cout << "image=" << element_image_of(base_pt, Elt_gk, 0) << endl;
216 exit(1);
217 }
218 groups::sims *Gk = NULL;
219 groups::sims *Uk = NULL;
220
221 G_orb.initialize_tables();
222 G_orb.init_generators(G->gens, verbose_level - 2);
223 // this is redundant as the generators for G are already in G_orb
224 // in fact, it might be a memory leak
225
226 G_orb.compute_point_orbit(elt_k, 0 /* verbose_level - 2*/);
227 // we recompute the orbit, but this time with elt_k as
228 // orbit representative, so that we can compute
229 // the stabilizer of elt_k in G
230
231 if (f_v) {
232 cout << "orbit of elt_k under G has length " << G_orb.orbit_len[0] << endl;
233 }
234 G_orb.point_stabilizer(this, G_order, Gk, 0, 0/*verbose_level - 2*/);
235
236 //D.integral_division_by_int(U_order, len, Uk_order, rem_int);
237 //cout << "expecting stabilizer of " << k << "-th point in U to have order " << Uk_order << endl;
238 U_orb.point_stabilizer(this, U_order, Uk, k, 0/*verbose_level - 2*/);
239
240 if (f_v) {
241 cout << "Gk transversal lengths:" << endl;
243 cout << "Uk transversal lengths:" << endl;
245 }
246
247 if (f_v) {
248 cout << "recursing" << endl;
249 }
250 coset_unrank(Gk, Uk, rank - rank0, Elt1, verbose_level);
251 if (f_v) {
252 cout << "recursion done" << endl;
253 cout << "Elt1=" << endl;
255
256 cout << "Elt_gk=" << endl;
257 element_print_quick(Elt_gk, cout);
258
259
260
261 }
262
263 element_mult(Elt_gk, Elt1, Elt2, 0);
264 if (f_v) {
265 cout << "Elt_gk * Elt1=" << endl;
267 }
268 element_move(Elt2, Elt, 0);
269
270 delete Gk;
271 delete Uk;
272 goto done2;
273 }
274 rank0 += nb;
275 }
276
277done2:
278 FREE_int(orbit);
279
280done:
281
282 FREE_int(Elt_gk);
283 FREE_int(Elt1);
284 FREE_int(Elt2);
285
286}
287
288long int action::coset_rank(groups::sims *G, groups::sims *U, int *Elt, int verbose_level)
289{
290 int f_v = (verbose_level >= 1);
291 long int rank = 0;
292 long int i, base_idx = 0, base_pt, rank1, nb, len, k, kk, elt_k, im;
293 int rem_int;
294 int *Elt_gk, *Elt1, *Elt2, *Elt3, *Elt_u;
296 ring_theory::longinteger_object G0_order, G_order, U_order, index, rem, a, b, c, d, Uk_order;
297 groups::schreier G_orb, U_orb;
299
300 if (f_v) {
301 cout << "##################################" << endl;
302 cout << "action::coset_rank element" << endl;
303 element_print_quick(Elt, cout);
304 element_print_base_images(Elt, cout);
305 cout << endl;
306 cout << "in action:" << endl;
307 print_info();
308 }
309 Elt_gk = NEW_int(elt_size_in_int);
313 Elt_u = NEW_int(elt_size_in_int);
314
315 G->group_order(G_order);
316
317 U->group_order(U_order);
318
319 D.integral_division(G_order, U_order, index, rem, 0);
320
321 if (f_v) {
322 cout << "The full group has order " << G_order << endl;
323 cout << "The subgroup has order " << U_order << endl;
324 cout << "The index is " << index << endl;
325 }
326
327#if 0
328 if (!test_if_lex_least_base(0/*verbose_level*/)) {
329 cout << "base is not lexleast" << endl;
330 exit(1);
331 }
332#endif
333
334 if (f_v) {
335 cout << "the base is lexleast" << endl;
336 }
337
338 if (f_v) {
339 G->print_transversal_lengths();
341 }
342
343 G_orb.init(this, verbose_level - 2);
344 G_orb.initialize_tables();
345 G_orb.init_generators(G->gens, verbose_level - 2);
346
347 U_orb.init(this, verbose_level - 2);
348 U_orb.initialize_tables();
349 U_orb.init_generators(U->gens, verbose_level - 2);
350
351 for (i = 0; i < base_len(); i++) {
352 if (G->get_orbit_length(i) > 1) {
353 base_idx = i;
354 break;
355 }
356 }
357 if (i == base_len()) {
358 if (f_v) {
359 cout << "the groups are equal" << endl;
360 }
361#if 0
362 G->element_unrank_int(rank, Elt);
363 if (f_v) {
364 cout << "the element with rank " << rank << " is:" << endl;
365 element_print_quick(Elt, cout);
366 }
367#endif
368 //element_one(Elt, 0);
369 goto done;
370 }
371 base_pt = base_i(base_idx);
372 if (f_v) {
373 cout << "base_idx = " << base_idx << endl;
374 cout << "base_pt = " << base_pt << endl;
375 cout << "G->orbit_len[base_idx]=" << G->get_orbit_length(base_idx) << endl;
376 cout << "U->orbit_len[base_idx]=" << U->get_orbit_length(base_idx) << endl;
377 }
378
379 D.integral_division_by_int(G_order, G->get_orbit_length(base_idx), G0_order, rem_int);
380
381 if (f_v) {
382 cout << "G0_order=" << G0_order << endl;
383 }
384
385 int *orbit;
386 int orbit_len;
387
388 orbit_len = G->get_orbit_length(base_idx);
389
390
391 orbit = NEW_int(orbit_len);
392 for (int t = 0; t < orbit_len; t++) {
393 orbit[t] = G->get_orbit(base_idx, t);
394 }
395 //int_vec_copy(G->orbit[base_idx], orbit, orbit_len);
396 Sorting.int_vec_heapsort(orbit, orbit_len);
397
398 if (f_v) {
399 cout << "G-orbit of length " << orbit_len << ":";
400 Int_vec_print(cout, orbit, orbit_len);
401 cout << endl;
402 }
403
404 //int nb_U_orbits_on_subset;
405
406 G_orb.compute_point_orbit(base_pt, 0 /* verbose_level - 2*/);
407 if (f_v) {
408 cout << "orbit of base_pt under G has length " << G_orb.orbit_len[0] << endl;
409 cout << "G-orbits: ";
410 G_orb.print_and_list_orbits(cout);
411 }
412
413 U_orb.orbits_on_invariant_subset_fast(orbit_len, orbit, verbose_level - 2);
414 //nb_U_orbits_on_subset = U_orb.nb_orbits;
415 if (f_v) {
416 cout << "U-orbits: ";
418 cout << endl;
419 cout << "in order:" << endl;
420 U_orb.print_orbit_lengths(cout);
421 cout << endl;
422 U_orb.print_and_list_orbits(cout);
423 }
424
425 element_move(Elt, Elt1, 0);
426 im = element_image_of(base_pt, Elt1, 0);
427 if (f_v) {
428 cout << "image of base point " << base_pt << " is " << im << endl;
429 }
430 k = U_orb.orbit_number(im); //U_orb.orbit_no[U_orb.orbit_inv[im]];
431 if (f_v) {
432 cout << "Which lies in orbit " << k << endl;
433 }
434 for (kk = 0; kk < k; kk++) {
435 len = U_orb.orbit_len[kk];
436 b.create(len, __FILE__, __LINE__);
437 D.mult(G0_order, b, c);
438 D.integral_division(c, U_order, d, rem, 0);
439 if (!rem.is_zero()) {
440 cout << "action::coset_rank: remainder is not zero, something is wrong" << endl;
441 exit(1);
442 }
443 nb = d.as_int();
444 rank += nb;
445 }
446 if (f_v) {
447 cout << "after going through the previous double cosets, rank=" << rank << endl;
448 }
449 len = U_orb.orbit_len[k];
450 b.create(len, __FILE__, __LINE__);
451 D.mult(G0_order, b, c);
452 D.integral_division(c, U_order, d, rem, 0);
453 if (!rem.is_zero()) {
454 cout << "action::coset_rank: remainder is not zero, something is wrong" << endl;
455 exit(1);
456 }
457 nb = d.as_int();
458 elt_k = U_orb.orbit[U_orb.orbit_first[k]];
459 if (f_v) {
460 cout << "elt_k=" << elt_k << endl;
461 }
462
463
464 G_orb.coset_rep(G_orb.orbit_inv[elt_k], 0 /* verbose_level */);
465 element_move(G_orb.cosetrep, Elt_gk, 0);
466
467 if (element_image_of(base_pt, Elt_gk, 0) != elt_k) {
468 cout << "image of base point under gk is not as expected!" << endl;
469 cout << "base_pt=" << base_pt << endl;
470 cout << "elt_k=" << elt_k << endl;
471 cout << "image=" << element_image_of(base_pt, Elt_gk, 0) << endl;
472 cout << "gk (before minimizing base images)=" << endl;
473 element_print_quick(Elt_gk, cout);
474 element_print_base_images(Elt_gk, cout);
475 cout << endl;
476 element_print_as_permutation(Elt_gk, cout);
477 exit(1);
478 }
479 if (f_v) {
480 cout << "gk (before minimizing base images)=" << endl;
481 element_print_quick(Elt_gk, cout);
482 //element_print_base_images(Elt_gk, cout);
483 //cout << endl;
484 element_print_as_permutation(Elt_gk, cout);
485 }
486
487 minimize_base_images(base_idx + 1, G, Elt_gk, 0/*verbose_level*/);
488 if (f_v) {
489 cout << "gk (after minimizing base images)=" << endl;
490 element_print_quick(Elt_gk, cout);
491 //element_print_base_images(Elt_gk, cout);
492 //cout << endl;
493 element_print_as_permutation(Elt_gk, cout);
494 }
495
496 if (element_image_of(base_pt, Elt_gk, 0) != elt_k) {
497 cout << "image of base point under gk is not as expected!" << endl;
498 cout << "base_pt=" << base_pt << endl;
499 cout << "elt_k=" << elt_k << endl;
500 cout << "image=" << element_image_of(base_pt, Elt_gk, 0) << endl;
501 cout << "gk (after minimizing base images)=" << endl;
502 element_print_quick(Elt_gk, cout);
503 element_print_as_permutation(Elt_gk, cout);
504 exit(1);
505 }
506 {
507 groups::sims *Gk = NULL;
508 groups::sims *Uk = NULL;
509
510 G_orb.initialize_tables();
511 G_orb.init_generators(G->gens, verbose_level - 2);
512 G_orb.compute_point_orbit(elt_k, 0 /* verbose_level - 2*/);
513
514 if (f_v) {
515 cout << "orbit of elt_k under G has length " << G_orb.orbit_len[0] << endl;
516 }
517 G_orb.point_stabilizer(this, G_order, Gk, 0, 0/*verbose_level - 2*/);
518
519 //D.integral_division_by_int(U_order, len, Uk_order, rem_int);
520 //cout << "expecting stabilizer of " << k << "-th point in U to have order " << Uk_order << endl;
521 U_orb.point_stabilizer(this, U_order, Uk, k, 0/*verbose_level - 2*/);
522
523 if (f_v) {
524 cout << "Gk transversal lengths:" << endl;
526 cout << "Uk transversal lengths:" << endl;
528 }
529
530 if (f_v) {
531 cout << "Elt_gk=" << endl;
532 element_print_quick(Elt_gk, cout);
533 }
534 element_invert(Elt_gk, Elt3, 0);
535 if (f_v) {
536 cout << "we are now going to divide off Elt_gk from the left." << endl;
537 cout << "Elt_gk^-1=" << endl;
539 }
540
542 if (f_v) {
543 cout << "Elt_gk^-1 * Elt =" << endl;
545 //element_print_base_images(Elt2, cout);
546 //cout << endl;
547 }
548
549
550 int im;
551
552 im = element_image_of(elt_k, Elt2, 0);
553 if (im != elt_k) {
554 if (f_v) {
555 cout << "image of elt_k = " << elt_k << " is " << im << endl;
556 cout << "we are now dividing off an element of U "
557 "from the right so that elt_k is fixed" << endl;
558 }
559
560 U_orb.coset_rep_inv(U_orb.orbit_inv[im], 0 /* verbose_level */);
561 element_move(U_orb.cosetrep, Elt_u, 0);
562 if (f_v) {
563 cout << "Elt_u =" << endl;
564 element_print_quick(Elt_u, cout);
565 cout << "moves " << im << " to " << elt_k << endl;
566 }
567 if (element_image_of(im, Elt_u, 0) != elt_k) {
568 cout << "image of " << im << " is "
569 << element_image_of(im, Elt_u, 0)
570 << " but not " << elt_k << " fatal" << endl;
571 exit(1);
572 }
573 element_mult(Elt2, Elt_u, Elt3, 0);
575 if (f_v) {
576 cout << "after multiplying Elt_u:" << endl;
578 }
579 }
580
581 if (f_v) {
582 cout << "recursing" << endl;
583 }
584
585 rank1 = coset_rank(Gk, Uk, Elt2, verbose_level);
586 if (f_v) {
587 cout << "recursion done, rank1=" << rank1 << endl;
588 }
589 rank += rank1;
590 if (f_v) {
591 cout << "rank=" << rank << endl;
592 }
593
594 delete Gk;
595 delete Uk;
596 }
597
598 FREE_int(orbit);
599
600done:
601
602 FREE_int(Elt_gk);
603 FREE_int(Elt1);
604 FREE_int(Elt2);
605 FREE_int(Elt3);
606 FREE_int(Elt_u);
607 return rank;
608}
609
610}}}
611
612
a collection of functions related to sorted vectors
domain to compute with objects of type longinteger
Definition: ring_theory.h:240
void integral_division_by_int(longinteger_object &a, int b, longinteger_object &q, int &r)
void mult(longinteger_object &a, longinteger_object &b, longinteger_object &c)
void integral_division(longinteger_object &a, longinteger_object &b, longinteger_object &q, longinteger_object &r, int verbose_level)
a class to represent arbitrary precision integers
Definition: ring_theory.h:366
void create(long int i, const char *file, int line)
void coset_unrank(groups::sims *G, groups::sims *U, long int rank, int *Elt, int verbose_level)
void element_print_quick(void *elt, std::ostream &ost)
Definition: action_cb.cpp:353
void element_mult(void *a, void *b, void *ab, int verbose_level)
Definition: action_cb.cpp:315
void element_invert(void *a, void *av, int verbose_level)
Definition: action_cb.cpp:322
void element_one(void *elt, int verbose_level)
Definition: action_cb.cpp:224
long int coset_rank(groups::sims *G, groups::sims *U, int *Elt, int verbose_level)
void element_move(void *a, void *b, int verbose_level)
Definition: action_cb.cpp:335
void minimize_base_images(int level, groups::sims *S, int *Elt, int verbose_level)
Definition: action.cpp:2303
void element_print_as_permutation(void *elt, std::ostream &ost)
Definition: action_cb.cpp:421
long int element_image_of(long int a, void *elt, int verbose_level)
Definition: action_cb.cpp:198
Schreier trees for orbits of groups on points.
Definition: groups.h:839
void orbits_on_invariant_subset_fast(int len, int *subset, int verbose_level)
Definition: schreier.cpp:1931
void init_generators(data_structures_groups::vector_ge &generators, int verbose_level)
Definition: schreier.cpp:373
void compute_point_orbit(int pt, int verbose_level)
Definition: schreier.cpp:1256
void print_orbit_length_distribution(std::ostream &ost)
void point_stabilizer(actions::action *default_action, ring_theory::longinteger_object &go, groups::sims *&Stab, int orbit_no, int verbose_level)
Definition: schreier.cpp:2388
void init(actions::action *A, int verbose_level)
Definition: schreier.cpp:308
void coset_rep_inv(int j, int verbose_level)
Definition: schreier.cpp:864
void coset_rep(int j, int verbose_level)
Definition: schreier.cpp:787
a permutation group represented via a stabilizer chain
Definition: groups.h:1273
void group_order(ring_theory::longinteger_object &go)
Definition: sims.cpp:951
data_structures_groups::vector_ge gens
Definition: groups.h:1280
#define FREE_int(p)
Definition: foundations.h:640
#define NEW_int(n)
Definition: foundations.h:625
#define Int_vec_print(A, B, C)
Definition: foundations.h:685
the orbiter library for the classification of combinatorial objects