Orbiter 2022
Combinatorial Objects
character_table_burnside.cpp
Go to the documentation of this file.
1/*
2 * character_table_burnside.cpp
3 *
4 * Created on: Nov 9, 2019
5 * Author: anton
6 *
7 * originally started on February 26, 2015
8 *
9 */
10
11
12
13
14#include "orbiter.h"
15
16using namespace std;
17using namespace orbiter::layer1_foundations;
18
19namespace orbiter {
20namespace layer5_applications {
21namespace apps_algebra {
22
23
24void character_table_burnside::do_it(int n, int verbose_level)
25{
26 int f_v = (verbose_level >= 1);
27
28 if (f_v) {
29 cout << "character_table_burnside::do_it" << endl;
30 }
31
33
35 D->init_integer_fractions(verbose_level);
36
37
40 int goi;
41 int *Elt;
42 int i, j;
43 int f_no_base = FALSE;
44
46 A->init_symmetric_group(n, f_no_base, verbose_level);
47 A->group_order(go);
48
49 goi = go.as_int();
50 cout << "Created group Sym(" << n << ") of size " << goi << endl;
51
52 Elt = NEW_int(A->elt_size_in_int);
53
54 groups::sims *S;
55
56 S = A->Sims;
57
58 for (i = 0; i < goi; i++) {
59 S->element_unrank_lint(i, Elt);
60 cout << "element " << i << " is ";
61 A->element_print_quick(Elt, cout);
62 cout << endl;
63 }
64
65 actions::action *Aconj;
66
68
69 cout << "Creating action by conjugation" << endl;
70
72 S, FALSE /* f_ownership */, FALSE /* f_basis */, verbose_level);
73
74 cout << "Creating action by conjugation done" << endl;
75
77
78 ABC = Aconj->G.ABC;
79
82
84
85 Sch->init(Aconj, verbose_level - 2);
86
87
89
90 SG->init_from_sims(S, 0);
91
92#if 0
94 cout << "action does not have strong generators" << endl;
95 exit(1);
96 }
97#endif
98
99 Sch->init_generators(*SG->gens, verbose_level - 2);
100
101 cout << "Computing conjugacy classes:" << endl;
102 Sch->compute_all_point_orbits(verbose_level);
103
104
105 int nb_classes;
106 int *class_size;
107
108 nb_classes = Sch->nb_orbits;
109
110 class_size = NEW_int(nb_classes);
111
112 for (i = 0; i < nb_classes; i++) {
113 class_size[i] = Sch->orbit_len[i];
114 }
115 cout << "class sizes : ";
116 Int_vec_print(cout, class_size, nb_classes);
117 cout << endl;
118
119
120
121
122 int *N;
123 int r, r0;
124
125
127 ABC,
128 Sch, nb_classes, N, verbose_level);
129
130
131 for (r = 0; r < nb_classes; r++) {
132 cout << "N_" << r << ":" << endl;
133 Int_matrix_print(N + r * nb_classes * nb_classes, nb_classes, nb_classes);
134 cout << endl;
135 }
136
137
138 r0 = compute_r0(N, nb_classes, verbose_level);
139
140
141 if (r0 == -1) {
142 cout << "Did not find a matrix with the right number "
143 "of distinct eigenvalues" << endl;
144 exit(1);
145 }
146
147
148 cout << "r0=" << r0 << endl;
149
150 int *N0;
151
152 N0 = N + r0 * nb_classes * nb_classes;
153
154
155
156
157 int *Lambda;
158 int nb_lambda;
159 int *Mu;
160 int *Mu_mult;
161 int nb_mu;
162
163 cout << "N_" << r0 << ":" << endl;
164
165 integral_eigenvalues(N0, nb_classes,
166 Lambda,
167 nb_lambda,
168 Mu,
169 Mu_mult,
170 nb_mu,
171 0 /*verbose_level*/);
172
173 cout << "Has " << nb_mu << " distinct eigenvalues" << endl;
174
175
176 cout << "We found " << nb_lambda << " integer roots, they are: " << endl;
177 Int_vec_print(cout, Lambda, nb_lambda);
178 cout << endl;
179 cout << "We found " << nb_mu << " distinct integer roots, they are: " << endl;
180 for (i = 0; i < nb_mu; i++) {
181 cout << Mu[i] << " with multiplicity " << Mu_mult[i] << endl;
182 }
183
184 int *Omega;
185
186
187 compute_omega(D, N0, nb_classes, Mu, nb_mu, Omega, verbose_level);
188
189
190
191 cout << "Omega:" << endl;
192 D->print_matrix(Omega, nb_classes, nb_classes);
193 //double_matrix_print(Omega, nb_classes, nb_classes);
194
195
196
197
198 int *character_degree;
199
200
201 compute_character_degrees(D, goi, nb_classes, Omega, class_size,
202 character_degree, verbose_level);
203
204
205 cout << "character degrees : ";
206 Int_vec_print(cout, character_degree, nb_classes);
207 cout << endl;
208
209
210 int *character_table;
211
212
213 compute_character_table(D, nb_classes, Omega,
214 character_degree, class_size,
215 character_table, verbose_level);
216
217
218
219
220
221 cout << "character table:" << endl;
222 Int_matrix_print(character_table, nb_classes, nb_classes);
223
224 int f_special = TRUE;
225 int **Gens;
226 int nb_gens;
227 int t_max;
228 int *Distribution;
229
230 t_max = character_degree[0];
231 for (i = 0; i < nb_classes; i++) {
232 if (character_degree[i] > t_max) {
233 t_max = character_degree[i];
234 }
235 }
236
237 cout << "t_max=" << t_max << endl;
238
239 cout << "creating generators:" << endl;
240 create_generators(A, n, Gens, nb_gens, f_special, verbose_level);
241
242
244 Sch, nb_classes,
245 Gens,nb_gens, t_max, Distribution, verbose_level);
246
247
248 cout << "Distribution table:" << endl;
249 Int_matrix_print(Distribution + nb_classes, t_max, nb_classes);
250
251
252 for (i = 0; i < nb_classes; i++) {
253
254 cout << "character " << i << " / " << nb_classes << ":" << endl;
255 Int_vec_print(cout, character_table + i * nb_classes, nb_classes);
256 cout << endl;
257
258
259 int *S, a, t;
260
261 S = NEW_int(t_max + 1);
262 Int_vec_zero(S, t_max + 1);
263
264 for (t = 0; t <= t_max; t++) {
265 S[t] = 0;
266 for (j = 0; j < nb_classes; j++) {
267 a = Distribution[t * nb_classes + j];
268 if (a == 0) {
269 continue;
270 }
271 S[t] += a * character_table[i * nb_classes + j];
272 }
273 }
274 cout << "S=";
275 Int_vec_print(cout, S + 1, t_max);
276 cout << endl;
277
278
280
281 int /*n,*/ deg;
282
283 //n = character_degree[i];
284
285 create_matrix(M, i, S, nb_classes,
286 character_degree, class_size,
287 verbose_level);
288
289 cout << "M=" << endl;
290 cout << M << endl;
291
292 unipoly p;
293
294
295 M.determinant(p, 0 /*verbose_level*/);
296 if (f_v) {
297 cout << "determinant:" << p << endl;
298 }
299
300 deg = p.degree();
301 if (f_v) {
302 cout << "has degree " << deg << endl;
303 }
304
305
306
307
308 FREE_int(S);
309 }
310
311
312 cout << "character table:" << endl;
313 Int_matrix_print(character_table, nb_classes, nb_classes);
314
315
317
318 L.print_integer_matrix_tex(cout, character_table, nb_classes, nb_classes);
319
320
321
322
323 FREE_int(Distribution);
324 for (i = 0; i < nb_gens; i++) {
325 FREE_int(Gens[i]);
326 }
327 FREE_pint(Gens);
328
329
330 FREE_int(character_table);
331 FREE_int(character_degree);
332
333 FREE_int(Omega);
334
335 FREE_int(Lambda);
336 FREE_int(Mu);
337 FREE_int(Mu_mult);
338
339
340 FREE_int(N);
341 FREE_OBJECT(SG);
342 FREE_OBJECT(Sch);
343 FREE_OBJECT(Aconj);
344
345 FREE_int(Elt);
346 FREE_OBJECT(A);
347 FREE_OBJECT(D);
348 if (f_v) {
349 cout << "character_table_burnside::do_it" << endl;
350 }
351}
352
353void character_table_burnside::create_matrix(discreta_matrix &M, int i, int *S, int nb_classes,
354 int *character_degree, int *class_size,
355 int verbose_level)
356{
357 int f_v = (verbose_level >= 1);
358 int n, ii, j;
359
360
361 if (f_v) {
362 cout << "character_table_burnside::create_matrix" << endl;
363 }
364 n = character_degree[i];
365 if (f_v) {
366 cout << "n=" << n << endl;
367 }
368 M.m_mn_n(n + 1, n + 1);
369
371
372 for (j = 0; j <= n; j++) {
373
374 {
375 unipoly p;
376
377 p.x_to_the_i(j);
378 M.s_ij(0, n - j) = p;
379 }
380
381 }
382 for (ii = 1; ii <= n; ii++) {
383
384 cout << "ii=" << ii << endl;
385
386 for (j = 0; j <= ii; j++) {
387 unipoly p;
388
389 p.one();
390 if (j == 0) {
391 p.m_ii(0, ii);
392 }
393 else {
394 p.m_ii(0, S[j]);
395 }
396 cout << "j=" << j << " p=" << p << endl;
397
398 M.s_ij(ii, ii - j) = p;
399 }
400 }
401
402 if (f_v) {
403 cout << "character_table_burnside::create_matrix done" << endl;
404 }
405}
406
407
409 algebra::a_domain *D, int nb_classes, int *Omega,
410 int *character_degree, int *class_size,
411 int *&character_table, int verbose_level)
412{
413 int f_v = (verbose_level >= 1);
414 int f_vv = (verbose_level >= 3);
415 int i, j, w;
416
417 if (f_v) {
418 cout << "character_table_burnside::compute_character_table" << endl;
419 }
420
421 character_table = NEW_int(nb_classes * nb_classes);
422
423 for (i = 0; i < nb_classes; i++) {
424
425 for (j = 0; j < nb_classes; j++) {
426
427 if (f_vv) {
428 cout << "i=" << i << " j=" << j
429 << " character_degree[i]=" << character_degree[i]
430 << " omega_ij="
431 << D->as_int(D->offset(Omega, j * nb_classes + i), 0)
432 << " class_size[j]=" << class_size[j] << endl;
433 }
434
435 w = character_degree[i] * D->as_int(D->offset(Omega, j * nb_classes + i), 0);
436 if (w % class_size[j]) {
437 cout << "class size does not divide w" << endl;
438 exit(1);
439 }
440 character_table[i * nb_classes + j] = w / class_size[j];
441 }
442 }
443
444
445 if (f_v) {
446 cout << "character_table_burnside::compute_character_table done" << endl;
447 }
448}
449
452 int goi, int nb_classes, int *Omega, int *class_size,
453 int *&character_degree, int verbose_level)
454{
455 int f_v = (verbose_level >= 1);
456 int f_vv = (verbose_level >= 2);
457 int i, r, d, f;
458 int *A, *B, *C, *Cv, *G, *S, *Sv, *E, *F;
459
460 if (f_v) {
461 cout << "character_table_burnside::compute_character_degrees" << endl;
462 }
463
464 character_degree = NEW_int(nb_classes);
474
475 for (i = 0; i < nb_classes; i++) {
476
477
478 D->make_zero(S, 0);
479
480 for (r = 0; r < nb_classes; r++) {
481 D->copy(D->offset(Omega, r * nb_classes + i), A, 0);
482
483 D->mult(A, A, B, 0);
484
485
486 D->make_integer(C, class_size[r], 0);
487 D->inverse(C, Cv, 0);
488
489
490 D->mult(B, Cv, E, 0);
491
492 D->add_apply(S, E, 0);
493 }
494
495 D->inverse(S, Sv, 0);
496
497 D->make_integer(G, goi, 0);
498 D->mult(G, Sv, F, 0);
499
500
501 f = D->as_int(F, 0);
502 d = sqrt(f);
503
504 if (d * d != f) {
505 cout << "f is not a perfect square" << endl;
506 exit(1);
507 }
508
509 if (f_vv) {
510 cout << "i=" << i << " d=" << d << endl;
511 }
512
513 character_degree[i] = d;
514 }
515 FREE_int(A);
516 FREE_int(B);
517 FREE_int(C);
518 FREE_int(Cv);
519 FREE_int(G);
520 FREE_int(S);
521 FREE_int(Sv);
522 FREE_int(E);
523 FREE_int(F);
524 if (f_v) {
525 cout << "character_table_burnside::compute_character_degrees done" << endl;
526 }
527}
528
530 algebra::a_domain *D, int *N0, int nb_classes,
531 int *Mu, int nb_mu, int *&Omega, int verbose_level)
532{
533 int f_v = (verbose_level >= 1);
534 int f_vv = (verbose_level >= 2);
535 int *M;
536 int *base_cols;
537 int h, x, rk, i, j, a;
538
539 if (f_v) {
540 cout << "character_table_burnside::compute_omega" << endl;
541 }
542 Omega = NEW_int(nb_classes * nb_classes * D->size_of_instance_in_int);
543 M = NEW_int(nb_classes * nb_classes * D->size_of_instance_in_int);
544 base_cols = NEW_int(nb_classes);
545
546 for (h = 0; h < nb_mu; h++) {
547
548 x = Mu[h];
549 if (f_v) {
550 cout << "eigenvalue " << h << " / " << nb_mu
551 << " is " << x << ":" << endl;
552 }
553 for (i = 0; i < nb_classes; i++) {
554 for (j = 0; j < nb_classes; j++) {
555 a = N0[i * nb_classes + j];
556 if (i == j) {
557 a -= x;
558 }
559 D->make_integer(D->offset(M, i * nb_classes + j), a, 0);
560 }
561 }
562 if (f_vv) {
563 cout << "before get_image_and_kernel:" << endl;
564 D->print_matrix(M, nb_classes, nb_classes);
565 //double_matrix_print(M, nb_classes, nb_classes);
566 }
567
568 D->get_image_and_kernel(M, nb_classes, rk, verbose_level);
569
570 //rk = double_Gauss(M, nb_classes, nb_classes,
571 //base_cols, 0 /*verbose_level */);
572
573 if (f_vv) {
574 cout << "after get_image_and_kernel:" << endl;
575 //double_matrix_print(M, nb_classes, nb_classes);
576 D->print_matrix(M, nb_classes, nb_classes);
577
578 cout << "after get_image_and_kernel, rk=" << rk << endl;
579 }
580
581 if (rk != nb_classes - 1) {
582 cout << "rk != nb_classes - 1" << endl;
583 exit(1);
584 }
585
586 int *b, *c;
587
590 D->copy(D->offset(M, (nb_classes - 1) * nb_classes), b, 0);
591 D->inverse(b, c, 0);
592
593 cout << "c=";
594 D->print(c);
595 cout << endl;
596
597 for (i = 0; i < nb_classes; i++) {
598 D->mult_apply(D->offset(M,
599 (nb_classes - 1) * nb_classes + i), c, 0);
600 }
601
602 if (f_vv) {
603 cout << "after rescaling:" << endl;
604 D->print_matrix(M, nb_classes, nb_classes);
605 }
606 for (i = 0; i < nb_classes; i++) {
607 D->copy(D->offset(M, (nb_classes - 1) * nb_classes + i),
608 D->offset(Omega, i * nb_classes + h), 0);
609 }
610 FREE_int(b);
611 FREE_int(c);
612
613
614
615
616 }
617
618
619 if (f_vv) {
620 cout << "Omega:" << endl;
621 D->print_matrix(Omega, nb_classes, nb_classes);
622 }
623
624 FREE_int(M);
625 FREE_int(base_cols);
626 if (f_v) {
627 cout << "character_table_burnside::compute_omega done" << endl;
628 }
629}
630
631int character_table_burnside::compute_r0(int *N, int nb_classes, int verbose_level)
632{
633 int f_v = (verbose_level >= 1);
634 int f_vv = (verbose_level >= 3);
635 int r, r0, i;
636
637 if (f_v) {
638 cout << "character_table_burnside::compute_r0" << endl;
639 }
640 r0 = -1;
641
642 for (r = 0; r < nb_classes; r++) {
643
644 int *Lambda;
645 int nb_lambda;
646 int *Mu;
647 int *Mu_mult;
648 int nb_mu;
649
650 if (f_vv) {
651 cout << "N_" << r << ":" << endl;
652 }
653
654 integral_eigenvalues(N + r * nb_classes * nb_classes, nb_classes,
655 Lambda,
656 nb_lambda,
657 Mu,
658 Mu_mult,
659 nb_mu,
660 0 /*verbose_level*/);
661
662
663 if (f_vv) {
664 cout << "Has " << nb_mu << " distinct eigenvalues" << endl;
665
666
667 cout << "We found " << nb_lambda
668 << " integer roots, they are: " << endl;
669 Int_vec_print(cout, Lambda, nb_lambda);
670 cout << endl;
671 cout << "We found " << nb_mu
672 << " distinct integer roots, they are: " << endl;
673 for (i = 0; i < nb_mu; i++) {
674 cout << Mu[i] << " with multiplicity " << Mu_mult[i] << endl;
675 }
676 }
677
678 if (nb_mu == nb_classes) {
679 r0 = r;
680 }
681
682
683 FREE_int(Lambda);
684 FREE_int(Mu);
685 FREE_int(Mu_mult);
686
687
688 }
689 if (f_v) {
690 cout << "character_table_burnside::compute_r0 done" << endl;
691 }
692 return r0;
693}
694
698 groups::schreier *Sch, int nb_classes, int *&N, int verbose_level)
699{
700 int f_v = (verbose_level >= 1);
701 int r, rl, rf, s, sl, sf, i, a, j, b, c, idx, t, tf; //, tl;
702
703
704 if (f_v) {
705 cout << "character_table_burnside::compute_multiplication_constants_center_of_group_ring" << endl;
706 }
707
708 N = NEW_int(nb_classes * nb_classes * nb_classes);
709 Int_vec_zero(N, nb_classes * nb_classes * nb_classes);
710
711
712 for (r = 0; r < nb_classes; r++) {
713 rl = Sch->orbit_len[r];
714 rf = Sch->orbit_first[r];
715
716 for (s = 0; s < nb_classes; s++) {
717 sl = Sch->orbit_len[s];
718 sf = Sch->orbit_first[s];
719
720
721 for (i = 0; i < rl; i++) {
722 a = Sch->orbit[rf + i];
723
724 for (j = 0; j < sl; j++) {
725 b = Sch->orbit[sf + j];
726
727 c = ABC->multiply(A, a, b, 0 /*verbose_level*/);
728
729
730 idx = Sch->orbit_inv[c];
731
732 t = Sch->orbit_number(c); //Sch->orbit_no[idx];
733
734 tf = Sch->orbit_first[t];
735 //tl = Sch->orbit_len[t];
736
737 if (idx == tf) {
738 N[r * nb_classes * nb_classes + s * nb_classes + t]++;
739 }
740 }
741 }
742 }
743 }
744 if (f_v) {
745 cout << "character_table_burnside::compute_multiplication_constants_center_of_group_ring done" << endl;
746 }
747}
748
751 groups::schreier *Sch, int nb_classes,
752 int **Gens, int nb_gens, int t_max, int *&Distribution, int verbose_level)
753{
754 int f_v = (verbose_level >= 1);
755 //int f_vv = (verbose_level >= 2);
756 int f_vvv = (verbose_level >= 3);
757 int *Elt1;
758 int *Elt2;
759 int *Choice;
760 int *Nb;
761 int t, h, i, /*idx,*/ j;
764
765 if (f_v) {
766 cout << "character_table_burnside::compute_Distribution_table" << endl;
767 }
768 Elt1 = NEW_int(A->elt_size_in_int);
769 Elt2 = NEW_int(A->elt_size_in_int);
770
771 Choice = NEW_int(t_max);
772 Distribution = NEW_int((t_max + 1) * nb_classes);
773 Int_vec_zero(Distribution, (t_max + 1) * nb_classes);
774 Nb = NEW_int(t_max + 1);
775
776 for (t = 1; t <= t_max; t++) {
777 Nb[t] = NT.i_power_j(nb_gens, t);
778 }
779
780 if (f_v) {
781 cout << "Nb : ";
782 Int_vec_print(cout, Nb + 1, t_max);
783 cout << endl;
784 }
785
786 for (t = 1; t <= t_max; t++) {
787 cout << "t=" << t << " Nb[t]=" << Nb[t] << endl;
788 for (h = 0; h < Nb[t]; h++) {
789 Gg.AG_element_unrank(nb_gens, Choice, 1, t, h);
790
791 if (f_vvv) {
792 cout << "h=" << h << " Choice=";
793 Int_vec_print(cout, Choice, t);
794 cout << endl;
795 }
796
797 multiply_word(A, Gens, Choice, t, Elt1, Elt2, verbose_level);
798
799 i = ABC->rank(Elt1);
800
801
802 //idx = Sch->orbit_inv[i];
803
804 j = Sch->orbit_number(i); // Sch->orbit_no[idx];
805
806
807 if (f_vvv) {
808 cout << "word:";
809 A->element_print(Elt1, cout);
810 cout << " has rank " << i << " and belongs to class " << j;
811 cout << endl;
812 }
813
814 Distribution[t * nb_classes + j]++;
815 }
816
817 if (f_v) {
818 cout << "after t=" << t << " Distribution:" << endl;
819 Int_matrix_print(Distribution, t + 1, nb_classes);
820 }
821 }
822
823 FREE_int(Choice);
824 FREE_int(Nb);
825 FREE_int(Elt1);
826 FREE_int(Elt2);
827
828 if (f_v) {
829 cout << "character_table_burnside::compute_Distribution_table done" << endl;
830 }
831}
832
833
834void character_table_burnside::multiply_word(actions::action *A, int **Gens, int *Choice, int t, int *Elt1, int *Elt2, int verbose_level)
835{
836 int i;
837
838 A->element_move(Gens[Choice[0]], Elt1, 0);
839 for (i = 1; i < t; i++) {
840 A->element_mult(Elt1, Gens[Choice[i]], Elt2, 0);
841 A->element_move(Elt2, Elt1, 0);
842 }
843}
844
845void character_table_burnside::create_generators(actions::action *A, int n, int **&Elt, int &nb_gens, int f_special, int verbose_level)
846{
847 int f_v = (verbose_level >= 1);
848 int i, j;
849 int *v;
850
851 if (f_v) {
852 cout << "character_table_burnside::create_generators" << endl;
853 }
854 nb_gens = n - 1;
855 Elt = NEW_pint(nb_gens);
856 for (i = 0; i < nb_gens; i++) {
857 Elt[i] = NEW_int(A->elt_size_in_int);
858 }
859 v = NEW_int(n);
860
861
862 if (f_special) {
863 for (i = 0; i < nb_gens; i++) {
864 for (j = 0; j < n; j++) {
865 v[j] = j;
866 }
867 v[0] = i + 1;
868 v[i + 1] = 0;
869 A->make_element(Elt[i], v, 0 /* verbose_level */);
870 }
871 }
872 else {
873 for (i = 0; i < nb_gens; i++) {
874 for (j = 0; j < n; j++) {
875 v[j] = j;
876 }
877 v[i] = i + 1;
878 v[i + 1] = i;
879 A->make_element(Elt[i], v, 0 /* verbose_level */);
880 }
881 }
882 cout << "generators:" << endl;
883 for (i = 0; i < nb_gens; i++) {
884 cout << "generator " << i << ":" << endl;
885 A->element_print(Elt[i], cout);
886 cout << endl;
887 }
888
889 FREE_int(v);
890
891}
892
893
894
896 int *&Lambda,
897 int &nb_lambda,
898 int *&Mu,
899 int *&Mu_mult,
900 int &nb_mu,
901 int verbose_level)
902{
903 int f_v = (verbose_level >= 1);
904 unipoly charpoly;
905 int *A;
906 int *B;
907 int i, deg, a, x;
908
909 if (f_v) {
910 cout << "character_table_burnside::integral_eigenvalues" << endl;
911 }
912 characteristic_poly(M, n, charpoly, 0 /*verbose_level*/);
913 if (f_v) {
914 cout << "characteristic polynomial:" << charpoly << endl;
915 }
916
917 deg = charpoly.degree();
918 if (f_v) {
919 cout << "has degree " << deg << endl;
920 }
921
922 A = NEW_int(deg + 1);
923 B = NEW_int(deg + 1);
924
925 for (i = 0; i <= deg; i++) {
926 A[i] = charpoly.s_ii(i);
927 }
928 if (f_v) {
929 cout << "coeffs : ";
930 Int_vec_print(cout, A, deg + 1);
931 cout << endl;
932 }
933
934
935 Lambda = NEW_int(deg);
936 Mu = NEW_int(deg);
937 Mu_mult = NEW_int(deg);
938 nb_lambda = 0;
939 nb_mu = 0;
940
941 for (x = -100; x < 100; x++) {
942 a = A[deg];
943 for (i = deg - 1; i >= 0; i--) {
944 a *= x;
945 a += A[i];
946 }
947 if (a == 0) {
948 if (f_v) {
949 cout << "Found integer root " << x << endl;
950 }
951 Lambda[nb_lambda++] = x;
952 if (nb_mu && Mu[nb_mu - 1] == x) {
953 if (f_v) {
954 cout << "The root is a multiple root" << endl;
955 }
956 Mu_mult[nb_mu - 1]++;
957 }
958 else {
959 Mu[nb_mu] = x;
960 Mu_mult[nb_mu] = 1;
961 nb_mu++;
962 }
963
964 for (i = deg - 1; i >= 0; i--) {
965 B[i] = A[i + 1];
966 A[i] = A[i] + x * B[i];
967 if (i == 0 && A[0]) {
968 cout << "division unsuccessful" << endl;
969 exit(1);
970 }
971 }
972 Int_vec_copy(B, A, deg);
973 deg--;
974 if (f_v) {
975 cout << "after dividing off, the polynomial is: ";
976 Int_vec_print(cout, A, deg + 1);
977 cout << endl;
978 }
979
980 x--; // try x again
981 }
982 }
983
984
985 if (f_v) {
986 cout << "after dividing off integer roots, the polynomial is: ";
987 Int_vec_print(cout, A, deg + 1);
988 cout << endl;
989 }
990
991 if (f_v) {
992 cout << "We found " << nb_lambda << " integer roots, they are: " << endl;
993 Int_vec_print(cout, Lambda, nb_lambda);
994 cout << endl;
995 cout << "We found " << nb_mu << " distinct integer roots, they are: " << endl;
996 for (i = 0; i < nb_mu; i++) {
997 cout << Mu[i] << " with multiplicity " << Mu_mult[i] << endl;
998 }
999 }
1000
1001 FREE_int(A);
1002 FREE_int(B);
1003}
1004
1005void character_table_burnside::characteristic_poly(int *N, int size, unipoly &charpoly, int verbose_level)
1006{
1007 int f_v = (verbose_level >= 1);
1008 int f_vv = (verbose_level >= 2);
1009 int i, j, k, a;
1010 discreta_matrix M, M1, P, Pv, Q, Qv, S, T;
1011
1012 if (f_v) {
1013 cout << "character_table_burnside::characteristic_poly" << endl;
1014 }
1015 M.m_mn(size, size);
1016 k = 0;
1017 for (i = 0; i < size; i++) {
1018 for (j = 0; j < size; j++) {
1019 a = N[k++];
1020 M.m_iji(i, j, a);
1021 }
1022 }
1023 if (f_vv) {
1024 cout << "M=" << endl;
1025 cout << M << endl;
1026 }
1027
1028
1030 M.minus_X_times_id();
1031
1032
1033#if 0
1034 M1 = M;
1035 cout << "M - x * Id=" << endl << M << endl;
1036 M.smith_normal_form(P, Pv, Q, Qv, verbose_level);
1037
1038 cout << "the Smith normal form is:" << endl;
1039 cout << M << endl;
1040
1041 S.mult(P, Pv);
1042 cout << "P * Pv=" << endl << S << endl;
1043
1044 S.mult(Q, Qv);
1045 cout << "Q * Qv=" << endl << S << endl;
1046
1047 S.mult(P, M1);
1048 cout << "T.mult(S, Q):" << endl;
1049 T.mult(S, Q);
1050 cout << "T=" << endl << T << endl;
1051#endif
1052
1053 //int deg;
1054 //int l, lv, b;
1055
1056
1057 M.determinant(charpoly, verbose_level);
1058 //charpoly = M.s_ij(size - 1, size - 1);
1059
1060 if (f_v) {
1061 cout << "characteristic polynomial:" << charpoly << endl;
1062 }
1063 //deg = charpoly.degree();
1064 //cout << "has degree " << deg << endl;
1065
1066#if 0
1067 for (i = 0; i <= deg; i++) {
1068 b = charpoly.s_ii(i);
1069 if (b > q2) {
1070 b -= q;
1071 }
1072 //c = Fq.mult(b, lv);
1073 charpoly.m_ii(i, b);
1074 }
1075
1076 cout << "characteristic polynomial:" << charpoly << endl;
1077#endif
1078
1079 if (f_v) {
1080 cout << "character_table_burnside::characteristic_poly done" << endl;
1081 }
1082}
1083
1084
1085
1087{
1088 double c;
1089
1090 c = a;
1091 a = b;
1092 b = c;
1093}
1094
1095int character_table_burnside::double_Gauss(double *A, int m, int n, int *base_cols, int verbose_level)
1096{
1097 int f_v = (verbose_level >= 1);
1098 int f_vv = (verbose_level >= 2);
1099 double pivot, pivot_inv, z, f, a, b, c, p;
1100 int i, j, k, jj, rank, idx;
1101
1102 if (f_v) {
1103 cout << "character_table_burnside::double_Gauss" << endl;
1104 }
1105 i = 0;
1106 for (j = 0; j < n; j++) {
1107 if (f_vv) {
1108 cout << "j=" << j << endl;
1109 double_matrix_print(A, m, n);
1110 }
1111 // search for pivot element:
1112 idx = -1;
1113 for (k = i; k < m; k++) {
1114 if (idx == -1) {
1115 p = A[k * n + j];
1116 idx = k;
1117 }
1118 else {
1119 if (double_abs(A[k * n + j]) > double_abs(p)) {
1120 p = A[k * n + j];
1121 idx = k;
1122 }
1123 }
1124 } // next k
1125 if (f_v) {
1126 cout << "column " << i << " pivot is " << p << " in row " << idx << endl;
1127 }
1128
1129 if (idx == -1 || double_abs(p) < 0.00001) { // no pivot found
1130 if (f_v) {
1131 cout << "no pivot found" << endl;
1132 }
1133 continue; // increase j, leave i constant
1134 }
1135 else {
1136 k = idx;
1137 // pivot element found:
1138 if (k != i) {
1139 for (jj = j; jj < n; jj++) {
1140 double_swap(A[i * n + jj], A[k * n + jj]);
1141 }
1142 }
1143 }
1144
1145 if (f_vv) {
1146 cout << "row " << i << " pivot in row " << k << " colum " << j << endl;
1147 double_matrix_print(A, m, n);
1148 }
1149
1150 base_cols[i] = j;
1151 //if (FALSE) {
1152 // cout << "."; cout.flush();
1153 // }
1154
1155 pivot = A[i * n + j];
1156 if (f_vv) {
1157 cout << "pivot=" << pivot << endl;
1158 }
1159 //pivot_inv = inv_table[pivot];
1160 pivot_inv = 1. / pivot;
1161 if (f_vv) {
1162 cout << "pivot=" << pivot << " pivot_inv=" << pivot_inv << endl;
1163 }
1164 // make pivot to 1:
1165 for (jj = j; jj < n; jj++) {
1166 A[i * n + jj] *= pivot_inv;
1167 }
1168 if (f_vv) {
1169 cout << "pivot=" << pivot << " pivot_inv=" << pivot_inv
1170 << " made to one: " << A[i * n + j] << endl;
1171 double_matrix_print(A, m, n);
1172 }
1173
1174
1175 // do the gaussian elimination:
1176
1177 if (f_vv) {
1178 cout << "doing elimination in column " << j << " from row " << i + 1 << " to row " << m - 1 << ":" << endl;
1179 }
1180 for (k = i + 1; k < m; k++) {
1181 if (f_vv) {
1182 cout << "k=" << k << endl;
1183 }
1184 z = A[k * n + j];
1185 if (double_abs(z) < 0.0000000001) {
1186 continue;
1187 }
1188 f = z;
1189 //A[k * n + j] = 0;
1190 if (f_vv) {
1191 cout << "eliminating row " << k << endl;
1192 }
1193 for (jj = j; jj < n; jj++) {
1194 a = A[i * n + jj];
1195 b = A[k * n + jj];
1196 // c := b + f * a
1197 // = b - z * a if !f_special
1198 // b - z * pivot_inv * a if f_special
1199 c = b - f * a;
1200 A[k * n + jj] = c;
1201 }
1202 if (f_vv) {
1203 double_matrix_print(A, m, n);
1204 }
1205 }
1206 i++;
1207 } // next j
1208 rank = i;
1209
1210
1211 for (i = rank - 1; i >= 0; i--) {
1212 if (f_v) {
1213 cout << "."; cout.flush();
1214 }
1215 j = base_cols[i];
1216 a = A[i * n + j];
1217
1218 // do the gaussian elimination in the upper part:
1219 for (k = i - 1; k >= 0; k--) {
1220 z = A[k * n + j];
1221 if (z == 0) {
1222 continue;
1223 }
1224 //A[k * n + j] = 0;
1225 for (jj = j; jj < n; jj++) {
1226 a = A[i * n + jj];
1227 b = A[k * n + jj];
1228 c = - z * a;
1229 c += b;
1230 A[k * n + jj] = c;
1231 }
1232 } // next k
1233 } // next i
1234
1235 return rank;
1236}
1237
1239{
1240 int i, j;
1241
1242 for (i = 0; i < m; i++) {
1243 for (j = 0; j < n; j++) {
1244 cout << setw(10) << A[i * n + j] << " ";
1245 }
1246 cout << endl;
1247 }
1248}
1249
1251{
1252 if (x < 0) {
1253 return - x;
1254 }
1255 else {
1256 return x;
1257 }
1258}
1259
1260void character_table_burnside::kernel_columns(int n, int nb_base_cols, int *base_cols, int *kernel_cols)
1261{
1262 int i, j, k;
1263
1264 j = k = 0;
1265 for (i = 0; i < n; i++) {
1266 if (j < nb_base_cols && i == base_cols[j]) {
1267 j++;
1268 continue;
1269 }
1270 kernel_cols[k++] = i;
1271 }
1272}
1273
1274void character_table_burnside::matrix_get_kernel(double *M, int m, int n, int *base_cols, int nb_base_cols,
1275 int &kernel_m, int &kernel_n, double *kernel)
1276 // kernel must point to the appropriate amount of memory! (at least n * (n - nb_base_cols) int's)
1277{
1278 int r, k, i, j, ii, iii, a, b;
1279 int *kcol;
1280
1281 r = nb_base_cols;
1282 k = n - r;
1283 kernel_m = n;
1284 kernel_n = k;
1285
1286 kcol = NEW_int(k);
1287
1288 ii = 0;
1289 j = 0;
1290 if (j < r) {
1291 b = base_cols[j];
1292 }
1293 else {
1294 b = -1;
1295 }
1296 for (i = 0; i < n; i++) {
1297 if (i == b) {
1298 j++;
1299 if (j < r) {
1300 b = base_cols[j];
1301 }
1302 else {
1303 b = -1;
1304 }
1305 }
1306 else {
1307 kcol[ii] = i;
1308 ii++;
1309 }
1310 }
1311 if (ii != k) {
1312 cout << "character_table_burnside::matrix_get_kernel ii != k" << endl;
1313 exit(1);
1314 }
1315 //cout << "kcol = " << kcol << endl;
1316 ii = 0;
1317 j = 0;
1318 if (j < r) {
1319 b = base_cols[j];
1320 }
1321 else {
1322 b = -1;
1323 }
1324 for (i = 0; i < n; i++) {
1325 if (i == b) {
1326 for (iii = 0; iii < k; iii++) {
1327 a = kcol[iii];
1328 kernel[i * kernel_n + iii] = M[j * n + a];
1329 }
1330 j++;
1331 if (j < r) {
1332 b = base_cols[j];
1333 }
1334 else {
1335 b = -1;
1336 }
1337 }
1338 else {
1339 for (iii = 0; iii < k; iii++) {
1340 if (iii == ii) {
1341 kernel[i * kernel_n + iii] = -1.;
1342 }
1343 else {
1344 kernel[i * kernel_n + iii] = 0;
1345 }
1346 }
1347 ii++;
1348 }
1349 }
1350 FREE_int(kcol);
1351}
1352
1353
1355{
1356 int a;
1357 double a1, a2;
1358
1359 a = (int) (x);
1360 a1 = (double)a - 0.000001;
1361 a2 = (double)a + 0.000001;
1362 if (a1 < a && a < a2) {
1363 return a;
1364 }
1365 cout << "error in double_as_int" << endl;
1366 exit(1);
1367}
1368
1369
1370
1371
1372}}}
1373
related to the computation of Young representations
Definition: algebra.h:32
void copy(int *elt_from, int *elt_to, int verbose_level)
Definition: a_domain.cpp:275
void init_integer_fractions(int verbose_level)
Definition: a_domain.cpp:53
void make_integer(int *elt, int n, int verbose_level)
Definition: a_domain.cpp:102
void add_apply(int *elt_a, int *elt_b, int verbose_level)
Definition: a_domain.cpp:383
void mult_apply(int *elt_a, int *elt_b, int verbose_level)
Definition: a_domain.cpp:508
void make_zero(int *elt, int verbose_level)
Definition: a_domain.cpp:122
void mult(int *elt_a, int *elt_b, int *elt_c, int verbose_level)
Definition: a_domain.cpp:477
void inverse(int *elt_a, int *elt_b, int verbose_level)
Definition: a_domain.cpp:682
void get_image_and_kernel(int *M, int n, int &rk, int verbose_level)
Definition: a_domain.cpp:1307
int as_int(int *elt, int verbose_level)
Definition: a_domain.cpp:65
void print_matrix(int *A, int m, int n)
Definition: a_domain.cpp:774
various functions related to geometries
Definition: geometry.h:721
void AG_element_unrank(int q, int *v, int stride, int len, long int a)
void print_integer_matrix_tex(std::ostream &ost, int *p, int m, int n)
a class to represent arbitrary precision integers
Definition: ring_theory.h:366
void m_ii(int i, int a)
Definition: discreta.h:824
void mult(discreta_base &x, discreta_base &y)
Definition: base.cpp:367
discreta_matrix & m_mn(int m, int n)
void smith_normal_form(discreta_matrix &P, discreta_matrix &Pv, discreta_matrix &Q, discreta_matrix &Qv, int verbose_level)
discreta_matrix & m_mn_n(int m, int n)
void m_iji(int i, int j, int a)
Definition: discreta.h:1099
void determinant(discreta_base &d, int verbose_level)
DISCRETA class for polynomials in one variable.
Definition: discreta.h:1236
a permutation group in a fixed action.
Definition: actions.h:99
void element_print_quick(void *elt, std::ostream &ost)
Definition: action_cb.cpp:353
void element_print(void *elt, std::ostream &ost)
Definition: action_cb.cpp:347
void init_symmetric_group(int degree, int f_no_base, int verbose_level)
void element_mult(void *a, void *b, void *ab, int verbose_level)
Definition: action_cb.cpp:315
void make_element(int *Elt, int *data, int verbose_level)
Definition: action.cpp:1875
void element_move(void *a, void *b, int verbose_level)
Definition: action_cb.cpp:335
void group_order(ring_theory::longinteger_object &go)
Definition: action.cpp:2223
void induced_action_by_conjugation(groups::sims *old_G, groups::sims *Base_group, int f_ownership, int f_basis, int verbose_level)
Schreier trees for orbits of groups on points.
Definition: groups.h:839
void compute_all_point_orbits(int verbose_level)
Definition: schreier.cpp:988
void init_generators(data_structures_groups::vector_ge &generators, int verbose_level)
Definition: schreier.cpp:373
void init(actions::action *A, int verbose_level)
Definition: schreier.cpp:308
a permutation group represented via a stabilizer chain
Definition: groups.h:1273
void element_unrank_lint(long int rk, int *Elt, int verbose_level)
Definition: sims.cpp:1326
a strong generating set for a permutation group with respect to a fixed action
Definition: groups.h:1703
void init_from_sims(groups::sims *S, int verbose_level)
data_structures_groups::vector_ge * gens
Definition: groups.h:1708
induced action by conjugation on the elements of a given group
long int multiply(actions::action *A, long int i, long int j, int verbose_level)
void multiply_word(actions::action *A, int **Gens, int *Choice, int t, int *Elt1, int *Elt2, int verbose_level)
void integral_eigenvalues(int *M, int n, int *&Lambda, int &nb_lambda, int *&Mu, int *&Mu_mult, int &nb_mu, int verbose_level)
void characteristic_poly(int *N, int size, unipoly &charpoly, int verbose_level)
void matrix_get_kernel(double *M, int m, int n, int *base_cols, int nb_base_cols, int &kernel_m, int &kernel_n, double *kernel)
void compute_multiplication_constants_center_of_group_ring(actions::action *A, induced_actions::action_by_conjugation *ABC, groups::schreier *Sch, int nb_classes, int *&N, int verbose_level)
void compute_character_degrees(algebra::a_domain *D, int goi, int nb_classes, int *Omega, int *class_size, int *&character_degree, int verbose_level)
void compute_Distribution_table(actions::action *A, induced_actions::action_by_conjugation *ABC, groups::schreier *Sch, int nb_classes, int **Gens, int nb_gens, int t_max, int *&Distribution, int verbose_level)
void compute_omega(algebra::a_domain *D, int *N0, int nb_classes, int *Mu, int nb_mu, int *&Omega, int verbose_level)
void compute_character_table(algebra::a_domain *D, int nb_classes, int *Omega, int *character_degree, int *class_size, int *&character_table, int verbose_level)
void create_matrix(discreta_matrix &M, int i, int *S, int nb_classes, int *character_degree, int *class_size, int verbose_level)
void create_generators(actions::action *A, int n, int **&Elt, int &nb_gens, int f_special, int verbose_level)
int double_Gauss(double *A, int m, int n, int *base_cols, int verbose_level)
void kernel_columns(int n, int nb_base_cols, int *base_cols, int *kernel_cols)
#define FREE_int(p)
Definition: foundations.h:640
#define Int_vec_zero(A, B)
Definition: foundations.h:713
#define NEW_pint(n)
Definition: foundations.h:627
#define NEW_OBJECT(type)
Definition: foundations.h:638
#define FREE_OBJECT(p)
Definition: foundations.h:651
#define NEW_int(n)
Definition: foundations.h:625
#define Int_matrix_print(A, B, C)
Definition: foundations.h:707
#define TRUE
Definition: foundations.h:231
#define FALSE
Definition: foundations.h:234
#define Int_vec_copy(A, B, C)
Definition: foundations.h:693
#define FREE_pint(p)
Definition: foundations.h:641
#define Int_vec_print(A, B, C)
Definition: foundations.h:685
algebra, combinatorics and graph theory, geometry, linear algebra, number theory, data structures,...
Definition: a_domain.cpp:18
the orbiter library for the classification of combinatorial objects
induced_actions::action_by_conjugation * ABC