Orbiter 2022
Combinatorial Objects
gen_geo.cpp
Go to the documentation of this file.
1/*
2 * gen_geo.cpp
3 *
4 * Created on: Aug 14, 2021
5 * Author: betten
6 */
7
8
9
10
11#include "foundations.h"
12
13using namespace std;
14
15
16
17namespace orbiter {
18namespace layer1_foundations {
19namespace geometry_builder {
20
21
22
23#define MAX_V 300
24
25
26
28{
29 GB = NULL;
30
32
33 inc = NULL;
34
36 //gen_print_intervall = FALSE;
37
38 //std::string inc_file_name;
39
40
41 //std::string fname_search_tree;
42 ost_search_tree = NULL;
43 //std::string fname_search_tree_flags;
45
46 Girth_test = NULL;
47
48 Test_semicanonical = NULL;
49
51}
52
54{
57 }
58
59 if (inc) {
61 }
62
63 if (Girth_test) {
65 }
68 }
69
72 }
73}
74
75void gen_geo::init(geometry_builder *GB, int verbose_level)
76{
77 int f_v = (verbose_level >= 1);
78
79 if (f_v) {
80 cout << "gen_geo::init" << endl;
81 }
83
85
86 if (f_v) {
87 cout << "gen_geo::init before inc->init" << endl;
88 }
89 inc->init(this, GB->V, GB->B, GB->R, verbose_level);
90 if (f_v) {
91 cout << "gen_geo::init after inc->init" << endl;
92 }
93
95
96
98
99 if (f_v) {
100 cout << "gen_geo::init before Decomposition_with_fuse->init" << endl;
101 }
102 Decomposition_with_fuse->init(this, verbose_level);
103 if (f_v) {
104 cout << "gen_geo::init after Decomposition_with_fuse->init" << endl;
105 }
106
107
108 if (f_v) {
109 cout << "gen_geo::init before init_semicanonical" << endl;
110 }
111 init_semicanonical(verbose_level);
112 if (f_v) {
113 cout << "gen_geo::init before init_semicanonical done" << endl;
114 }
115
116
117 if (GB->Descr->f_girth_test) {
118
120
121 Girth_test->init(this, GB->Descr->girth, verbose_level);
122
123 }
124
126
127 if (f_v) {
128 cout << "gen_geo::init before Geometric_backtrack_search->init" << endl;
129 }
130 Geometric_backtrack_search->init(this, verbose_level);
131 if (f_v) {
132 cout << "gen_geo::init after Geometric_backtrack_search->init" << endl;
133 }
134
135 if (f_v) {
136 cout << "gen_geo::init done" << endl;
137 }
138
139}
140
141
142void gen_geo::init_semicanonical(int verbose_level)
143{
144 int f_v = (verbose_level >= 1);
145
146 if (f_v) {
147 cout << "gen_geo::init_semicanonical" << endl;
148 }
149
151
152 if (f_v) {
153 cout << "gen_geo::init_semicanonical before Test_semicanonical->init" << endl;
154 }
155 Test_semicanonical->init(this, MAX_V, verbose_level);
156 if (f_v) {
157 cout << "gen_geo::init_semicanonical after Test_semicanonical->init" << endl;
158 }
159
160 if (f_v) {
161 cout << "gen_geo::init_semicanonical done" << endl;
162 }
163}
164
165
167{
168 int i1, i2, a;
169
170 for (i1 = 0; i1 < line; i1++) {
171 cout << "line " << i1 << " : ";
172 for (i2 = 0; i2 < i1; i2++) {
173 a = inc->pairs[i1][i2];
174 cout << a;
175 }
176 cout << endl;
177 }
178}
179
180void gen_geo::main2(int verbose_level)
181{
182 int f_v = (verbose_level >= 1);
183
184 if (f_v) {
185 cout << "gen_geo::main2, verbose_level = " << verbose_level << endl;
186 }
187 int V;
188
189
190 if (f_v) {
191 cout << "gen_geo::main2 before generate_all" << endl;
192 }
193 generate_all(verbose_level);
194 if (f_v) {
195 cout << "gen_geo::main2 after generate_all" << endl;
196 }
197
198
199
200 V = inc->Encoding->v;
201 iso_type *it;
202
203 it = inc->iso_type_at_line[V - 1];
204 {
205 string fname;
206 fname.assign(inc_file_name);
207 fname.append(".inc");
208 it->write_inc_file(fname, verbose_level);
209
211
212 cout << "Written file " << fname << " of size " << Fio.file_size(fname) << endl;
213 }
214
215 it = inc->iso_type_at_line[V - 1];
216
217 if (it->Canonical_forms->B.size()) {
218
219 {
220 string fname;
221 fname.assign(inc_file_name);
222 fname.append(".blocks_long");
223 it->write_blocks_file_long(fname, verbose_level);
224
226
227 cout << "Written file " << fname << " of size " << Fio.file_size(fname) << endl;
228
229 }
230
232
234
235 if (inc->is_block_tactical(V, OiP->set)) {
236
237 string fname;
238 fname.assign(inc_file_name);
239 fname.append(".blocks");
240 it->write_blocks_file(fname, verbose_level);
241
243
244 cout << "Written file " << fname << " of size " << Fio.file_size(fname) << endl;
245 }
246 }
247
248
249 if (inc->iso_type_no_vhbars) {
251 {
252 string fname;
253 fname.assign(inc_file_name);
254 fname.append("_resolved.inc");
255 it->write_inc_file(fname, verbose_level);
256 }
257 }
258
259
260 print(cout, V, V);
261
262 int i, a;
263
264 for (i = 0; i < GB->Descr->print_at_line.size(); i++) {
265 a = GB->Descr->print_at_line[i];
266 inc->iso_type_at_line[a - 1]->print_geos(verbose_level);
267 }
268
269
270 if (f_v) {
271 cout << "gen_geo::main2 done" << endl;
272 }
273
274}
275
276void gen_geo::generate_all(int verbose_level)
277{
278 int f_v = (verbose_level >= 1);
279 int f_vv = (verbose_level >= 3);
280
281 if (f_v) {
282 cout << "gen_geo::generate_all, verbose_level = " << verbose_level << endl;
283 }
284
285 int ret = FALSE;
286 int f_already_there;
287 //int s_nb_i_vbar, s_nb_i_hbar;
288 iso_type *it0, *it1;
289
290 if (f_v) {
291 if (GB->Descr->f_lambda) {
292 cout << "lambda = " << GB->Descr->lambda << endl;
293 }
294 }
295
296
297 setup_output_files(verbose_level);
298
299 if (f_v) {
300 cout << "gen_geo::generate_all before it0 = ..." << endl;
301 }
302
303 it0 = inc->iso_type_at_line[inc->Encoding->v - 1];
304
305 if (it0 == NULL) {
306 cout << "please install a test at line " << inc->Encoding->v << endl;
307 exit(1);
308 }
309
310 if (f_v) {
311 cout << "gen_geo::generate_all before it1 = ..." << endl;
312 }
313
314 it1 = inc->iso_type_no_vhbars;
315
316
317 if (it1 && forget_ivhbar_in_last_isot) {
318 cout << "gen_geo::generate_all inc.iso_type_no_vhbars && forget_ivhbar_in_last_isot" << endl;
319 goto l_exit;
320 }
321
322 inc->gl_nb_GEN = 0;
323 if (!Geometric_backtrack_search->First(verbose_level - 5)) {
324 ret = TRUE;
325
326 cout << "gen_geo::generate_all Geometric_backtrack_search->First "
327 "returns FALSE, no geometry exists. This is perhaps a bit unusual." << endl;
328 goto l_exit;
329 }
330
331
332 while (TRUE) {
333
334
335 inc->gl_nb_GEN++;
336 if (f_v) {
337 cout << "gen_geo::generate_all nb_GEN=" << inc->gl_nb_GEN << endl;
338 print(cout, inc->Encoding->v, inc->Encoding->v);
339 //cout << "pairs:" << endl;
340 //inc->print_pairs(inc->Encoding->v);
341
342#if 0
343 if ((inc->gl_nb_GEN % gen_print_intervall) == 0) {
344 //inc->print(cout, inc->Encoding->v);
345 }
346#endif
347 }
348
349
350 //cout << "*** do_geo *** geometry no. " << gg->inc.gl_nb_GEN << endl;
351#if 0
352 if (incidence_back_test(&gg->inc,
353 TRUE /* f_verbose */,
354 FALSE /* f_very_verbose */)) {
355 }
356#endif
357
358
359
360#if 0
362 s_nb_i_vbar = inc->nb_i_vbar;
363 s_nb_i_hbar = inc->nb_i_hbar;
364 inc->nb_i_vbar = 1;
365 inc->nb_i_hbar = 1;
366 }
367#endif
368 if (f_v) {
369 cout << "gen_geo::generate_all before isot_add for it0" << endl;
370 }
371
373 FALSE /* f_partition_fixing_last */,
374 f_already_there,
375 verbose_level - 2);
376
377 if (f_v) {
378 cout << "gen_geo::generate_all after isot_add for it0, f_already_there=" << f_already_there << endl;
379 }
380
381
382 record_tree(inc->Encoding->v, f_already_there);
383
384
385 if (FALSE) {
386 cout << "gen_geo::generate_all after isot_add for it0" << endl;
387 }
388
389 if (f_vv && it0->Canonical_forms->B.size() % 1 == 0) {
390 cout << it0->Canonical_forms->B.size() << endl;
391 print(cout, inc->Encoding->v, inc->Encoding->v);
392 }
393
394#if 0
396 inc->nb_i_vbar = s_nb_i_vbar;
397 inc->nb_i_hbar = s_nb_i_hbar;
398 }
399 if (!f_already_there && inc->iso_type_no_vhbars) {
400 s_nb_i_vbar = inc->nb_i_vbar;
401 s_nb_i_hbar = inc->nb_i_hbar;
402 inc->nb_i_vbar = 1;
403 inc->nb_i_hbar = 1;
404
405 if (FALSE) {
406 cout << "gen_geo::generate_all before isot_add for it1" << endl;
407 }
409 inc->Encoding->v, inc,
410 f_already_there,
411 verbose_level - 2);
412
413 //record_tree(inc->Encoding->v, f_already_there);
414
415 if (FALSE) {
416 cout << "gen_geo::generate_all after isot_add for it1" << endl;
417 }
418 if (!f_already_there) {
419 //save_theX(inc->iso_type_no_vhbars->fp);
420 }
421 inc->nb_i_vbar = s_nb_i_vbar;
422 inc->nb_i_hbar = s_nb_i_hbar;
423 }
424 if (!f_already_there && !inc->iso_type_no_vhbars) {
425 }
426#endif
427
428 if (!Geometric_backtrack_search->Next(verbose_level - 5)) {
429 if (f_v) {
430 cout << "gen_geo::generate_all Geometric_backtrack_search->Next "
431 "returns FALSE, finished" << endl;
432 }
433 break;
434 }
435 }
436
437
438 close_output_files(verbose_level);
439
440
441l_exit:
442 if (f_v) {
443 cout << "gen_geo::generate_all done" << endl;
444 }
445}
446
447void gen_geo::setup_output_files(int verbose_level)
448{
449 int f_v = (verbose_level >= 1);
450
451
452 if (GB->Descr->f_search_tree) {
454 fname_search_tree.append("_tree.txt");
455
456 if (f_v) {
457 cout << "gen_geo::setup_output_files, opening file " << fname_search_tree << endl;
458 }
459
460 ost_search_tree = new ofstream;
461 ost_search_tree->open (fname_search_tree, std::ofstream::out);
462 }
463 else {
464 ost_search_tree = NULL;
465 }
466
469 fname_search_tree_flags.append("_tree_flags.txt");
470
471 if (f_v) {
472 cout << "gen_geo::setup_output_files, opening file " << fname_search_tree << endl;
473 }
474
475 ost_search_tree_flags = new ofstream;
476 ost_search_tree_flags->open (fname_search_tree_flags, std::ofstream::out);
477 }
478 else {
480 }
481
482}
483
484void gen_geo::close_output_files(int verbose_level)
485{
486 //int f_v = (verbose_level >= 1);
487
488 if (GB->Descr->f_search_tree) {
489 *ost_search_tree << "-1" << endl;
490 ost_search_tree->close();
491 }
492
494 *ost_search_tree_flags << "-1" << endl;
495 ost_search_tree_flags->close();
496 }
497
498}
499
500void gen_geo::record_tree(int i1, int f_already_there)
501{
502 int color;
503
504 if (f_already_there) {
505 color = COLOR_RED;
506 }
507 else {
508 color = COLOR_GREEN;
509 }
510
511
512 if (ost_search_tree) {
513
514 int row;
515 long int rk;
516
517 *ost_search_tree << i1;
518 for (row = 0; row < i1; row++) {
519 rk = inc->Encoding->rank_row(row);
520 *ost_search_tree << " " << rk;
521 }
522 *ost_search_tree << " " << color;
523 *ost_search_tree << endl;
524 }
525
527
528 std::vector<int> flags;
529 int h;
530
531 inc->Encoding->get_flags(i1, flags);
532
533 *ost_search_tree_flags << flags.size();
534
535 for (h = 0; h < flags.size(); h++) {
536 *ost_search_tree_flags << " " << flags[h];
537
538 }
539 *ost_search_tree_flags << " " << color;
540 *ost_search_tree_flags << endl;
541
542 }
543
544}
545
546
547void gen_geo::print_I_m(int I, int m)
548{
550 int i1;
551
552 i1 = C->i0 + m;
553 print(cout, i1 + 1, i1 + 1);
554}
555
556void gen_geo::print(int v)
557{
558 print(cout, v, v);
559}
560
561
562void gen_geo::increment_pairs_point(int i1, int col, int k)
563{
564 int ii, ii1;
565
566 for (ii = 0; ii < k; ii++) {
567 ii1 = inc->theY[col][ii];
568 inc->pairs[i1][ii1]++;
569 }
570}
571
572void gen_geo::decrement_pairs_point(int i1, int col, int k)
573{
574 int ii, ii1;
575
576 for (ii = 0; ii < k; ii++) {
577 ii1 = inc->theY[col][ii];
578 inc->pairs[i1][ii1]--;
579 }
580}
581
582void gen_geo::girth_test_add_incidence(int i, int j_idx, int j)
583{
584 if (Girth_test) {
585 Girth_test->add_incidence(i, j_idx, j);
586 }
587}
588
589void gen_geo::girth_test_delete_incidence(int i, int j_idx, int j)
590{
591 if (Girth_test) {
592 Girth_test->delete_incidence(i, j_idx, j);
593 }
594}
595
596void gen_geo::girth_Floyd(int i, int verbose_level)
597{
598 if (Girth_test) {
599 Girth_test->Floyd(i, verbose_level);
600 }
601}
602
603int gen_geo::check_girth_condition(int i, int j_idx, int j, int verbose_level)
604{
605 if (Girth_test) {
606#if 0
607 inc->print(cout, i + 1, GB->V);
610#endif
611 return Girth_test->check_girth_condition(i, j_idx, j, verbose_level);
612 }
613 else {
614 return TRUE;
615 }
616}
617
618
619int gen_geo::apply_tests(int I, int m, int J, int n, int j, int verbose_level)
620{
621 int f_v = (verbose_level >= 1);
622 int fuse_idx;
623 int i1, r, k, j0, j1;
624
625 if (f_v) {
626 cout << "gen_geo::apply_tests "
627 "I=" << I << " m=" << m
628 << " J=" << J << " n=" << n << " j=" << j << endl;
629 }
631 fuse_idx = C->fuse_idx;
632 i1 = C->i0 + m;
633 // current row
634
635 r = C->r0 + n;
636 // index of current incidence within the row
637
638 j0 = C->j0;
639
640 j1 = j0 + j;
641
642 k = inc->K[j1];
643
644 // We want to place an incidence in (i1,j1).
645
646 if (GB->Descr->f_lambda) {
647
648 // We check that there are no repeated columns
649 // in the incidence matrix of the design that we create.
650
651
652 // If this was the last incidence in column j1,
653 // make sure the column is different from the previous column.
654 // Do this test based on theY[], which lists the incidences in the column.
655
656 // JS = Jochim Selzer
657
658
659 if (GB->Descr->f_simple) { /* JS 180100 */
660
661 // Note that K[j1] does not take into account
662 // the incidence that we want to place in column j1.
663
664 if (Decomposition_with_fuse->F_last_k_in_col[fuse_idx * GB->b_len + J] &&
665 k == Decomposition_with_fuse->K1[fuse_idx * GB->b_len + J] - 1) {
666 int ii;
667
668 // check whether the column is
669 // different from the previous column:
670
671 for (ii = 0; ii <= k; ii++) {
672 if (inc->theY[j1 - 1][ii] != inc->theY[j1][ii]) {
673 break; // yes, columns differ !
674 }
675 }
676 if (ii > k) {
677
678 // not OK, columns are equal.
679 // The design is not simple.
680
681 inc->Encoding->theX_ir(i1, r) = -1;
682 inc->theY[j1][k] = -1;
683 if (f_v) {
684 cout << "gen_geo::apply_tests "
685 "I=" << I << " m=" << m
686 << " J=" << J << " n=" << n << " j=" << j
687 << " rejected because not simple" << endl;
688 }
689 return FALSE;
690 }
691 }
692 } // JS
693
694
695 // check whether there is enough capacity in the lambda array.
696 // This means, check if all scalar products
697 // for previous rows with a one in column j1
698 // are strictly less than \lambda:
699 // This means that there is room for one more pair
700 // created by the present incidence in row i1 and column j1
701
702 int ii, ii1;
703
704 for (ii = 0; ii < k; ii++) {
705
706 ii1 = inc->theY[j1][ii];
707
708 if (inc->pairs[i1][ii1] >= GB->Descr->lambda) {
709
710 // no, fail
711
712 inc->Encoding->theX_ir(i1, r) = -1;
713 inc->theY[j1][k] = -1;
714 break;
715 }
716 }
717
718
719 if (ii < k) {
720
721 // There is not enough capacity in the lambda array.
722 // So, we cannot put the incidence at (i1,j1):
723
724 if (f_v) {
725 cout << "gen_geo::apply_tests "
726 "I=" << I << " m=" << m << " J=" << J
727 << " n=" << n << " j=" << j
728 << " rejected because of pair test" << endl;
729 }
730
731 return FALSE;
732 }
733
734 // increment the pairs counter:
735
736 increment_pairs_point(i1, j1, k);
737
738 // additional test that applies if the row is complete:
739
740 // In this case, all scalar products with previous rows must be equal to lambda:
741
742 if (J == GB->b_len - 1 && n == C->r - 1) {
743 for (ii = 0; ii < i1; ii++) {
744 if (inc->pairs[i1][ii] != GB->Descr->lambda) {
745 // no, fail
746 break;
747 }
748 }
749 if (ii < i1) {
750
751 // reject this incidence:
752
753 decrement_pairs_point(i1, j1, k);
754
755 if (f_v) {
756 cout << "gen_geo::apply_tests "
757 "I=" << I << " m=" << m << " J=" << J
758 << " n=" << n << " j=" << j << " rejected because at least "
759 "one pair is not covered lambda times" << endl;
760 }
761 return FALSE;
762 }
763 }
764 }
765 else {
766
767 if (GB->Descr->f_find_square) { /* JS 120100 */
768
769 // Test the square condition.
770 // The square condition tests whether there is
771 // a pair of points that is contained in two different blocks
772 // (corresponding to a square in the incidence matrix, hence the name).
773 // We need only consider the pairs of points that include i1.
774
775 if (inc->find_square(i1, r)) {
776
777 // fail, cannot place incidence here
778
779 inc->Encoding->theX_ir(i1, r) = -1;
780 if (f_v) {
781 cout << "gen_geo::apply_tests "
782 "I=" << I << " m=" << m << " J=" << J
783 << " n=" << n << " j=" << j << " rejected because "
784 "of square condition" << endl;
785 }
786 return FALSE;
787 }
788 }
789 }
790
791 girth_test_add_incidence(i1, r, j1);
792
793 if (!check_girth_condition(i1, r, j1, 0 /*verbose_level*/)) {
794
796
797 if (GB->Descr->f_lambda) {
798
799 decrement_pairs_point(i1, j1, k);
800
801 }
802 if (f_v) {
803 cout << "gen_geo::apply_tests "
804 "I=" << I << " m=" << m << " J=" << J
805 << " n=" << n << " j=" << j << " rejected because "
806 "of girth condition" << endl;
807 }
808 return FALSE;
809 }
810
811
812
813 return TRUE;
814}
815
816void gen_geo::print(std::ostream &ost, int v, int v_cut)
817{
819 v, v_cut, this, TRUE /* f_print_isot */);
820}
821
822
823void gen_geo::print_override_theX(std::ostream &ost, int *theX, int v, int v_cut)
824{
826 v, v_cut, this, theX, TRUE /* f_print_isot */);
827}
828
829
830
831
832}}}
833
834
835
a combinatorial object for which a canonical form can be computed using Nauty
Definition: geometry.h:1487
a row-tactical decomposition with fuse, to be used by the geometry_builder
description of a configuration which is part of class decomposition_with_fuse
void decrement_pairs_point(int i1, int col, int k)
Definition: gen_geo.cpp:572
void init(geometry_builder *GB, int verbose_level)
Definition: gen_geo.cpp:75
void girth_test_delete_incidence(int i, int j_idx, int j)
Definition: gen_geo.cpp:589
int apply_tests(int I, int m, int J, int n, int j, int verbose_level)
Definition: gen_geo.cpp:619
void increment_pairs_point(int i1, int col, int k)
Definition: gen_geo.cpp:562
void print_override_theX(std::ostream &ost, int *theX, int v, int v_cut)
Definition: gen_geo.cpp:823
void girth_test_add_incidence(int i, int j_idx, int j)
Definition: gen_geo.cpp:582
int check_girth_condition(int i, int j_idx, int j, int verbose_level)
Definition: gen_geo.cpp:603
void record_tree(int i1, int f_already_there)
Definition: gen_geo.cpp:500
classification of geometries with a given row-tactical decomposition
int check_girth_condition(int i, int j_idx, int j, int verbose_level)
Definition: girth_test.cpp:150
void init(gen_geo *gg, int girth, int verbose_level)
Definition: girth_test.cpp:46
void get_flags(int row, std::vector< int > &flags)
void print_partitioned(std::ostream &ost, int v_cur, int v_cut, gen_geo *gg, int f_print_isot)
void print_partitioned_override_theX(std::ostream &ost, int v_cur, int v_cut, gen_geo *gg, int *the_X, int f_print_isot)
encoding of an incidence geometry during classification
void init(gen_geo *gg, int v, int b, int *R, int verbose_level)
Definition: incidence.cpp:79
classification of geometries based on canonical forms
void write_blocks_file(std::string &fname, int verbose_level)
Definition: iso_type.cpp:364
data_structures::classify_using_canonical_forms * Canonical_forms
void write_inc_file(std::string &fname, int verbose_level)
Definition: iso_type.cpp:319
void add_geometry(inc_encoding *Encoding, int f_partition_fixing_last, int &f_already_there, int verbose_level)
Definition: iso_type.cpp:95
void write_blocks_file_long(std::string &fname, int verbose_level)
Definition: iso_type.cpp:422
void init(gen_geo *gg, int MAX_V, int verbose_level)
#define NEW_OBJECT(type)
Definition: foundations.h:638
#define FREE_OBJECT(p)
Definition: foundations.h:651
#define TRUE
Definition: foundations.h:231
#define FALSE
Definition: foundations.h:234
#define MAX_V
Definition: gen_geo.cpp:23
#define COLOR_RED
#define COLOR_GREEN
the orbiter library for the classification of combinatorial objects