Orbiter 2022
Combinatorial Objects
permutation.cpp
Go to the documentation of this file.
1// permutation.cpp
2//
3// Anton Betten
4// 10.11.1999
5// moved from D2 to ORBI Nov 15, 2007
6
8#include "discreta.h"
9
10using namespace std;
11
12
13
14namespace orbiter {
15namespace layer2_discreta {
16
17
18
19#undef PERMUTATION_CHANGE_KIND_VERBOSE
20#undef PERMUTATION_COPY_VERBOSE
21
26 };
27
30
32{
34}
35
37{
39}
40
42{
45}
46
48{
49 a.init("");
52 a.append_i(i + 1);
53 }
54 else {
55 a.append_i(i);
56 }
57 }
59 a.append_i(i + 1);
60 }
62 Vector v;
63
64 v.m_l_n(2);
65 {
68 }
69 if (v.s_ii(1) == 0)
70 a.append("\\infty");
71 else
72 a.append_i(v.s_ii(0));
73 }
74
75}
76
77
78
80{
81 k = PERMUTATION;
82 self.vector_pointer = NULL;
83}
84
86 // copy constructor: this := x
87{
88 cout << "permutation::copy constructor for object: " << const_cast<discreta_base &>(x) << "\n";
89 clearself();
90 const_cast<discreta_base &>(x).copyobject_to(*this);
91}
92
94 // copy assignment
95{
96 // cout << "permutation::operator = (copy assignment)" << endl;
97 copyobject(const_cast<discreta_base &>(x));
98 return *this;
99}
100
102{
103 OBJECTSELF s;
104
105 s = self;
106 new(this) permutation;
107 self = s;
108 k = PERMUTATION;
109}
110
112{
114}
115
117{
118 // cout << "permutation::freeself_permutation()\n";
119 if (self.vector_pointer == NULL) {
120 // cout << "returning\n";
121 return;
122 }
123 // cout << "free_nobjects_plus_length()\n";
125 self.vector_pointer = NULL;
126}
127
129{
130 return PERMUTATION;
131}
132
134{
135 int i, l;
136
137#ifdef PERMUTATION_COPY_VERBOSE
138 cout << "permutation::copyobject_to()\n";
139#endif
140 x.freeself();
141 if (x.s_kind() != PERMUTATION) {
143 x.self.vector_pointer = NULL;
144 // x.printobjectkindln();
145 }
146 l = s_l();
147#ifdef PERMUTATION_COPY_VERBOSE
148 cout << "l=" << l << "\n";
149#endif
150 permutation & xx = x.as_permutation();
151#ifdef PERMUTATION_COPY_VERBOSE
152 cout << "calling xx.m_l()\n";
153#endif
154 xx.m_l(l);
155 for (i = 0; i < l; i++) {
156#ifdef PERMUTATION_COPY_VERBOSE
157 cout << "copy " << i << ": " << s_i(i) << endl;
158#endif
159 xx[i] = s_i(i);
160 }
161}
162
163ostream& permutation::print(ostream& ost)
164{
165 return print_cycle(ost);
166}
167
168ostream& permutation::print_list(ostream& ost)
169{
170 return as_vector().Vector::print(ost);
171}
172
173ostream& permutation::print_cycle(ostream& ost)
174{
176 Vector have_seen;
177 int l, l1, first, next, len, n;
178 int f_nothing_printed_at_all = TRUE;
179
180 n = s_l();
181 have_seen.m_l(n);
182 for (l = 0; l < n; l++) {
183 have_seen[l].m_i_i(FALSE);
184 }
185 l = 0;
186 while (l < n) {
187 if (have_seen[l].s_i_i()) {
188 l++;
189 continue;
190 }
191 /* Bearbeite Zyklus, beginnend mit l: */
192 first = l;
193 l1 = l;
194 len = 1;
195 while (TRUE) {
196 have_seen[l1].m_i_i(TRUE);
197 next = s_ii(l1);
198 if (next > n) {
199 cout << "permutation::print_cycle: next = "
200 << next << " > n = " << n << endl;
201 print_list(ost);
202 exit(1);
203 }
204 if (next == first) {
205 break;
206 }
207 if (have_seen[next].s_i_i()) {
208 cout << "permutation::print_cycle: have_seen[next]\n";
209 print_list(ost);
210 exit(1);
211 }
212 l1 = next;
213 len++;
214 }
215 if (len == 1)
216 continue;
217 f_nothing_printed_at_all = FALSE;
218 /* Drucke Zyklus, beginnend mit first: */
219 l1 = first;
220 ost << "(";
221 while (TRUE) {
222 {
223 hollerith a;
224 convert_digit(l1, a);
225 ost << a;
226 }
227 next = s_ii(l1);
228 if (next == first) {
229 break;
230 }
231 ost << ", ";
232 l1 = next;
233 }
234 ost << ")";
235 }
236 if (f_nothing_printed_at_all) {
237 ost << "id";
238 }
239 }
240
242 Vector have_seen;
243 int l, l1, first, next, len, n;
244 int f_nothing_printed_at_all = TRUE;
245
246 n = s_l();
247 have_seen.m_l(n);
248 for (l = 0; l < n; l++) {
249 have_seen[l].m_i_i(FALSE);
250 }
251 l = 0;
252 while (l < n) {
253 if (have_seen[l].s_i_i()) {
254 l++;
255 continue;
256 }
257 /* Bearbeite Zyklus, beginnend mit l: */
258 first = l;
259 l1 = l;
260 len = 1;
261 while (TRUE) {
262 have_seen[l1].m_i_i(TRUE);
263 next = s_ii(l1);
264 if (next > n) {
265 cout << "permutation::print_cycle: next = "
266 << next << " > n = " << n << endl;
267 print_list(ost);
268 exit(1);
269 }
270 if (next == first) {
271 break;
272 }
273 if (have_seen[next].s_i_i()) {
274 cout << "permutation::print_cycle: have_seen[next]\n";
275 print_list(ost);
276 exit(1);
277 }
278 l1 = next;
279 len++;
280 }
281 if (len == 1)
282 continue;
283 f_nothing_printed_at_all = FALSE;
284 /* Drucke Zyklus, beginnend mit first: */
285 l1 = first;
286 ost << "(";
287 while (TRUE) {
288 {
289 hollerith a;
290 convert_digit(l1, a);
291 ost << a;
292 }
293 next = s_ii(l1);
294 if (next == first) {
295 break;
296 }
297 ost << ", ";
298 l1 = next;
299 }
300 ost << ")";
301 }
302 if (f_nothing_printed_at_all) {
303 ost << "(";
304#if 0
305 {
306 hollerith a;
307 convert_digit(n - 1, a);
308 ost << a;
309 }
310#endif
311 ost << ")";
312 }
313 }
314
315 return ost;
316}
317
318
319void permutation::sscan(const char *s, int verbose_level)
320{
321 istringstream ins(s);
322 scan(ins, verbose_level);
323}
324
325void permutation::scan(istream & is, int verbose_level)
326//Scans a permutation from a stream.
327{
328 int f_v = (verbose_level >+ 1);
329 int l = 20;
330 Vector cycle;
331 permutation perm;
332 int i, a_last, a, dig, ci;
333 char s[10000], c;
334 int si, largest_point = 0;
336
337 //l = s_l();
338 perm.m_l(l);
339 cycle.m_l_n(l);
340 perm.one();
341 while (TRUE) {
342 c = ST.get_character(is, verbose_level);
343 while (c == ' ' || c == '\t') {
344 c = ST.get_character(is, f_v);
345 }
346 ci = 0;
347 if (c != '(') {
348 break;
349 }
350 if (f_v) {
351 cout << "opening parenthesis" << endl;
352 }
353 c = ST.get_character(is, verbose_level);
354 while (TRUE) {
355 while (c == ' ' || c == '\t')
356 c = ST.get_character(is, verbose_level);
357
358 si = 0;
359 // read digits:
360 while (c >= '0' && c <= '9') {
361 s[si++] = c;
362 c = ST.get_character(is, f_v);
363 }
364 while (c == ' ' || c == '\t')
365 c = ST.get_character(is, f_v);
366 if (c == ',')
367 c = ST.get_character(is, f_v);
368 s[si] = 0;
369 dig = atoi(s);
370 if (dig > largest_point)
371 largest_point = dig;
372 if (f_v) {
373 cout << "digit as string: " << s << ", numeric: " << dig << endl;
374 }
375 if (dig < 0) {
376 cout << "permutation::scan(): digit < 0" << endl;
377 exit(1);
378 }
379 if (dig >= l) {
380 permutation perm1;
381 Vector cycle1;
382 int l1, i;
383
384 l1 = MAXIMUM(l + (l >> 1), largest_point + 1);
385 cout << "permutation::scan(): digit = " << dig << " >= " << l << ", extending permutation degree to " << l1 << endl;
386 perm1.m_l(l1);
387 for (i = 0; i < l; i++) {
388 perm1.m_ii(i, perm.s_i(i));
389 }
390 perm.swap(perm1);
391 cycle1.m_l_n(l1);
392 for (i = 0; i < l; i++) {
393 cycle1.m_ii(i, cycle.s_ii(i));
394 }
395 cycle.swap(cycle1);
396 l = l1;
397 }
398 si = 0;
399 cycle.m_ii(ci, dig + 1);
400 ci++;
401 if (c == ')') {
402 if (f_v) {
403 cout << "closing parenthesis, cycle = ";
404 for (i = 0; i < ci; i++)
405 cout << cycle.s_ii(i) << " ";
406 cout << endl;
407 }
408 for (i = 1; i < ci; i++) {
409 a_last = cycle.s_ii(i - 1);
410 a = cycle.s_ii(i);
411 perm.m_ii(a_last - 1, a - 1);
412 }
413 if (ci > 1) {
414 a_last = cycle.s_ii(ci - 1);
415 a = cycle.s_ii(0);
416 perm.m_ii(a_last - 1, a - 1);
417 }
418 ci = 0;
419 if (!is)
420 break;
421 //c = get_character(is, f_v);
422 break;
423 }
424 } // loop for one cycle
425 if (!is)
426 break;
427 while (c == ' ' || c == '\t')
428 c = ST.get_character(is, f_v);
429 ci = 0;
430 } // end of loop over all cycles
431 {
432 permutation perm1;
433 int i;
434
435 perm1.m_l(largest_point + 1);
436 for (i = 0; i <= largest_point; i++) {
437 perm1.m_ii(i, perm.s_i(i));
438 }
439 perm.swap(perm1);
440 }
441 if (f_v) {
442 cout << "read permutation " << perm;
443 }
444 swap(perm);
445}
446
448{
449 int l;
450
451 if (self.vector_pointer == NULL) {
452 cout << "permutation::s_i() vector_pointer == NULL\n";
453 exit(1);
454 }
455 l = self.vector_pointer[-1].s_i_i();
456 if ( i < 0 || i >= l ) {
457 cout << "permutation::s_i() addressing error, i = " << i << ", length = " << l << "\n";
458 exit(1);
459 }
461}
462
464{
465 permutation& px = x.as_permutation();
466 permutation py;
467 int i, l;
468
469 if (s_kind() != PERMUTATION) {
470 cout << "permutation::mult_to() this not a permutation\n";
471 exit(1);
472 }
473 if (x.s_kind() != PERMUTATION) {
474 cout << "permutation::mult_to() x is not a permutation\n";
475 exit(1);
476 }
477 l = s_l();
478 if (px.s_l() != l) {
479 cout << "permutation::mult_to() px.s_l() != l\n";
480 exit(1);
481 }
482 py.m_l(l);
483 for (i = 0; i < l; i++) {
484 py[i] = px[s_i(i)];
485 }
486 y.swap(py);
487}
488
490{
491 permutation px;
492 int i, j, l;
493
494 if (s_kind() != PERMUTATION) {
495 cout << "permutation::invert_to() this is not a permutation\n";
496 exit(1);
497 }
498 l = s_l();
499 px.m_l(l);
500 for (i = 0; i < l; i++) {
501 j = s_ii(i);
502 px[j] = i;
503 }
504 x.swap(px);
505 return TRUE;
506}
507
509{
510 int i, l;
511
512 l = s_l();
513 for (i = 0; i < l; i++)
514 s_i(i) = i;
515}
516
518{
519 int i, l;
520
521 l = s_l();
522 for (i = 0; i < l; i++)
523 if (s_i(i) != i)
524 return FALSE;
525 return TRUE;
526}
527
529{
530 int l1, l2, i, c;
531
532 if (s_kind() != PERMUTATION) {
533 return compare_with(a);
534 }
535 if (a.s_kind() != PERMUTATION) {
536 cout << "a is not a permutation\n";
537 exit(1);
538 }
540 l1 = s_l();
541 l2 = p.s_l();
542 for (i = 0; i < l1; i++) {
543 if (i < l2) {
544 c = s_i(i) - p[i];
545 if (c)
546 return c;
547 }
548 else {
549 return -1;
550 }
551 }
552 if (l2 > l1)
553 return 1;
554 return 0;
555}
556
557#if 0
558#if TEXDOCU
559void permutation::perm2lehmercode(Vector v)
560#else
561Computes the lehmercode of a given permutation
562#endif
563{
564 int i, j, k;
565
566 s_s()->copy(vec);
567 for (i = 0; i < vec->s_li(); ) {
568 k = vec->s_ii(i) - 1;
569 vec->m_ii(i, k);
570 i++;
571 for (j = i; j < vec->s_li(); j++)
572 if (vec->s_ii(j) > k)
573 vec->s_i(j)->dec();
574 }
575}
576#endif
577
578
579void permutation::write_mem(memory & M, int debug_depth)
580{
581 int i, l, a;
582
583 l = s_l();
584 M.write_int(l);
585 if (ONE_char_int(l)) {
586 for (i = 0; i < l; i++) {
587 a = s_i(i) + 1;
588 M.write_char((char) a);
589 }
590 }
591 else {
592 for (i = 0; i < l; i++) {
593 a = s_i(i) + 1;
594 M.write_int(a);
595 }
596 }
597}
598
599void permutation::read_mem(memory & M, int debug_depth)
600{
601 int i, l, a;
602 char c;
603
604 M.read_int(&l);
605 m_l(l);
606 if (ONE_char_int(l)) {
607 for (i = 0; i < l; i++) {
608 M.read_char(&c);
609 a = (int) c;
610 a--;
611 s_i(i) = a;
612 }
613 }
614 else {
615 for (i = 0; i < l; i++) {
616 M.read_int(&a);
617 a--;
618 s_i(i) = a;
619 }
620 }
621}
622
624{
625 int l;
626 int size = 0;
627
628 l = s_l();
629 size += 4; /* l */
630 if (ONE_char_int(l))
631 size += l * 1;
632 else
633 size += l * 4;
634 return size;
635}
636
638{
639 int i, l;
640
641 l = s_l();
642 f.m_l(0);
643 for (i = 0; i < l; i++) {
644 if (s_ii(i) == i) {
645 f.append_integer(i);
646 }
647 }
648}
649
651//Computes the induced action on the blocks of a design.
652//this contains the point-permutation, B the sorted list
653//of blocks of the simple (no repeated blocks) design.
654//gg will contain the action of degree B$->$s\_li();
655//Important: B is a sorted vector of sorted blocks !!!
656//This routine works fine only for \lq simple\rq designs,
657//e.g. no block occurs twice
658//exception: empty blocks are treated correctly,
659//they lie in the first positions of B (due to the sorting).
660{
661 int i, j, l, b, a, aa;
662 int nb_empty, idx;
663 Vector b1;
664
665 b = B.s_l();
666 gg.m_l(b);
667 nb_empty = 0;
668 for (i = 0; i < b; i++) {
669 Vector & bl = B.s_i(i).as_vector();
670 l = bl.s_l();
671 if (l == 0) {
672 idx = nb_empty;
673 nb_empty++;
674 }
675 else {
676 b1.m_l(l);
677 for (j = 0; j < l; j++) {
678 a = bl.s_ii(j);
679 aa = s_ii(a);
680 b1.m_ii(j, aa);
681 }
682 b1.sort();
683 if (!B.search(b1, &idx)) {
684 cout << "permutation::induce_action_on_blocks, image block not found " << *this << endl;
685 cout << "block: [" << bl << "]" << endl;
686 cout << "image block: [" << b1 << "]" << endl;
687 exit(1);
688 }
689 }
690 gg.m_ii(i, idx);
691 }
692}
693
695//induction on three sets. Gives a permutation of degree $(n choose 3)$
696//where $n$ is the degree of the permutation in this.
697{
698 int k, l, n, n3, m1, m2, m3, bm1, bm2, bm3, x;
699
700 n = s_l();
701 n3 = n * (n - 1) * (n - 2);
702 n3 /= 2;
703 n3 /= 3;
704 b.m_l(n3);
705 k = 0;
706 for (m1 = 1; m1 <= n; m1++) {
707 for (m2 = m1 + 1; m2 <= n; m2++) {
708 for (m3 = m2 + 1; m3 <= n; m3++) {
709 bm1 = s_ii(m1 - 1) + 1;
710 bm2 = s_ii(m2 - 1) + 1;
711 bm3 = s_ii(m3 - 1) + 1;
712 if (bm1 > bm2) {
713 x = bm1; bm1 = bm2; bm2 = x;
714 }
715 if (bm2 > bm3) {
716 x = bm2; bm2 = bm3; bm3 = x;
717 }
718 if (bm1 > bm2) {
719 x = bm1; bm1 = bm2; bm2 = x;
720 }
721 x = bm3 - bm2;
722 for (l = bm1 + 1; l < bm2; l++)
723 x += n - l;
724 for (l = 1; l < bm1; l++) {
725 if (n - l > 1)
726 x += ((n - l) * (n - l - 1)) >> 1;
727 }
728 b.m_ii(k, x - 1);
729 k++;
730 } // next m3
731 } // next m2
732 } // next m1
733 if (k != n3) {
734 cout << "permutation::induce3() k != n3" << endl;
735 exit(1);
736 }
737}
738
740//a is in fact only a permutation of $1, .. n$.
741//It computes the induced action of a on the pairs $(i,j)$,
742//$1 \le i < j \le n$, which are enumerated in the following way:
743//$\{ \{1,2\}, \{1,3\}, \ldots,\{2,3\},\ldots,\{n-1,n\}\}$.
744{
745 int n;
746 int i, j, k, i1, j1, k1, m;
748
749 n = s_l();
750 m = (n * (n - 1)) >> 1;
751 b.m_l(m);
752 for (i = 0; i < n - 1; i++) {
753 i1 = s_ii(i);
754 for (j = i + 1; j < n; j++) {
755 j1 = s_ii(j);
756 k = Combi.ij2k(i, j, n);
757 k1 = Combi.ij2k(i1, j1, n);
758 b.m_ii(k, k1);
759 }
760 }
761}
762
764//computes induction on two sets.
765//tuple2\_rank and tuple2\_unrank are used.
766{
767 int n, m, i, j, rank, i1, j1, rank1;
768
769 n = s_l();
770 if (f_injective)
771 m = n * (n - 1);
772 else
773 m = n * n;
774 p.m_l(m);
775 for (rank = 0; rank < m; rank++) {
776 tuple2_rank(rank, i, j, n, f_injective);
777 i1 = s_ii(i) - 1;
778 j1 = s_ii(j) - 1;
779 rank1 = tuple2_unrank(i1, j1, n, f_injective);
780 p.m_ii(rank, rank1);
781 }
782}
783
785{
786 int i, j, l;
787
788 l = s_l();
789 b.m_l(n + l);
790 for (i = 0; i < n; i++)
791 b.m_ii(i, i);
792 for (i = 0; i < l; i++) {
793 j = s_ii(i);
794 b.m_ii(n + i, n + j);
795 }
796}
797
799{
800 int i, j, l;
801
802 l = s_l();
803 b.m_l(n + l);
804 for (i = 0; i < l; i++) {
805 j = s_ii(i);
806 b.m_ii(i, j);
807 }
808 for (i = 0; i < n; i++)
809 b.m_ii(l + i, l + i);
810}
811
813//Adds a fixpoint as the new first point of the premutation.
814//All other points are shifted up by one element.
815{
817 // cout << "add_n_fixpoints_in_front() gives " << b << endl;
818}
819
820void permutation::embed_at(permutation & b, int n, int at)
821//adds at fixpoints at the beginning,
822//n - at - l fixpoints at the end.
823//l is the length of the this permutation.
824//Result is b.
825{
826 permutation q;
827 int l, m;
828
829 l = s_l();
830 if (n < l) {
831 cout << "permutation::embed_at() n < l" << endl;
832 exit(1);
833 }
834 if (at + l >= n) {
835 cout << "permutation::embed_at() at + l >= n" << endl;
836 exit(1);
837 }
838 m = n - at - l; // this is >= 0 !
841}
842
844//Attention: $0 \le i < n$ (before: $1 \le i \le n$)
845{
846 int j, k, l;
847
848 l = s_l();
849 if (s_ii(i) != i) {
850 cout << "permutation::remove_fixpoint(): i is not a fixpoint" << endl;
851 exit(1);
852 }
853 b.m_l(l - 1);
854 for (j = 0; j < l; j++) {
855 if (j == i)
856 continue;
857 k = s_ii(j);
858 if (k > i)
859 k--;
860 if (j > i)
861 b.m_ii(j - 1, k);
862 else
863 b.m_ii(j, k);
864 }
865}
866
868//Let $a$ and $b$ act on disjoint sets, and put the resulting permutation into this.
869{
870 int i, j, l1, l2, l3;
871
872 l1 = a.s_l();
873 l2 = b.s_l();
874 l3 = l1 + l2;
875 m_l(l3);
876 for (i = 0; i < l1; i++) {
877 j = a.s_ii(i);
878 m_ii(i, j);
879 }
880 for (i = 0; i < l2; i++) {
881 j = b.s_ii(i);
882 m_ii(l1 + i, l1 + j);
883 }
884}
885
887//a acts on the rows, b on the columns of the cartesian product.
888{
889 int n, m, nm, i, j, rank, i1, j1, rank1;
890
891 n = a.s_l();
892 m = b.s_l();
893 nm = n * m;
894 m_l(nm);
895 for (rank = 0; rank < nm; rank++) {
896 i = rank / m;
897 j = rank % m;
898 i1 = a.s_ii(i);
899 j1 = b.s_ii(j);
900 rank1 = i1 * m + j1;
901 m_ii(rank, rank1);
902 }
903}
904
905
906void permutation::Add2Cycle(int i0, int i1)
907{
908 int N;
909
910 N = s_l();
911 if (i0 < 0 || i0 >= N || i1 < 0 || i1 >= N)
912 {
913 cout << "permutation::Add2Cycle \ni? < 0 || i? >= N" << endl;
914 exit(1);
915 }
916 m_ii(i0, i1);
917 m_ii(i1, i0);
918}
919
920void permutation::Add3Cycle(int i0, int i1, int i2)
921{
922 int N;
923
924 N = s_l();
925 if (i0 < 0 || i0 >= N || i1 < 0 ||
926 i1 >= N || i2 < 0 || i2 >= N)
927 {
928 cout << "permutation::Add3Cycle \ni? < 0 || i? >= N" << endl;
929 exit(1);
930 }
931 m_ii(i0, i1);
932 m_ii(i1, i2);
933 m_ii(i2, i0);
934}
935
936void permutation::Add4Cycle(int i0, int i1, int i2, int i3)
937{
938 int N;
939
940 N = s_l();
941 if (i0 < 0 || i0 >= N || i1 < 0 ||
942 i1 >= N || i2 < 0 || i2 >= N || i3 < 0 || i3 >= N)
943 {
944 cout << "permutation::Add4Cycle \ni? < 0 || i? >= N" << endl;
945 exit(1);
946 }
947 m_ii(i0, i1);
948 m_ii(i1, i2);
949 m_ii(i2, i3);
950 m_ii(i3, i0);
951}
952
953void permutation::Add5Cycle(int i0, int i1, int i2, int i3, int i4)
954{
955 int N;
956
957 N = s_l();
958 if (i0 < 0 || i0 >= N || i1 < 0 ||
959 i1 >= N || i2 < 0 || i2 >= N ||
960 i3 < 0 || i3 >= N || i4 < 0 || i4 >= N)
961 {
962 cout << "permutation::Add5Cycle \ni? < 0 || i? >= N" << endl;
963 exit(1);
964 }
965 m_ii(i0, i1);
966 m_ii(i1, i2);
967 m_ii(i2, i3);
968 m_ii(i3, i4);
969 m_ii(i4, i0);
970}
971
972void permutation::AddNCycle(int first, int len)
973{
974 int N, i;
975
976 N = s_l();
977 if (first < 1 || first + len - 1 > N)
978 {
979 cout << "permutation::AddNCycle \nfirst < 1 || first+len-1 > N" << endl;
980 exit(1);
981 }
982 for (i = 0; i < len; i++)
983 {
984 if (i == len - 1)
985 m_ii(first + i - 1, first);
986 else
987 m_ii(first + i - 1, first + i + 1);
988 }
989}
990
991void permutation::cycle_type(Vector& type, int verbose_level)
992{
993 int f_v = (verbose_level >= 1);
994 Vector have_seen;
995 int l, l1, first, next, len, n;
996
997 n = s_l();
998 have_seen.m_l(n);
999 type.m_l_n(n);
1000 for (l = 0; l < n; l++) {
1001 have_seen[l].m_i_i(FALSE);
1002 }
1003 l = 0;
1004 while (l < n) {
1005 if (have_seen[l].s_i_i()) {
1006 l++;
1007 continue;
1008 }
1009 /* Bearbeite Zyklus, beginnend mit l: */
1010 first = l;
1011 l1 = l;
1012 len = 1;
1013 while (TRUE) {
1014 have_seen[l1].m_i_i(TRUE);
1015 next = s_ii(l1);
1016 if (next > n) {
1017 cout << "permutation::cycle_type: next = "
1018 << next << " > n = " << n << endl;
1019 print_list(cout);
1020 exit(1);
1021 }
1022 if (next == first) {
1023 break;
1024 }
1025 if (have_seen[next].s_i_i()) {
1026 cout << "permutation::cycle_type: have_seen[next]\n";
1027 print_list(cout);
1028 exit(1);
1029 }
1030 l1 = next;
1031 len++;
1032 }
1033 type.s_ii(len - 1)++;
1034 }
1035 if (f_v) {
1036 cout << "the permutation " << *this << " has cycle type " << type << endl;
1037 }
1038}
1039
1040int permutation::nb_of_inversions(int verbose_level)
1041{
1042 Vector type;
1043 int i, l, inv = 0, ai;
1044
1045 l = s_l();
1046 cycle_type(type, verbose_level);
1047 for (i = 1; i <= l; i++) {
1048 ai = type.s_ii(i - 1);
1049 inv += ai * (i - 1);
1050 }
1051 return inv;
1052}
1053
1054int permutation::signum(int verbose_level)
1055{
1056 int inv = nb_of_inversions(verbose_level);
1057 if (EVEN(inv))
1058 return 1;
1059 else
1060 return -1;
1061}
1062
1063int permutation::is_even(int verbose_level)
1064{
1065 int inv = nb_of_inversions(verbose_level);
1066 if (EVEN(inv))
1067 return TRUE;
1068 else
1069 return FALSE;
1070}
1071
1072
1074{
1075 Vector have_seen, cycle;
1076 int l, l1, first, next, len, n;
1077
1078 cycles.m_l(0);
1079 n = s_l();
1080 have_seen.m_l(n);
1081 for (l = 0; l < n; l++) {
1082 have_seen[l].m_i_i(FALSE);
1083 }
1084 l = 0;
1085 while (l < n) {
1086 if (have_seen[l].s_i_i()) {
1087 l++;
1088 continue;
1089 }
1090 /* Bearbeite Zyklus, beginnend mit l: */
1091 first = l;
1092 l1 = l;
1093 len = 1;
1094 cycle.m_l_n(n);
1095 cycle.m_ii(len - 1, l);
1096 while (TRUE) {
1097 have_seen[l1].m_i_i(TRUE);
1098 next = s_ii(l1);
1099 if (next > n) {
1100 cout << "permutation::cycles: next = "
1101 << next << " > n = " << n << endl;
1102 print_list(cout);
1103 exit(1);
1104 }
1105 if (next == first) {
1106 break;
1107 }
1108 if (have_seen[next].s_i_i()) {
1109 cout << "permutation::print_cycle: have_seen[next]\n";
1110 print_list(cout);
1111 exit(1);
1112 }
1113 l1 = next;
1114 cycle.m_ii(len, l1);
1115 len++;
1116 }
1117 cycle.realloc(len);
1118 cycles.append(cycle);
1119 }
1120}
1121
1123{
1124 int i, j;
1125
1126 q.m_l(len);
1127 for (i = 0; i < len; i++) {
1128 j = s_i(first + i);
1129 if (j > first + len) {
1130 cout << "permutation::restrict_to_subset() j > first + len, subset not invariant" << endl;
1131 exit(1);
1132 }
1133 if (j < first) {
1134 cout << "permutation::restrict_to_subset() j < first, subset not invariant" << endl;
1135 exit(1);
1136 }
1137 j -= first;
1138 q.s_i(i) = j;
1139 }
1140}
1141
1143 permutation &per, int verbose_level)
1144{
1145 int f_v = (verbose_level >= 1);
1146 int f_vv = (verbose_level >= 2);
1147 domain *dom;
1148 int nb_pts, nb_lines;
1149 int i, j, p1, p2, q1, q2;
1151
1152 if (f_v) {
1153 cout << "permutation::induce_on_lines_of_PG_k_q" << endl;
1154 }
1155 dom = allocate_finite_field_domain(q, verbose_level - 2);
1157 nb_pts = Gg.nb_PG_elements(k, q);
1158 nb_lines = nb_PG_lines(k, q);
1159 if (f_v) {
1160 cout << "nb_pts=" << nb_pts << " nb_lines=" << nb_lines << endl;
1161 }
1162 if (s_l() != nb_pts) {
1163 cout << "permutation::induce_on_lines_of_PG_k_q() s_l() != nb_pts" << endl;
1164 exit(1);
1165 }
1166 per.m_l(nb_lines);
1167 L.m_mn_n(k + 1, 2);
1168 {
1169 with ww(dom);
1170 for (i = 0; i < nb_lines; i++) {
1171 L.PG_line_unrank(i); // a matrix of two columns
1172 if (f_vv) {
1173 cout << "L=\n" << L << endl;
1174 }
1175 L.PG_point_rank(0, 0, 1, 0, k + 1, p1);
1176 if (f_vv) {
1177 cout << p1 << endl;
1178 }
1179 L.PG_point_rank(0, 1, 1, 0, k + 1, p2);
1180 if (f_vv) {
1181 cout << p2 << endl;
1182 }
1183 q1 = s_i(p1);
1184 q2 = s_i(p2);
1185 L.PG_point_unrank(0, 0, 1, 0, k + 1, q1);
1186 L.PG_point_unrank(0, 1, 1, 0, k + 1, q2);
1187 if (f_vv) {
1188 cout << "L'=\n" << L << endl;
1189 }
1190 L.PG_line_rank(j, verbose_level - 2);
1191 if (f_vv) {
1192 cout << "j=" << j << endl;
1193 }
1194 per.s_i(i) = j;
1195 if (f_vv) {
1196 cout << i << "=("<< p1 << "," << p2 << ") -> (" << q1 << "," << q2 << ") = " << j << endl;
1197 }
1198 }
1199 if (f_v) {
1200 cout << "the permutation \n" << *this << endl;
1201 cout << "on projective lines\n" << per << endl;
1202 }
1203 }
1204}
1205
1207 int f_modified, int verbose_level)
1208{
1209 int f_v = (verbose_level >= 1);
1210 unipoly a;
1212 int l;
1213 int f_action_from_right = TRUE;
1215
1216 a.Singer(p, 3, verbose_level - 2);
1217 cout << "permutation::singer_cycle_on_points_of_projective_plane(): primitive polynomial: " << a << endl;
1218
1219 domain *dom = allocate_finite_field_domain(p, verbose_level - 2);
1220 l = Gg.nb_PG_elements(2, p);
1221 m_l(l);
1222 {
1223 with ww(dom);
1224 M.m_mn_n(3, 3);
1225 M[1][0].one();
1226 M[2][1].one();
1227 M[0][2] = a[0];
1228 M[1][2] = a[1];
1229 M[2][2] = a[2];
1230 M[0][2].negate();
1231 M[1][2].negate();
1232 M[2][2].negate();
1233 M.transpose();
1234 cout << "as matrix:" << endl;
1235 cout << M << endl;
1236 M.PG_rep(*this, f_action_from_right, f_modified);
1237 }
1238 if (f_v) {
1239 cout << "singer cycle on points of projective plane of order "<< p << " : " << *this << endl;
1240 }
1241}
1242
1243void permutation::Cn_in_Cnm(int n, int m)
1244{
1245 int i, nm = n * m;
1246
1247 if (n < 1) {
1248 cout << "permutation::Cn_in_Cnm()n < 1" << endl;
1249 exit(1);
1250 }
1251 if (m < 1) {
1252 cout << "permutation::Cn_in_Cnm()m < 1" << endl;
1253 exit(1);
1254 }
1255 // the cycle (0,1, 2 ... ,nm-1):
1256 m_l(nm);
1257 one();
1258 for (i = 0; i < nm - 1; i++)
1259 m_ii(i, i + 1);
1260 m_ii(nm - 1, 0);
1261 power_int(m);
1262}
1263
1265{
1266 int j, l;
1267
1268 l = s_l();
1269 for (j = 0; j < l; j++) {
1270 if (s_i(j) == i)
1271 return j;
1272 }
1273 cout << "permutation::preimage() error: not a permutation" << endl;
1274 exit(1);
1275}
1276
1278{
1279 int i;
1280
1281 freeself();
1283 for (i = 0; i < l; i++) {
1284 s_i(i) = i;
1285 }
1286}
1287
1289{
1290 int sgn;
1291
1292 if (x.s_kind() != PERMUTATION) {
1293 cout << "signum_map() x must be a permutation" << endl;
1294 exit(1);
1295 }
1296 permutation & p = x.as_permutation();
1297 int f_v = FALSE;
1298 sgn = p.signum(f_v);
1300 d.m_i_i(sgn);
1301}
1302
1303#if 0
1304char get_character(istream & is, int f_v)
1305{
1306 char c;
1307
1308 if (!is) {
1309 cout << "get_character() at end" << endl;
1310 exit(1);
1311 }
1312 is >> c;
1313 if (f_v) {
1314 cout << "get_character: \"" << c << "\", ascii=" << (int)c << endl;
1315 }
1316 return c;
1317}
1318#endif
1319
1320}}
1321
1322
functions related to strings and character arrays
char get_character(std::istream &is, int verbose_level)
various functions related to geometries
Definition: geometry.h:721
DISCRETA vector class for vectors of DISCRETA objects.
Definition: discreta.h:797
Vector & append_integer(int a)
Definition: vector.cpp:390
discreta_base & s_i(int i)
Definition: vector.cpp:202
void m_ii(int i, int a)
Definition: discreta.h:824
bool search(discreta_base &x, int *idx)
Definition: vector.cpp:477
DISCRETA base class. All DISCRETA classes are derived from this class.
Definition: discreta.h:382
void swap(discreta_base &a)
Definition: base.cpp:179
void copyobject(discreta_base &x)
Definition: base.cpp:194
discreta_base & power_int(int l)
Definition: base.cpp:447
void PG_point_unrank(int i0, int j0, int di, int dj, int length, int a)
discreta_matrix & m_mn_n(int m, int n)
void PG_rep(domain *dom, permutation &p, int f_action_from_right, int f_modified)
void PG_point_rank(int i0, int j0, int di, int dj, int length, int &a)
DISCRETA class for influencing arithmetic operations.
Definition: discreta.h:1360
DISCRETA string class.
Definition: discreta.h:626
DISCRETA class to serialize data structures.
Definition: discreta.h:582
DISCRETA permutation class.
Definition: discreta.h:976
void read_mem(memory &m, int debug_depth)
void embed_at(permutation &b, int n, int at)
void remove_fixpoint(permutation &b, int i)
void AddNCycle(int first, int len)
std::ostream & print(std::ostream &)
void sscan(const char *s, int verbose_level)
void Add3Cycle(int i0, int i1, int i2)
void copyobject_to(discreta_base &x)
void write_mem(memory &m, int debug_depth)
void Add5Cycle(int i0, int i1, int i2, int i3, int i4)
void add_n_fixpoints_in_front(permutation &b, int n)
void cycle_type(Vector &type, int verbose_level)
std::ostream & print_cycle(std::ostream &ost)
void add_fixpoint_in_front(permutation &b)
void induce_on_2tuples(permutation &p, int f_injective)
void mult_to(discreta_base &x, discreta_base &y)
void cartesian_product_action(permutation &a, permutation &b)
void set_print_type_PG_1_q_element(domain *dom)
Definition: permutation.cpp:41
void add_n_fixpoints_at_end(permutation &b, int n)
void Add4Cycle(int i0, int i1, int i2, int i3)
void induce_on_lines_of_PG_k_q(int k, int q, permutation &per, int verbose_level)
void induce_action_on_blocks(permutation &gg, Vector &B)
std::ostream & print_list(std::ostream &ost)
int nb_of_inversions(int verbose_level)
permutation & operator=(const discreta_base &x)
Definition: permutation.cpp:93
void restrict_to_subset(permutation &q, int first, int len)
void singer_cycle_on_points_of_projective_plane(int p, int f_modified, int verbose_level)
void join(permutation &a, permutation &b)
void convert_digit(int i, hollerith &a)
Definition: permutation.cpp:47
void scan(std::istream &is, int verbose_level)
DISCRETA class for polynomials in one variable.
Definition: discreta.h:1236
void Singer(int p, int f, int verbose_level)
Definition: unipoly.cpp:564
DISCRETA class related to class domain.
Definition: discreta.h:1413
#define TRUE
Definition: foundations.h:231
#define FALSE
Definition: foundations.h:234
#define EVEN(x)
Definition: foundations.h:221
#define ONE_char_int(a)
Definition: foundations.h:225
#define MAXIMUM(x, y)
Definition: foundations.h:217
domain * allocate_finite_field_domain(int q, int verbose_level)
Definition: domain.cpp:378
enum printing_mode_enum current_printing_mode()
Definition: global.cpp:1573
discreta_base * calloc_nobjects_plus_length(int n, kind k)
Definition: global.cpp:121
void free_nobjects_plus_length(discreta_base *p)
Definition: global.cpp:144
void tuple2_rank(int rank, int &i, int &j, int n, int f_injective)
Definition: global.cpp:1327
domain * current_permutation_print_type_dom
Definition: permutation.cpp:29
void signum_map(discreta_base &x, discreta_base &d)
int nb_PG_lines(int n, int q)
@ PERMUTATION
PERMUTATION.
Definition: discreta.h:57
int tuple2_unrank(int i, int j, int n, int f_injective)
Definition: global.cpp:1349
enum permutation_print_type current_permutation_print_type
Definition: permutation.cpp:28
the orbiter library for the classification of combinatorial objects
DISCRETA internal class.
Definition: discreta.h:353