Orbiter 2022
Combinatorial Objects
canonical_form_classifier.cpp
Go to the documentation of this file.
1/*
2 * canonical_form_classifier.cpp
3 *
4 * Created on: Apr 24, 2021
5 * Author: betten
6 */
7
8
9
10
11#include "orbiter.h"
12
13using namespace std;
14
15namespace orbiter {
16namespace layer5_applications {
17namespace projective_geometry {
18
19
20
22{
23 Descr = NULL;
24 Poly_ring = NULL;
25 AonHPD = NULL;
27 CB = NULL;
29 alpha = NULL;
30 gamma = NULL;
31
32 SubC = NULL;
33
34 Elt = NULL;
35 eqn2 = NULL;
36
37 //canonical_equation = NULL;
38 //transporter_to_canonical_form = NULL;
39 //longinteger_object go_eqn;
40
41 CFS_table = NULL;
42 counter = 0;
43 Canonical_forms = NULL;
44 Goi = NULL;
45
47
48 transversal = NULL;
49 frequency = NULL;
50 nb_types = 0;
51
52}
53
55{
56
57}
58
60{
61 int f_v = (verbose_level >= 1);
62 int cnt;
63
64 if (f_v) {
65 cout << "canonical_form_classifier::count_nb_objects_to_test" << endl;
66 }
67
69
70
71 for (cnt = 0; cnt < Descr->nb_files; cnt++) {
72
73 char str[1000];
74 string fname;
75
76 sprintf(str, Descr->fname_mask.c_str(), cnt);
77 fname.assign(str);
78
80
81 S.read_spreadsheet(fname, verbose_level);
82
84
85 if (f_v) {
86 cout << "canonical_form_classifier::count_nb_objects_to_test "
87 "file " << cnt << " / " << Descr->nb_files << " has "
88 << S.nb_rows - 1 << " objects" << endl;
89 }
90 }
91
92 if (f_v) {
93 cout << "canonical_form_classifier::count_nb_objects_to_test "
94 "nb_objects_to_test=" << nb_objects_to_test << endl;
95 }
96}
97
98
100 int verbose_level)
101{
102 int f_v = (verbose_level >= 1);
103
104
105 if (f_v) {
106 cout << "canonical_form_classifier::classify";
108 cout << " using nauty" << endl;
109 }
111 cout << " using substructure" << endl;
112 }
113 }
114
115
116
117
119
120
121 if (!Descr->f_degree) {
122 cout << "canonical_form_classifier::classify please use -degree <d> to specify the degree" << endl;
123 exit(1);
124 }
125 if (!Descr->f_fname_base_out) {
126 cout << "please use -fname_base_out" << endl;
127 exit(1);
128 }
129
131 Poly_ring->init(Descr->PA->F, Descr->PA->n + 1, Descr->degree, FALSE, t_PART, verbose_level);
132
133
135 if (f_v) {
136 cout << "canonical_form_classifier::classify "
137 "before AonHPD->init" << endl;
138 }
139 AonHPD->init(Descr->PA->A, Poly_ring, verbose_level);
140 if (f_v) {
141 cout << "canonical_form_classifier::classify "
142 "after AonHPD->init" << endl;
143 }
144
145
146
147
148 if (f_v) {
149 cout << "canonical_form_classifier::classify "
150 "before count_nb_objects_to_test" << endl;
151 }
152
153 count_nb_objects_to_test(verbose_level);
154
155
156 if (f_v) {
157 cout << "canonical_form_classifier::classify "
158 "nb_objects_to_test=" << nb_objects_to_test << endl;
159 }
160
163
164
165
168
170 if (f_v) {
171 cout << "canonical_form_classifier::classify "
172 "before classify_nauty" << endl;
173 }
174 classify_nauty(verbose_level);
175 if (f_v) {
176 cout << "canonical_form_classifier::classify "
177 "after classify_nauty" << endl;
178 }
179 }
181
182 if (f_v) {
183 cout << "canonical_form_classifier::classify "
184 "before classify_with_substructure" << endl;
185 }
186 classify_with_substructure(verbose_level);
187 if (f_v) {
188 cout << "canonical_form_classifier::classify "
189 "after classify_with_substructure" << endl;
190 }
191 }
192 else {
193 cout << "canonical_form_classifier::classify please select which algorithm to use" << endl;
194 exit(1);
195 }
196
197 //FREE_int(eqn2);
198 //FREE_int(Elt);
199 //FREE_int(canonical_equation);
200 //FREE_int(transporter_to_canonical_form);
201
202
203 int i, j;
204
205 cout << "canonical forms:" << endl;
206 for (i = 0; i < nb_objects_to_test; i++) {
207 cout << setw(2) << i << " : ";
209 cout << " : " << Goi[i] << endl;
210 }
211
213
215
216
218 transversal, frequency, nb_types, verbose_level);
219
220
221 cout << "Classification of curves:" << endl;
222
223
224 cout << "transversal:" << endl;
226 cout << endl;
227
228 //Classification_of_quartic_curves->print();
229
230 for (i = 0; i < Classification_of_quartic_curves->nb_types; i++) {
231
232 //h = int_vec_hash(Reps + i * data_set_sz, data_set_sz);
233
234 cout << i << " : " << Classification_of_quartic_curves->Frequency[i] << " x ";
235 Int_vec_print(cout,
238 cout << " : ";
240 cout << Goi[j] << " : ";
241 Int_vec_print(cout,
244 cout << endl;
245#if 0
246 cout << "for elements ";
247 int_vec_print(cout, sorting_perm_inv + type_first[i], Frequency[i]);
248 cout << endl;
249#endif
250 }
251
252
253 if (f_v) {
254 cout << "canonical_form_classifier::classify "
255 "before write_canonical_forms_csv" << endl;
256 }
259 verbose_level);
260 if (f_v) {
261 cout << "canonical_form_classifier::classify "
262 "after write_canonical_forms_csv" << endl;
263 }
264
265
266 if (f_v) {
267 cout << "canonical_form_classifier::classify "
268 "before generate_source_code" << endl;
269 }
270
274 verbose_level);
275
276 if (f_v) {
277 cout << "canonical_form_classifier::classify "
278 "after generate_source_code" << endl;
279 }
280
281
282 if (f_v) {
283 cout << "canonical_form_classifier::classify done" << endl;
284 }
285}
286
287
289{
290 int f_v = (verbose_level >= 1);
291
292
293 if (f_v) {
294 cout << "canonical_form_classifier::classify_nauty" << endl;
295 }
296
297
299
300
301
302
303 main_loop(verbose_level);
304
305 if (f_v) {
306 cout << "canonical_form_classifier::classify_nauty The number of isomorphism types is " << CB->nb_types << endl;
307 }
308
309
310}
311
313{
314 int f_v = (verbose_level >= 1);
315
316
317 if (f_v) {
318 cout << "canonical_form_classifier::classify_with_substructure, "
319 "Descr->substructure_size=" << Descr->substructure_size << endl;
320 }
321
322
323
324
326
327 if (f_v) {
328 cout << "canonical_form_classifier::classify_with_substructure before SubC->classify_substructures" << endl;
329 }
330
333 Descr->PA->A,
334 Descr->PA->A,
337 verbose_level - 3);
338
339 if (f_v) {
340 cout << "canonical_form_classifier::classify_with_substructure "
341 "after SubC->classify_substructures" << endl;
342 cout << "canonical_form_classifier::classify_with_substructure "
343 "We found " << SubC->nb_orbits
344 << " orbits at level " << Descr->substructure_size << ":" << endl;
345 }
346
347
348
350
351
352
353
354 if (f_v) {
355 cout << "canonical_form_classifier::classify_with_substructure before main_loop" << endl;
356 }
357 main_loop(verbose_level);
358 if (f_v) {
359 cout << "canonical_form_classifier::classify_with_substructure after main_loop" << endl;
360 }
361
362
363
364 if (f_v) {
365 cout << "canonical_form_classifier::classify_with_substructure done" << endl;
366 }
367
368}
369
370
372{
373 int f_v = (verbose_level >= 1);
374 int cnt;
375
376
377
378 if (f_v) {
379 cout << "canonical_form_classifier::main_loop" << endl;
380 }
381
382 string fname_case_out;
383
384
385 counter = 0;
386
387 for (cnt = 0; cnt < Descr->nb_files; cnt++) {
388 char str[1000];
389 string fname;
390 int row;
391
392 sprintf(str, Descr->fname_mask.c_str(), cnt);
393 fname.assign(str);
394
396
397 S.read_spreadsheet(fname, verbose_level);
398
399 if (f_v) {
400 cout << "canonical_form_classifier::classify_nauty S.nb_rows = " << S.nb_rows << endl;
401 cout << "canonical_form_classifier::classify_nauty S.nb_cols = " << S.nb_cols << endl;
402 }
403
404
405
406
407 for (row = 0; row < S.nb_rows - 1; row++, counter++) {
408
409 if (f_v) {
410 cout << "cnt = " << cnt << " / " << Descr->nb_files << " row = " << row << " / " << S.nb_rows - 1 << endl;
411 }
412
413 sprintf(str, "_cnt%d", counter);
414
415 fname_case_out.assign(Descr->fname_base_out);
416 fname_case_out.append(str);
417
418 int j, t;
419 string eqn_txt;
420 string pts_txt;
421 string bitangents_txt;
422 int *eqn;
423 int sz;
424 long int *pts;
425 int nb_pts;
426 long int *bitangents;
427 int nb_bitangents;
428
429 j = 1;
430 t = S.Table[(row + 1) * S.nb_cols + j];
431 if (S.tokens[t] == NULL) {
432 cout << "canonical_form_classifier::classify_nauty token[t] == NULL" << endl;
433 }
434 eqn_txt.assign(S.tokens[t]);
435 j = 2;
436 t = S.Table[(row + 1) * S.nb_cols + j];
437 if (S.tokens[t] == NULL) {
438 cout << "canonical_form_classifier::classify_nauty token[t] == NULL" << endl;
439 }
440 pts_txt.assign(S.tokens[t]);
441 j = 3;
442 t = S.Table[(row + 1) * S.nb_cols + j];
443 if (S.tokens[t] == NULL) {
444 cout << "canonical_form_classifier::classify_nauty token[t] == NULL" << endl;
445 }
446 bitangents_txt.assign(S.tokens[t]);
447
449
450 ST.remove_specific_character(eqn_txt, '\"');
451 ST.remove_specific_character(pts_txt, '\"');
452 ST.remove_specific_character(bitangents_txt, '\"');
453
454 if (FALSE) {
455 cout << "row = " << row << " eqn=" << eqn_txt << " pts_txt=" << pts_txt << " =" << bitangents_txt << endl;
456 }
457
458 Int_vec_scan(eqn_txt, eqn, sz);
459 Lint_vec_scan(pts_txt, pts, nb_pts);
460 Lint_vec_scan(bitangents_txt, bitangents, nb_bitangents);
461
462 if (FALSE) {
463 cout << "row = " << row << " eqn=";
464 Int_vec_print(cout, eqn, sz);
465 cout << " pts=";
466 Lint_vec_print(cout, pts, nb_pts);
467 cout << " bitangents=";
468 Lint_vec_print(cout, bitangents, nb_bitangents);
469 cout << endl;
470 }
471
472
473 //quartic_curve_object::init_equation_and_bitangents(quartic_curve_domain *Dom,
474 // int *eqn15, long int *bitangents28,
475 // int verbose_level)
476
477
479 if (f_v) {
480 cout << "canonical_form_classifier::main_loop "
481 "before classify_curve_nauty" << endl;
482 }
483
484
485 int *canonical_equation;
486 int *transporter_to_canonical_form;
487
488 canonical_equation = NEW_int(Poly_ring->get_nb_monomials());
489 transporter_to_canonical_form = NEW_int(Descr->PA->A->elt_size_in_int);
490
491
492 classify_curve_nauty(cnt, row,
493 eqn, sz, pts, nb_pts, bitangents, nb_bitangents,
494 canonical_equation,
495 transporter_to_canonical_form,
496 verbose_level);
497
498 Int_vec_copy(canonical_equation,
501
502 FREE_int(canonical_equation);
503 FREE_int(transporter_to_canonical_form);
504
505 if (f_v) {
506 cout << "canonical_form_classifier::main_loop "
507 "after classify_curve_nauty" << endl;
508 }
509 }
511
512
513
514
515
516 if (nb_pts >= Descr->substructure_size) {
517
518 if (f_v) {
519 cout << "canonical_form_classifier::main_loop "
520 "before CFS->classify_curve_with_substructure" << endl;
521 }
522
524
526
528
530 this,
531 counter, cnt, row,
532 fname_case_out,
533 eqn,
534 sz,
535 pts,
536 nb_pts,
537 bitangents,
538 nb_bitangents,
539 go_eqn,
540 verbose_level);
541
542 CFS_table[counter] = CFS;
546 Goi[counter] = go_eqn.as_lint();
547
548 if (f_v) {
549 cout << "canonical_form_classifier::main_loop "
550 "after CFS->classify_curve_with_substructure" << endl;
551 }
552 }
553 else {
554
555
556 if (f_v) {
557 cout << "canonical_form_classifier::main_loop "
558 "too small for substructure algorithm. Skipping" << endl;
559 }
560
561 CFS_table[counter] = NULL;
565 Goi[counter] = -1;
566
567 }
568 }
569 else {
570 cout << "canonical_form_classifier::main_loop please select which algorithm to use" << endl;
571 exit(1);
572 }
573
574#if 0
575 FREE_int(eqn);
576 FREE_lint(pts);
577 FREE_lint(bitangents);
578#endif
579
580 } // next row
581
582
583 } // next cnt
584
585 if (f_v) {
586 cout << "canonical_form_classifier::main_loop done" << endl;
587 }
588}
589
590
592 int *eqn,
593 int sz,
594 long int *pts,
595 int nb_pts,
596 long int *bitangents,
597 int nb_bitangents,
598 int *canonical_equation,
599 int *transporter_to_canonical_form,
600 int verbose_level)
601{
602 int f_v = (verbose_level >= 1);
603
604 if (f_v) {
605 cout << "canonical_form_classifier::classify_curve_nauty" << endl;
606 }
607
610
611 groups::strong_generators *gens_stab_of_canonical_equation;
612
613
614
615
616
617
619
620 C->quartic_curve(
621 Descr->PA,
622 Poly_ring,
623 AonHPD,
624 row, eqn, sz,
625 pts, nb_pts,
626 bitangents, nb_bitangents,
627 canonical_equation,
628 transporter_to_canonical_form,
629 gens_stab_of_canonical_equation,
630 verbose_level);
631
633
634 FREE_OBJECT(gens_stab_of_canonical_equation);
635
639
640
641 if (CB->n == 0) {
644 verbose_level);
645 }
646 int f_found;
647 int idx;
648
649 CB->search_and_add_if_new(C->Canonical_form->get_data(), C /* void *extra_data */, f_found, idx, verbose_level);
650
651
652 if (!f_found) {
653 if (f_v) {
654 cout << "After search_and_add_if_new, cnt = " << cnt << " row = " << row << " The canonical form is new" << endl;
655 }
656 }
657 else {
658 if (f_v) {
659 cout << "After search_and_add_if_new, cnt = " << cnt << " row = " << row << " We found the canonical form at idx = " << idx << endl;
660 }
661
662
663
664
665 long int *alpha_inv;
666 long int *beta_inv;
667 int i, j;
668
669 //long int *canonical_labeling;
670
671
672
673
674 int idx1;
675 int found_at = -1;
676
677 if (f_v) {
678 cout << "starting loop over idx1" << endl;
679 }
680
681 for (idx1 = idx; idx1 >= 0; idx1--) {
682
683
684
685 // test if entry at idx1 is equal to C.
686 // if not, break
687
688 if (f_v) {
689 cout << "canonical_form_classifier::classify_curve_nauty before CB->compare_at idx1 = " << idx1 << endl;
690 }
691 if (CB->compare_at(C->Canonical_form->get_data(), idx1) != 0) {
692 if (f_v) {
693 cout << "canonical_form_classifier::classify_curve_nauty at idx1 = " << idx1 << " is not equal, break" << endl;
694 }
695 break;
696 }
697 if (f_v) {
698 cout << "canonical_form_classifier::classify_curve_nauty canonical form at " << idx1 << " is equal" << endl;
699 }
700
701
704
705 alpha_inv = C1->canonical_labeling;
706
707 beta_inv = C->canonical_labeling;
708
709 // compute gamma = beta * alpha^-1
710
711
712 if (f_v) {
713 cout << "canonical_form_classifier::classify_curve_nauty computing alpha" << endl;
714 }
715 for (i = 0; i < canonical_labeling_len; i++) {
716 j = alpha_inv[i];
717 alpha[j] = i;
718 }
719
720 if (f_v) {
721 cout << "canonical_form_classifier::classify_curve_nauty computing gamma" << endl;
722 }
723 for (i = 0; i < canonical_labeling_len; i++) {
724 gamma[i] = beta_inv[alpha[i]];
725 }
726
727
728 // gamma maps C1 to C.
729 // So, in the contragredient action, it maps the equation of C to the equation of C1,
730 // which is what we want.
731
732 // turn gamma into a matrix
733
734
735 int Mtx[10];
736 //int Mtx_inv[10];
737 int frobenius;
738
739 if (f_v) {
740 cout << "canonical_form_classifier::classify_curve_nauty before PA->P->reverse_engineer_semilinear_map" << endl;
741 }
743 gamma, Mtx, frobenius,
744 0 /*verbose_level*/);
745 if (f_v) {
746 cout << "canonical_form_classifier::classify_curve_nauty after PA->P->reverse_engineer_semilinear_map" << endl;
747 }
748
749 Mtx[9] = frobenius;
750
751 Descr->PA->A->make_element(Elt, Mtx, 0 /* verbose_level*/);
752
753 if (f_v) {
754 cout << "The isomorphism from C to C1 is given by:" << endl;
755 Descr->PA->A->element_print(Elt, cout);
756 }
757
758
759
760 //int frobenius_inv;
761
762 //frobenius_inv = NT.int_negate(Mtx[3 * 3], PA->F->e);
763
764
765 //PA->F->matrix_inverse(Mtx, Mtx_inv, 3, 0 /* verbose_level*/);
766
767 if (f_v) {
768 cout << "canonical_form_classifier::classify_curve_nauty before substitute_semilinear" << endl;
769 }
770 Poly_ring->substitute_semilinear(C->eqn /* coeff_in */, eqn2 /* coeff_out */,
771 Descr->PA->A->is_semilinear_matrix_group(), frobenius, Mtx, 0/*verbose_level*/);
772 if (f_v) {
773 cout << "canonical_form_classifier::classify_curve_nauty after substitute_semilinear" << endl;
774 }
775
777
778
779 if (f_v) {
780 cout << "The mapped equation is:";
782 cout << endl;
783 }
784
785
786
787
788 int idx2;
789
790 if (!C1->Orb->search_equation(eqn2 /*new_object */, idx2, TRUE)) {
791 // need to map points and bitangents under gamma:
792 if (f_v) {
793 cout << "we found the canonical form but we did not find the equation at idx1=" << idx1 << endl;
794 }
795
796
797 }
798 else {
799 if (f_v) {
800 cout << "After search_and_add_if_new, cnt = " << cnt << " row = " << row << " We found the canonical form and the equation at idx2 " << idx2 << ", idx1=" << idx1 << endl;
801 }
802 found_at = idx1;
803 break;
804 }
805
806
807 }
808
809
810 if (found_at == -1) {
811
812 if (f_v) {
813 cout << "we found the canonical form but we did not find the equation" << endl;
814 }
815
816 long int *pts2;
817 //int nb_pts;
818 long int *bitangents2;
819 //int nb_bitangents;
820 int i;
821
822 pts2 = NEW_lint(nb_pts);
823 bitangents2 = NEW_lint(nb_bitangents);
824
825 for (i = 0; i < nb_pts; i++) {
826 pts2[i] = Descr->PA->A->element_image_of(pts[i], Elt, 0 /* verbose_level */);
827 }
828 for (i = 0; i < nb_bitangents; i++) {
829 bitangents2[i] = Descr->PA->A_on_lines->element_image_of(bitangents[i], Elt, 0 /* verbose_level */);
830 }
831
834
835
837
838 if (f_v) {
839 cout << "we recompute the quartic curve from the canonical equation." << endl;
840 }
841 if (f_v) {
842 cout << "canonical_form_classifier::classify_curve_nauty before C2->quartic_curve" << endl;
843 }
844 C2->quartic_curve(
845 Descr->PA,
846 Poly_ring,
847 AonHPD,
848 row, eqn2, sz,
849 pts2, nb_pts,
850 bitangents2, nb_bitangents,
851 canonical_equation,
852 transporter_to_canonical_form,
853 gens_stab_of_canonical_equation,
854 verbose_level);
855 if (f_v) {
856 cout << "canonical_form_classifier::classify_curve_nauty after C2->quartic_curve" << endl;
857 }
858
859 if (f_v) {
860 cout << "After search_and_add_if_new, adding at " << idx << endl;
861 }
862 CB->add_at_idx(C2->Canonical_form->get_data(), C2 /* void *extra_data */, idx, 0 /* verbose_level*/);
863
864
865 } // if (found_at == -1)
866 else {
867 if (f_v) {
868 cout << "we found the equation at index " << found_at << endl;
869 }
870
871 }
872
873 } // if f_found
874
877
878 if (f_v) {
879 cout << "canonical_form_classifier::classify_curve_nauty done" << endl;
880 }
881
882}
883
884
886 std::string &fname_base,
887 int verbose_level)
888{
889 int f_v = (verbose_level >= 1);
890 //int f_vv = (verbose_level >= 2);
891 std::string fname;
892 int i, j;
894
895 int nb_orbits;
896 int nb_monomials;
897
899 actions::action *A_on_lines;
900
901 if (f_v) {
902 cout << "canonical_form_classifier::write_canonical_forms_csv" << endl;
903 }
904 fname.assign(fname_base);
905 fname.append("_canonical_form.csv");
906
907
909 nb_monomials = Poly_ring->get_nb_monomials();
910
911
912 A = Descr->PA->A;
913 A_on_lines = Descr->PA->A_on_lines;
914
915
916 {
917 ofstream ost(fname.c_str());
918
919 ost << "ROW,SourceFile,SourceRow,Eqn,Pts,Lines,Transporter,CanEqn,CanPts,CanLines,AutTl,AutGens,Ago" << endl;
920 for (i = 0; i < nb_objects_to_test; i++) {
921
922 if (f_v) {
923 cout << "canonical_form_classifier::write_canonical_forms_csv i=" << i << " / " << nb_objects_to_test << endl;
924 }
925
926 if (CFS_table[i] == NULL) {
927 continue;
928 }
929
930 ost << i;
931 ost << ",";
932 ost << CFS_table[i]->cnt;
933 ost << ",";
934 ost << CFS_table[i]->row;
935 ost << ",";
936
937 //Orbiter->Int_vec.print(cout, Canonical_forms + i * Poly_ring->get_nb_monomials(), Poly_ring->get_nb_monomials());
938 //cout << " : " << Goi[i] << endl;
939
940 {
941 string str;
943 ost << str;
944 }
945 ost << ",";
946 {
947 string str;
949 ost << str;
950 }
951 ost << ",";
952 {
953 string str;
955 ost << str;
956 }
957 ost << ",";
958 {
959 string str;
961 ost << str;
962 }
963 ost << ",";
964 {
965 string str;
966 orbiter_kernel_system::Orbiter->Int_vec->create_string_with_quotes(str, CFS_table[i]->canonical_equation, nb_monomials);
967 ost << str;
968 }
969 ost << ",";
970
971
972 long int *Pts_orig;
973 long int *Pts_canonical;
974
975 Pts_orig = CFS_table[i]->pts;
976 Pts_canonical = NEW_lint(CFS_table[i]->nb_pts);
977 for (j = 0; j < CFS_table[i]->nb_pts; j++) {
978 Pts_canonical[j] = A->element_image_of(Pts_orig[j], CFS_table[i]->transporter_to_canonical_form, 0 /* verbose_level */);
979 }
980 Sorting.lint_vec_heapsort(Pts_canonical, CFS_table[i]->nb_pts);
981
982
983 {
984 string str;
986 ost << str;
987 }
988 ost << ",";
989
990
991 long int *bitangents_orig;
992 long int *bitangents_canonical;
993
994 bitangents_orig = CFS_table[i]->bitangents;
995 bitangents_canonical = NEW_lint(CFS_table[i]->nb_bitangents);
996 for (j = 0; j < CFS_table[i]->nb_bitangents; j++) {
997 bitangents_canonical[j] = A_on_lines->element_image_of(bitangents_orig[j], CFS_table[i]->transporter_to_canonical_form, 0 /* verbose_level */);
998 }
999
1000 //Sorting.lint_vec_heapsort(bitangents_canonical, CFS_table[i]->nb_bitangents);
1001
1002 {
1003 string str;
1004 orbiter_kernel_system::Orbiter->Lint_vec->create_string_with_quotes(str, bitangents_canonical, CFS_table[i]->nb_bitangents);
1005 ost << str;
1006 }
1007 ost << ",";
1008
1010
1012
1013 {
1014 string str;
1016 ost << str;
1017 }
1018 ost << ",";
1019
1020 {
1021 string str;
1022
1023 gens->get_gens_data_as_string_with_quotes(str, 0 /*verbose_level*/);
1024 ost << str;
1025 }
1026 ost << ",";
1028
1029 gens->group_order(go);
1030 ost << go << endl;
1031
1032
1033 }
1034 ost << "END" << endl;
1035 }
1036
1037
1039
1040 cout << "written file " << fname << " of size "
1041 << Fio.file_size(fname.c_str()) << endl;
1042 if (f_v) {
1043 cout << "canonical_form_classifier::write_canonical_forms_csv done" << endl;
1044 }
1045}
1046
1047
1048
1050 std::string &fname_base,
1051 data_structures::tally_vector_data *Classification_of_quartic_curves,
1052 int verbose_level)
1053{
1054 int f_v = (verbose_level >= 1);
1055 int f_vv = (verbose_level >= 2);
1056 std::string fname;
1057 int orbit_index;
1058 int i, j;
1059
1060 int nb_orbits;
1061 int nb_monomials;
1062
1063 actions::action *A;
1064 actions::action *A_on_lines;
1065
1066 if (f_v) {
1067 cout << "canonical_form_classifier::generate_source_code" << endl;
1068 }
1069 fname.assign(fname_base);
1070 fname.append(".cpp");
1071
1072
1074 nb_monomials = Poly_ring->get_nb_monomials();
1075
1076
1077 A = Descr->PA->A;
1078 A_on_lines = Descr->PA->A_on_lines;
1079
1080 {
1081 ofstream f(fname.c_str());
1082
1083 f << "static int " << fname_base.c_str() << "_nb_reps = "
1084 << nb_orbits << ";" << endl;
1085 f << "static int " << fname_base.c_str() << "_size = "
1086 << nb_monomials << ";" << endl;
1087
1088
1089
1090 if (f_v) {
1091 cout << "canonical_form_classifier::generate_source_code "
1092 "preparing reps" << endl;
1093 }
1094 f << "// the equations:" << endl;
1095 f << "static int " << fname_base.c_str() << "_reps[] = {" << endl;
1096 for (orbit_index = 0;
1097 orbit_index < nb_orbits;
1098 orbit_index++) {
1099
1100
1101 int *equation;
1102
1103 if (f_v) {
1104 cout << "canonical_form_classifier::generate_source_code "
1105 "orbit_index = " << orbit_index << endl;
1106 }
1107
1108 int idx;
1109
1111
1113
1114
1115 if (CFS) {
1116 //equation = Classification_of_quartic_curves->Reps + orbit_index * Classification_of_quartic_curves->data_set_sz;
1118
1119 f << "\t";
1120 for (i = 0; i < nb_monomials; i++) {
1121 f << equation[i];
1122 f << ", ";
1123 }
1124 f << endl;
1125 }
1126 else {
1127 f << "\t";
1128 for (i = 0; i < nb_monomials; i++) {
1129 f << 0;
1130 f << ", ";
1131 }
1132 f << "// problem" << endl;
1133
1134 }
1135
1136 }
1137 f << "};" << endl;
1138
1139
1140
1141 if (f_v) {
1142 cout << "canonical_form_classifier::generate_source_code "
1143 "preparing stab_order" << endl;
1144 }
1145 f << "// the stabilizer orders:" << endl;
1146 f << "static const char *" << fname_base.c_str() << "_stab_order[] = {" << endl;
1147 for (orbit_index = 0;
1148 orbit_index < nb_orbits;
1149 orbit_index++) {
1150
1152
1153 int idx;
1154
1156
1157
1158 ago.create(Goi[idx], __FILE__, __LINE__);
1159
1160 f << "\t\"";
1161
1162 ago.print_not_scientific(f);
1163 f << "\"," << endl;
1164
1165 }
1166 f << "};" << endl;
1167
1168
1169
1170
1171
1172 if (f_v) {
1173 cout << "canonical_form_classifier::generate_source_code "
1174 "preparing Bitangents" << endl;
1175 }
1176 f << "// the 28 bitangents:" << endl;
1177 f << "static long int " << fname_base.c_str() << "_Bitangents[] = { " << endl;
1178
1179
1180 for (orbit_index = 0;
1181 orbit_index < nb_orbits;
1182 orbit_index++) {
1183
1184
1185 if (f_v) {
1186 cout << "canonical_form_classifier::generate_source_code "
1187 "orbit_index = " << orbit_index << endl;
1188 }
1189
1190 int idx;
1191
1193
1195
1196
1197 if (CFS) {
1198 long int *bitangents_orig;
1199 long int *bitangents_canonical;
1200
1201 bitangents_orig = CFS->bitangents;
1202 bitangents_canonical = NEW_lint(CFS->nb_bitangents);
1203 for (j = 0; j < CFS->nb_bitangents; j++) {
1204 bitangents_canonical[j] = A_on_lines->element_image_of(bitangents_orig[j], CFS->transporter_to_canonical_form, 0 /* verbose_level */);
1205 }
1206
1207
1208
1209
1210 f << "\t";
1211 for (j = 0; j < 28; j++) {
1212 f << bitangents_canonical[j];
1213 f << ", ";
1214 }
1215 f << endl;
1216 }
1217 else {
1218 f << "\t";
1219 for (j = 0; j < 28; j++) {
1220 f << 0;
1221 f << ", ";
1222 }
1223 f << "// problem" << endl;
1224
1225 }
1226
1227 }
1228 f << "};" << endl;
1229
1230 f << "static int " << fname_base.c_str() << "_make_element_size = "
1231 << A->make_element_size << ";" << endl;
1232
1233 {
1234 int *stab_gens_first;
1235 int *stab_gens_len;
1236 int fst;
1237
1238
1239
1240 stab_gens_first = NEW_int(nb_orbits);
1241 stab_gens_len = NEW_int(nb_orbits);
1242 fst = 0;
1243 for (orbit_index = 0;
1244 orbit_index < nb_orbits;
1245 orbit_index++) {
1246
1247
1249
1250 int idx;
1251
1253
1255 //gens = CFS->Gens_stabilizer_canonical_form;
1256 if (CFS) {
1258
1259
1260 stab_gens_first[orbit_index] = fst;
1261 stab_gens_len[orbit_index] = gens->gens->len;
1262 fst += stab_gens_len[orbit_index];
1263 }
1264 else {
1265 stab_gens_first[orbit_index] = fst;
1266 stab_gens_len[orbit_index] = 0;
1267 fst += 0;
1268
1269 }
1270 }
1271
1272
1273 if (f_v) {
1274 cout << "canonical_form_classifier::generate_source_code "
1275 "preparing stab_gens_fst" << endl;
1276 }
1277 f << "static int " << fname_base.c_str() << "_stab_gens_fst[] = { " << endl << "\t";
1278 for (orbit_index = 0;
1279 orbit_index < nb_orbits;
1280 orbit_index++) {
1281 f << stab_gens_first[orbit_index];
1282 if (orbit_index < nb_orbits - 1) {
1283 f << ", ";
1284 }
1285 if (((orbit_index + 1) % 10) == 0) {
1286 f << endl << "\t";
1287 }
1288 }
1289 f << "};" << endl;
1290
1291 if (f_v) {
1292 cout << "canonical_form_classifier::generate_source_code "
1293 "preparing stab_gens_len" << endl;
1294 }
1295 f << "static int " << fname_base.c_str() << "_stab_gens_len[] = { " << endl << "\t";
1296 for (orbit_index = 0;
1297 orbit_index < nb_orbits;
1298 orbit_index++) {
1299 f << stab_gens_len[orbit_index];
1300 if (orbit_index < nb_orbits - 1) {
1301 f << ", ";
1302 }
1303 if (((orbit_index + 1) % 10) == 0) {
1304 f << endl << "\t";
1305 }
1306 }
1307 f << "};" << endl;
1308
1309
1310 if (f_v) {
1311 cout << "canonical_form_classifier::generate_source_code "
1312 "preparing stab_gens" << endl;
1313 }
1314 f << "static int " << fname_base.c_str() << "_stab_gens[] = {" << endl;
1315 for (orbit_index = 0;
1316 orbit_index < nb_orbits;
1317 orbit_index++) {
1318 int j;
1319
1320 for (j = 0; j < stab_gens_len[orbit_index]; j++) {
1321 if (f_vv) {
1322 cout << "canonical_form_classifier::generate_source_code "
1323 "before extract_strong_generators_in_order "
1324 "generator " << j << " / "
1325 << stab_gens_len[orbit_index] << endl;
1326 }
1327 f << "\t";
1328
1330
1331 int idx;
1332
1334
1336 //gens = CFS->Gens_stabilizer_canonical_form;
1337 if (CFS) {
1339
1340
1341 A->element_print_for_make_element(gens->gens->ith(j), f);
1342 f << endl;
1343 }
1344 else {
1345 f << "// problem" << endl;
1346 }
1347 }
1348 }
1349 f << "};" << endl;
1350
1351
1352 FREE_int(stab_gens_first);
1353 FREE_int(stab_gens_len);
1354 }
1355 }
1356
1358
1359 cout << "written file " << fname << " of size "
1360 << Fio.file_size(fname.c_str()) << endl;
1361 if (f_v) {
1362 cout << "canonical_form_classifier::generate_source_code done" << endl;
1363 }
1364}
1365
1366
1367
1368
1369void canonical_form_classifier::report(std::string &fname_base, int verbose_level)
1370{
1371
1372 int f_v = (verbose_level >= 1);
1373
1374 if (f_v) {
1375 cout << "canonical_form_classifier::report" << endl;
1376 }
1377
1378 string label;
1379 string fname;
1380
1381
1382 label.assign(fname_base);
1383 label.append("_canonical");
1384
1385 fname.assign(label);
1386 fname.append(".tex");
1387
1388
1389 {
1390 ofstream ost(fname);
1392
1393 L.head_easy(ost);
1394
1395
1396 report2(ost, fname_base, verbose_level);
1397
1398 L.foot(ost);
1399 }
1401
1402 cout << "Written file " << fname << " of size "
1403 << Fio.file_size(fname) << endl;
1404
1405
1406 if (f_v) {
1407 cout << "canonical_form_classifier::report done" << endl;
1408 }
1409
1410}
1411
1412void canonical_form_classifier::report2(std::ostream &ost, std::string &fname_base, int verbose_level)
1413{
1414 int f_v = (verbose_level >= 1);
1415 std::string label;
1416 std::string fname;
1417
1418 if (f_v) {
1419 cout << "canonical_form_classifier::report2" << endl;
1420 }
1421
1422 label.assign(fname_base);
1423 label.append("_canonical");
1424
1425 fname.assign(label);
1426 fname.append("_data.csv");
1427
1428 int i, j;
1429 //int nb_cols = 5 + SubC->nb_orbits + 15;
1430 int nb_cols = 21;
1431
1432 //long int *Table;
1433
1435
1436 S.init_empty_table(nb_objects_to_test + 1, nb_cols);
1437
1438 //Table = NEW_lint(nb_objects_to_test * nb_cols);
1439
1440 S.fill_entry_with_text(0, 0, "Line");
1441 S.fill_entry_with_text(0, 1, "File");
1442 S.fill_entry_with_text(0, 2, "RowInFile");
1443 S.fill_entry_with_text(0, 3, "nb_pts");
1444 S.fill_entry_with_text(0, 4, "nb_sub_orbs");
1445 S.fill_entry_with_text(0, 5, "frequencies");
1446 S.fill_entry_with_text(0, 6, "nb_types");
1447 S.fill_entry_with_text(0, 7, "selected_type");
1448 S.fill_entry_with_text(0, 8, "selected_orbit");
1449 S.fill_entry_with_text(0, 9, "selected_frequency");
1450 S.fill_entry_with_text(0, 10, "go_min");
1451 S.fill_entry_with_text(0, 11, "set_stabilizer_order");
1452 S.fill_entry_with_text(0, 12, "reduced_set_size");
1453 S.fill_entry_with_text(0, 13, "nb_interesting_subsets");
1454 S.fill_entry_with_text(0, 14, "nb_interesting_subsets_reduced");
1455 S.fill_entry_with_text(0, 15, "nb_interesting_subsets_rr");
1456 S.fill_entry_with_text(0, 16, "nb_orbits");
1457 S.fill_entry_with_text(0, 17, "nb_interesting_orbits");
1458 S.fill_entry_with_text(0, 18, "nb_interesting_points");
1459 S.fill_entry_with_text(0, 19, "orbit_length_under_set_stab");
1460 S.fill_entry_with_text(0, 20, "stab_of_eqn");
1461
1462 j = 1;
1463 for (i = 0; i < nb_objects_to_test; i++, j++) {
1464
1465 cout << "i=" << i << endl;
1466
1467
1468 S.set_entry_lint(j, 0, i);
1469
1470 if (CFS_table[i]) {
1471
1472 S.set_entry_lint(j, 1, CFS_table[i]->cnt);
1473 S.set_entry_lint(j, 2, CFS_table[i]->row);
1474 S.set_entry_lint(j, 3, CFS_table[i]->nb_pts);
1475 S.set_entry_lint(j, 4, SubC->nb_orbits);
1476#if 0
1477 Table[i * nb_cols + 0] = i;
1478 Table[i * nb_cols + 1] = CFS_table[i]->cnt;
1479 Table[i * nb_cols + 2] = CFS_table[i]->row;
1480 Table[i * nb_cols + 3] = CFS_table[i]->nb_pts;
1481 Table[i * nb_cols + 4] = SubC->nb_orbits;
1482#endif
1483 //cout << "i=" << i << " getting orbit_frequencies" << endl;
1484
1485 string str;
1486
1488
1489 S.fill_entry_with_text(j, 5, str);
1490
1491#if 0
1492 for (j = 0; j < SubC->nb_orbits; j++) {
1493 Table[i * nb_cols + 5 + j] = CFS_table[i]->orbit_frequencies[j];
1494 }
1495#endif
1496
1497 //cout << "i=" << i << " getting orbit_frequencies part 3" << endl;
1498
1499 S.set_entry_lint(j, 6, CFS_table[i]->SubSt->nb_types);
1500 S.set_entry_lint(j, 7, CFS_table[i]->SubSt->selected_type);
1501 S.set_entry_lint(j, 8, CFS_table[i]->SubSt->selected_orbit);
1502 S.set_entry_lint(j, 9, CFS_table[i]->SubSt->selected_frequency);
1503 S.set_entry_lint(j, 10, CFS_table[i]->SubSt->gens->group_order_as_lint());
1504 S.set_entry_lint(j, 11, CFS_table[i]->Gens_stabilizer_original_set->group_order_as_lint());
1505 S.set_entry_lint(j, 12, CFS_table[i]->CS->Stab_orbits->reduced_set_size);
1506 S.set_entry_lint(j, 13, CFS_table[i]->SubSt->nb_interesting_subsets);
1507 S.set_entry_lint(j, 14, CFS_table[i]->CS->Stab_orbits->nb_interesting_subsets_reduced);
1508 S.set_entry_lint(j, 15, CFS_table[i]->CS->nb_interesting_subsets_rr);
1509 S.set_entry_lint(j, 16, CFS_table[i]->CS->Stab_orbits->nb_orbits);
1510 S.set_entry_lint(j, 17, CFS_table[i]->CS->Stab_orbits->nb_interesting_orbits);
1511 S.set_entry_lint(j, 18, CFS_table[i]->CS->Stab_orbits->nb_interesting_points);
1512 S.set_entry_lint(j, 19, CFS_table[i]->Orb->used_length);
1513 S.set_entry_lint(j, 20, CFS_table[i]->gens_stab_of_canonical_equation->group_order_as_lint());
1514
1515#if 0
1516 Table[i * nb_cols + 5 + SubC->nb_orbits + 0] = CFS_table[i]->nb_types;
1517 Table[i * nb_cols + 5 + SubC->nb_orbits + 1] = CFS_table[i]->selected_type;
1518 Table[i * nb_cols + 5 + SubC->nb_orbits + 2] = CFS_table[i]->selected_orbit;
1519 Table[i * nb_cols + 5 + SubC->nb_orbits + 3] = CFS_table[i]->selected_frequency;
1520 Table[i * nb_cols + 5 + SubC->nb_orbits + 4] = CFS_table[i]->go_min.as_lint();
1521 Table[i * nb_cols + 5 + SubC->nb_orbits + 5] = CFS_table[i]->Gens_stabilizer_original_set->group_order_as_lint();
1522 Table[i * nb_cols + 5 + SubC->nb_orbits + 6] = CFS_table[i]->CS->reduced_set_size;
1523 Table[i * nb_cols + 5 + SubC->nb_orbits + 7] = CFS_table[i]->nb_interesting_subsets;
1524 Table[i * nb_cols + 5 + SubC->nb_orbits + 8] = CFS_table[i]->CS->nb_interesting_subsets_reduced;
1525 Table[i * nb_cols + 5 + SubC->nb_orbits + 9] = CFS_table[i]->CS->nb_interesting_subsets_rr;
1526 Table[i * nb_cols + 5 + SubC->nb_orbits + 10] = CFS_table[i]->CS->nb_orbits;
1527 Table[i * nb_cols + 5 + SubC->nb_orbits + 11] = CFS_table[i]->CS->nb_interesting_orbits;
1528 Table[i * nb_cols + 5 + SubC->nb_orbits + 12] = CFS_table[i]->CS->nb_interesting_points;
1529 Table[i * nb_cols + 5 + SubC->nb_orbits + 13] = CFS_table[i]->Orb->used_length;
1530 Table[i * nb_cols + 5 + SubC->nb_orbits + 14] = CFS_table[i]->gens_stab_of_canonical_equation->group_order_as_lint();
1531#endif
1532 }
1533 else {
1534 //Orbiter->Lint_vec.zero(Table + i * nb_cols, nb_cols);
1535 //Table[i * nb_cols + 0] = i;
1536 S.set_entry_lint(j, 1, 0);
1537 S.set_entry_lint(j, 2, 0);
1538 S.set_entry_lint(j, 3, 0);
1539 S.set_entry_lint(j, 4, 0);
1540 S.fill_entry_with_text(j, 5, "");
1541
1542 int h;
1543
1544 for (h = 6; h <= 20; h++) {
1545 S.set_entry_lint(j, h, 0);
1546 }
1547 }
1548
1549 }
1550 if (f_v) {
1551 cout << "canonical_form_classifier::report2 finished collecting Table" << endl;
1552 }
1553
1554#if 1
1556
1557 S.save(fname, 0 /* verbose_level*/);
1558
1559 //Fio.lint_matrix_write_csv(fname, Table, nb_objects_to_test, nb_cols);
1560
1561 cout << "Written file " << fname << " of size "
1562 << Fio.file_size(fname) << endl;
1563#endif
1564
1565 if (f_v) {
1566 cout << "canonical_form_classifier::report2 done" << endl;
1567 }
1568
1569}
1570
1571
1572}}}
1573
1574
classification of 0/1 matrices using canonical forms
void add_at_idx(uchar *data, void *extra_data, int idx, int verbose_level)
void search_and_add_if_new(uchar *data, void *extra_data, int &f_found, int &idx, int verbose_level)
void create_string_with_quotes(std::string &str, int *v, int len)
Definition: int_vec.cpp:1088
void create_string_with_quotes(std::string &str, long int *v, int len)
Definition: lint_vec.cpp:533
a collection of functions related to sorted vectors
void read_spreadsheet(std::string &fname, int verbose_level)
void set_entry_lint(int row_idx, int col_idx, long int val)
void save(std::string &fname, int verbose_level)
void fill_entry_with_text(int row_idx, int col_idx, const char *text)
functions related to strings and character arrays
a statistical analysis of data consisting of vectors of ints
void get_transversal(int *&transversal, int *&frequency, int &nb_types, int verbose_level)
void init(int *data, int data_length, int data_set_sz, int verbose_level)
int reverse_engineer_semilinear_map(int *Elt, int *Mtx, int &frobenius, int verbose_level)
homogeneous polynomials of a given degree in a given number of variables over a finite field GF(q)
Definition: ring_theory.h:88
void init(field_theory::finite_field *F, int nb_vars, int degree, int f_init_incidence_structure, monomial_ordering_type Monomial_ordering_type, int verbose_level)
void substitute_semilinear(int *coeff_in, int *coeff_out, int f_semilinear, int frob_power, int *Mtx_inv, 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)
a permutation group in a fixed action.
Definition: actions.h:99
void element_print(void *elt, std::ostream &ost)
Definition: action_cb.cpp:347
void element_print_for_make_element(void *elt, std::ostream &ost)
Definition: action_cb.cpp:409
groups::strong_generators * Strong_gens
Definition: actions.h:130
void make_element(int *Elt, int *data, int verbose_level)
Definition: action.cpp:1875
long int element_image_of(long int a, void *elt, int verbose_level)
Definition: action_cb.cpp:198
a strong generating set for a permutation group with respect to a fixed action
Definition: groups.h:1703
data_structures_groups::vector_ge * gens
Definition: groups.h:1708
void get_gens_data_as_string_with_quotes(std::string &str, int verbose_level)
void group_order(ring_theory::longinteger_object &go)
induced action on the set of homogeneous polynomials over a finite field
void init(actions::action *A, ring_theory::homogeneous_polynomial_domain *HPD, int verbose_level)
int search_equation(int *eqn, int &idx, int verbose_level)
void classify_substructures(std::string &fname_base_out, actions::action *A, actions::action *A2, groups::strong_generators *gens, int substructure_size, int verbose_level)
void classify(canonical_form_classifier_description *Descr, int verbose_level)
induced_actions::action_on_homogeneous_polynomials * AonHPD
void classify_curve_nauty(int cnt, int row, int *eqn, int sz, long int *pts, int nb_pts, long int *bitangents, int nb_bitangents, int *canonical_equation, int *transporter_to_canonical_form, int verbose_level)
void generate_source_code(std::string &fname_base, data_structures::tally_vector_data *Classification_of_quartic_curves, int verbose_level)
void report2(std::ostream &ost, std::string &fname_base, int verbose_level)
to compute the canonical form of an object using nauty
void quartic_curve(projective_space_with_action *PA, ring_theory::homogeneous_polynomial_domain *Poly4_x123, induced_actions::action_on_homogeneous_polynomials *AonHPD, int idx, int *eqn, int sz, long int *Pts_on_curve, int sz_curve, long int *bitangents, int nb_bitangents, int *canonical_equation, int *transporter_to_canonical_form, groups::strong_generators *&gens_stab_of_canonical_equation, int verbose_level)
to compute the canonical form of an object using substructure canonization
void classify_curve_with_substructure(canonical_form_classifier *Canonical_form_classifier, int counter, int cnt, int row, std::string &fname_case_out, int *eqn, int sz, long int *pts, int nb_pts, long int *bitangents, int nb_bitangents, ring_theory::longinteger_object &go_eqn, int verbose_level)
#define Int_vec_scan(A, B, C)
Definition: foundations.h:716
#define FREE_int(p)
Definition: foundations.h:640
#define Int_vec_zero(A, B)
Definition: foundations.h:713
#define Lint_vec_scan(A, B, C)
Definition: foundations.h:717
#define NEW_pvoid(n)
Definition: foundations.h:637
#define NEW_OBJECT(type)
Definition: foundations.h:638
#define Lint_vec_print(A, B, C)
Definition: foundations.h:686
#define FREE_OBJECT(p)
Definition: foundations.h:651
#define NEW_int(n)
Definition: foundations.h:625
#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_lint(p)
Definition: foundations.h:642
#define NEW_lint(n)
Definition: foundations.h:628
#define Int_vec_print(A, B, C)
Definition: foundations.h:685
orbiter_kernel_system::orbiter_session * Orbiter
global Orbiter session
the orbiter library for the classification of combinatorial objects