Orbiter 2022
Combinatorial Objects
point_line.cpp
Go to the documentation of this file.
1// point_line.cpp
2// Anton Betten
3//
4// started: 2001
5
6
7
8#include "foundations.h"
9
10
11using namespace std;
12
13
14namespace orbiter {
15namespace layer1_foundations {
16namespace geometry {
17
18
20{
21 int f_v = (verbose_level >= 1);
22 int f_vv = (verbose_level >= 2);
23 int line = 0;
24 int *pts_on_line;
25 int u, v, o, e = 0, loe, p0, a, i, y1, y2;
26 int slope, b, x, f_slope, f_b, f_x;
27 int f_found_quadrangle = FALSE;
28 int aa;
30
31 if (f_v) {
32 cout << "is_desarguesian_plane plane_order ="
33 << plane_order << endl;
34 }
37 if (f_vv) {
38 cout << "line " << line << " ";
40 }
41 u = pts_on_line[0];
42 v = pts_on_line[1];
43 if (f_vv) {
44 cout << "choosing points u=" << u << " and v=" << v
45 << " on line " << line << endl;
46 }
47 for (o = 0; o < nb_pts; o++) {
48 if (o == u)
49 continue;
50 if (o == v)
51 continue;
52 for (e = 0; e < nb_pts; e++) {
53 if (e == u)
54 continue;
55 if (e == v)
56 continue;
57 if (e == o)
58 continue;
60 if (loe == line)
61 continue;
62 p0 = plane_line_intersection(loe, line);
63 if (p0 == u)
64 continue;
65 if (p0 == v)
66 continue;
67 if (p0 == o)
68 continue;
69 if (p0 == e)
70 continue;
71 // now: (o,e,u,v) is a quadrangle with u and v both on line
72 f_found_quadrangle = TRUE;
73 break;
74 }
75 if (f_found_quadrangle)
76 break;
77 }
78 if (!f_found_quadrangle) {
79 cout << "did not find a quadrangle, something is wrong" << endl;
80 exit(1);
81 }
82 if (f_vv) {
83 cout << "found quadrangle (" << o << "," << e
84 << "," << u << "," << v << ")";
85 }
86 coordinatize_plane(o, e, u, v, MOLS, f_vv);
87 if (f_vv) {
88 cout << "plane coordinatized" << endl;
89 }
91 aa = plane_order;
93 while (aa > 1) {
95 aa /= plane_prime;
96 }
98 cout << "plane order not a power of a prime." << endl;
99 return FALSE;
100 }
101 if (plane_exponent > 1) {
102 if (f_v) {
103 cout << "plane order is not prime:" << endl;
104 cout << plane_order << " = " << plane_prime << "^"
105 << plane_exponent << endl;
106 }
107 return identify_field_not_of_prime_order(verbose_level);
108 }
109 else {
110 if (f_v) {
111 cout << "plane order is prime" << endl;
112 }
113 field_element[0] = 0;
114 field_element_inv[0] = 0;
115 field_element[1] = 1;
116 field_element_inv[1] = 1;
117 a = 1;
118 for (i = 2; i < plane_order; i++) {
119 a = MOLSsxb(0, a, 1) % plane_order;
120 field_element[i] = a;
121 field_element_inv[a] = i;
122 cout << "field element " << i << " = " << a << endl;
123 }
124 for (slope = 1; slope < plane_order; slope++) {
125 f_slope = field_element[slope];
126
127 for (b = 0; b < plane_order; b++) {
128 f_b = field_element[b];
129
130 for (x = 0; x < plane_order; x++) {
131 f_x = field_element[x];
132
133 // compute slope * x + b from the field,
134 // i.e. MOLS 0 (addition) and plane_order (multiplication)
135 y1 = (slope * x + b) % plane_order;
136 //MOLSaddition(MOLSmultiplication(slope, x), b);
137 a = MOLSsxb(f_slope, f_x, f_b);
138 y2 = field_element_inv[a];
139 if (y1 != y2) {
140 if (f_v) {
141 cout << "the plane is not desarguesian:" << endl;
142 cout << "slope = " << slope << endl;
143 cout << "f_slope = " << f_slope << endl;
144 cout << "b = " << b << endl;
145 cout << "f_b = " << f_b << endl;
146 cout << "x = " << x << endl;
147 cout << "f_x = " << f_x << endl;
148 cout << "y1 = " << y1 << endl;
149 cout << "y2 = " << y2 << endl;
150 cout << "a = " << a << endl;
151 }
152 return FALSE;
153 }
154 }
155 }
156 }
157 }
158 if (f_v) {
159 cout << "the plane is desarguesian" << endl;
160 }
161 return TRUE;
162}
163
165{
166 cout << "point_line::identify_field_not_of_prime_order "
167 "not yet implemented" << endl;
168 exit(1);
169#if 0
170 int m, n; // the size of the incidence matrix
171 int d, d2;
172 int i, j, k, ii, jj, kk, a;
173 int nb_inc = 0; // the number of incidences
174 int mpn;
175 int *M1;
176 int *canonical_form1;
177 int *canonical_form_inv1;
178 permutation_group_generators Aut_gens1;
179 //int *Aut_gens1;
180 //int nb_Aut_gens1;
181 longinteger_object ago1;
182 int *M2;
183 int *canonical_form2;
184 int *canonical_form_inv2;
185 permutation_group_generators Aut_gens2;
186 //int *Aut_gens2;
187 //int nb_Aut_gens2;
188 longinteger_object ago2;
189 int row_parts[5];
190 int col_parts[3];
191 int nb_row_parts = 3;
192 int nb_col_parts = 3;
193 finite_field F;
194 int ret = TRUE;
195
196 d = plane_order;
197 d2 = d * d;
198 m = 3 * d;
199 n = d + 2 * d2;
200 mpn = m + n;
201 row_parts[0] = d;
202 row_parts[1] = d;
203 row_parts[2] = d;
204 col_parts[0] = d;
205 col_parts[1] = d2;
206 col_parts[2] = d2;
207 M1 = NEW_int(m * n);
208 canonical_form1 = NEW_int(mpn);
209 canonical_form_inv1 = NEW_int(mpn);
210 //Aut_gens1 = NEW_int(mpn * mpn);
211 M2 = NEW_int(m * n);
212 canonical_form2 = NEW_int(mpn);
213 canonical_form_inv2 = NEW_int(mpn);
214 //Aut_gens2 = NEW_int(mpn * mpn);
215
216 for (i = 0; i < m; i++) {
217 for (j = 0; j < n; j++) {
218 M1[i * n + j] = 0;
219 }
220 }
221 for (i = 0; i < 3; i++) {
222 for (j = 0; j < d; j++) {
223 M1[(i * d + j) * n + j] = 1;
224 nb_inc++;
225 }
226 }
227
228 for (i = 0; i < d; i++) {
229 for (j = 0; j < d; j++) {
230 a = MOLSsxb(0, i, j); // attention, we need the digits from 0 to d-1 !!
231 M1[i * n + d + i * d + j] = 1;
232 nb_inc++;
233 M1[(d + j) * n + d + i * d + j] = 1;
234 nb_inc++;
235 M1[(2 * d + a) * n + d + i * d + j] = 1;
236 nb_inc++;
237 }
238 }
239 for (i = 0; i < d; i++) {
240 for (j = 0; j < d; j++) {
241 a = MOLSsxb(plane_order, i, j); // attention, we need the digits from 0 to d-1 !!
242 M1[i * n + d + d2 + i * d + j] = 1;
243 nb_inc++;
244 M1[(d + j) * n + d + d2 + i * d + j] = 1;
245 nb_inc++;
246 M1[(2 * d + a) * n + d + d2 + i * d + j] = 1;
247 nb_inc++;
248 }
249 }
250 if (f_v) {
251 cout << "computing canonical labelling of the planar ternary ring of order " << plane_order << endl;
252 }
253
254#if 0
255 compute_canonical_labeling_of_01matrix(M1, m, n,
256 TRUE, row_parts, nb_row_parts, col_parts, nb_col_parts,
257 canonical_form1, canonical_form_inv1,
258 Aut_gens1,
260#endif
261
262 Aut_gens1.compute_group_order(ago1);
263 if (ago1.as_int() != plane_exponent) {
264 cout << "the planar ternanry ring does not have the right number of automorphisms, not desarguesian" << endl;
265 ret = FALSE;
266 goto finish;
267 }
268
269 if (f_v) {
270 cout << "setting up the field of order " << plane_order << endl;
271 }
272 F.init(plane_order, FALSE, FALSE);
273 nb_inc = 0;
274 for (i = 0; i < m; i++) {
275 for (j = 0; j < n; j++) {
276 M2[i * n + j] = 0;
277 }
278 }
279 for (i = 0; i < 3; i++) {
280 for (j = 0; j < d; j++) {
281 M2[(i * d + j) * n + j] = 1;
282 nb_inc++;
283 }
284 }
285
286 for (i = 0; i < d; i++) {
287 for (j = 0; j < d; j++) {
288 a = F.add(i, j); // attention, we need the digits from 0 to d-1 !!
289 M2[i * n + d + i * d + j] = 1;
290 nb_inc++;
291 M2[(d + j) * n + d + i * d + j] = 1;
292 nb_inc++;
293 M2[(2 * d + a) * n + d + i * d + j] = 1;
294 nb_inc++;
295 }
296 }
297 for (i = 0; i < d; i++) {
298 for (j = 0; j < d; j++) {
299 a = F.mult(i, j); // attention, we need the digits from 0 to d-1 !!
300 M2[i * n + d + d2 + i * d + j] = 1;
301 nb_inc++;
302 M2[(d + j) * n + d + d2 + i * d + j] = 1;
303 nb_inc++;
304 M2[(2 * d + a) * n + d + d2 + i * d + j] = 1;
305 nb_inc++;
306 }
307 }
308 if (f_v) {
309 cout << "computing canonical labelling of the field of order " << plane_order << endl;
310 }
311#if 0
312 compute_canonical_labeling_of_01matrix(M2, m, n,
313 TRUE, row_parts, nb_row_parts, col_parts, nb_col_parts,
314 canonical_form2, canonical_form_inv2,
315 Aut_gens2,
317#endif
318 Aut_gens2.compute_group_order(ago2);
319 if (ago2.as_int() != plane_exponent) {
320 cout << "the field does not have the right number of automorphisms, something is wrong" << endl;
321 exit(1);
322 }
323 for (i = 0; i < d; i++) {
324 a = canonical_form1[canonical_form_inv2[i]];
325 field_element[i] = a;
326 field_element_inv[a] = i;
327 }
328 if (f_vv) {
329 for (i = 0; i < plane_order; i++) {
330 cout << "field element " << i << " = " << field_element[i] << endl;
331 }
332 }
333 if (field_element[0] != 0) {
334 cout << "field_element[0] != 0, something is wrong" << endl;
335 exit(1);
336 }
337 if (field_element[1] != 1) {
338 cout << "field_element[1] != 1, something is wrong" << endl;
339 exit(1);
340 }
341
342 // we double check everything once more:
343 for (i = 0; i < plane_order; i++) {
344 ii = field_element[i];
345 for (j = 0; j < plane_order; j++) {
346 jj = field_element[j];
347 k = F.add(i, j);
348 kk = MOLSsxb(0, ii, jj);
349 if (field_element[k] != kk) {
350 cout << "i=" << i << " j=" << j << " i+j=" << k << endl;
351 cout << "ii=" << ii << " jj=" << jj << " ii+jj=" << kk << endl;
352 cout << "but field_element[k]=" << field_element[k] << endl;
353 exit(1);
354 }
355 k = F.mult(i, j);
356 kk = MOLSsxb(plane_order, ii, jj);
357 if (field_element[k] != kk) {
358 cout << "i=" << i << " j=" << j << " i*j=" << k << endl;
359 cout << "ii=" << ii << " jj=" << jj << " ii*jj=" << kk << endl;
360 cout << "but field_element[k]=" << field_element[k] << endl;
361 exit(1);
362 }
363 }
364 }
365 // at this point, the fields are really isomorphic!!!
366
367 ret = TRUE;
368finish:
369 FREE_int(M1);
370 FREE_int(canonical_form1);
371 FREE_int(canonical_form_inv1);
372 //delete [] Aut_gens1;
373 FREE_int(M2);
374 FREE_int(canonical_form2);
375 FREE_int(canonical_form_inv2);
376 //delete [] Aut_gens2;
377
378 return ret;
379#endif
380}
381
382void point_line::init_projective_plane(int order, int verbose_level)
383{
384 int f_v = (verbose_level >= 1);
385 int i, j, h;
386
388 if (f_v) {
389 cout << "computing data for a projective plane of order "
390 << order << " with " << m << " points" << endl;
391 }
392 plane_order = order;
393 nb_pts = m;
396 for (i = 0; i < nb_pts; i++) {
398 plane.points_on_lines + i * (plane_order + 1));
399 }
400 for (i = 0; i < nb_pts; i++) {
402 for (j = i + 1; j < nb_pts; j++) {
406 }
407 }
408
411 for (i = 0; i < nb_pts; i++) {
414 }
415 for (i = 0; i < nb_pts; i++) {
417 for (j = i + 1; j < nb_pts; j++) {
418 h = plane_line_intersection(i, j);
421 }
422 }
423
424 if (f_v) {
425 cout << "allocating data for the coordinatization" << endl;
426 }
427
429 points = NEW_int(m);
430 // pt_labels and points are mutually inverse permutations of {0,1,...,m-1}
431
440 if (f_v) {
441 cout << "finished" << endl;
442 }
444}
445
447{
460 FREE_int(MOLS);
464 }
465}
466
467void point_line::plane_report(ostream &ost)
468{
469 int i, j, h;
470
471
472 ost << "lines on points:" << endl;
473 ost << "pt : lines through pt" << endl;
474 for (i = 0; i < m; i++) {
475 ost << i << " & ";
476 for (j = 0; j <= plane_order; j++) {
477 ost << dual_plane.points_on_lines[i * (plane_order + 1) + j];
478 if (j < plane_order)
479 ost << ", ";
480 }
481 ost << endl;
482 }
483 ost << "points on lines:" << endl;
484 ost << "line : pts on line" << endl;
485 for (i = 0; i < m; i++) {
486 ost << i << " & ";
487 for (j = 0; j <= plane_order; j++) {
488 ost << plane.points_on_lines[i * (plane_order + 1) + j];
489 if (j < plane_order)
490 ost << ", ";
491 }
492 ost << endl;
493 }
494 ost << "lines through two points:" << endl;
495 ost << "pt_1, pt_2 : line through pt_1 and pt_2" << endl;
496 for (i = 0; i < m; i++) {
497 for (j = i + 1; j < m; j++) {
499 ost << i << ", " << j << " & " << h << endl;
500 }
501 }
502 ost << "intersections of lines:" << endl;
503 ost << "line_1, line_2 : point of intersection" << endl;
504 for (i = 0; i < m; i++) {
505 for (j = i + 1; j < m; j++) {
507 ost << i << ", " << j << " & " << h << endl;
508 }
509 }
510
511}
512
514{
515 if (pt1 == pt2) {
516 cout << "point_line::plane_line_through_two_points "
517 "pts are equal" << endl;
518 exit(1);
519 }
521 return plane.line_through_two_points[pt1 * nb_pts + pt2];
522 }
523 else {
524 int j;
525
526 for (j = 0; j < n; j++) {
527 if (a[pt1 * n + j] && a[pt2 * n + j])
528 return j;
529 }
530 cout << "point_line::plane_line_through_two_points "
531 "there is no line through pt1=" << pt1
532 << " and pt2=" << pt2 << endl;
533 exit(1);
534 }
535}
536
537int point_line::plane_line_intersection(int line1, int line2)
538{
539 if (line1 == line2) {
540 cout << "point_line::plane_line_intersection "
541 "lines are equal" << endl;
542 exit(1);
543 }
545 return dual_plane.line_through_two_points[line1 * nb_pts + line2];
546 }
547 else {
548 int i;
549
550 for (i = 0; i < m; i++) {
551 if (a[i * n + line1] && a[i * n + line2])
552 return i;
553 }
554 cout << "point_line::plane_line_intersection "
555 "there is no common point to line1=" << line1
556 << " and line2=" << line2 << endl;
557 exit(1);
558 }
559}
560
562{
564 int j;
565
566 for (j = 0; j <= plane_order; j++) {
567 pts[j] = plane.points_on_lines[line * (plane_order + 1) + j];
568 }
569 }
570 else {
571 int i, l;
572
573 l = 0;
574 for (i = 0; i < m; i++) {
575 if (a[i * n + line]) {
576 pts[l++] = i;
577 }
578 }
579 if (l != plane_order + 1) {
580 cout << "point_line::plane_get_points_on_line "
581 "l != plane_order + 1" << endl;
582 exit(1);
583 }
584 }
585}
586
588{
590 int j;
591
592 for (j = 0; j <= plane_order; j++) {
593 lines[j] = dual_plane.points_on_lines[pt * (plane_order + 1) + j];
594 }
595 }
596 else {
597 int j, l;
598
599 l = 0;
600 for (j = 0; j < m; j++) {
601 if (a[pt * n + j]) {
602 lines[l++] = j;
603 }
604 }
605 if (l != plane_order + 1) {
606 cout << "point_line::plane_get_lines_through_point "
607 "l != plane_order + 1" << endl;
608 exit(1);
609 }
610 }
611}
612
613int point_line::plane_points_collinear(int pt1, int pt2, int pt3)
614{
615 int line;
616 line = plane_line_through_two_points(pt1, pt2);
617 if (a[pt3 * n + line])
618 return TRUE;
619 else
620 return FALSE;
621}
622
623int point_line::plane_lines_concurrent(int line1, int line2, int line3)
624{
625 int pt;
626 pt = plane_line_intersection(line1, line2);
627 if (a[pt * n + line3])
628 return TRUE;
629 else
630 return FALSE;
631}
632
633int point_line::plane_first_quadrangle(int &pt1, int &pt2, int &pt3, int &pt4)
634{
635 // int v = m;
636 int pts[4];
637
638 pts[0] = pt1;
639 pts[1] = pt2;
640 pts[2] = pt3;
641 pts[3] = pt4;
642 if (!plane_quadrangle_first_i(pts, 0)) {
643 cout << "point_line::plane_first_quadrangle "
644 "no quadrangle" << endl;
645 exit(1);
646 }
647 else {
648 pt1 = pts[0];
649 pt2 = pts[1];
650 pt3 = pts[2];
651 pt4 = pts[3];
652 return TRUE;
653 }
654}
655
656int point_line::plane_next_quadrangle(int &pt1, int &pt2, int &pt3, int &pt4)
657{
658 // int v = m;
659 int pts[4];
660
661 pts[0] = pt1;
662 pts[1] = pt2;
663 pts[2] = pt3;
664 pts[3] = pt4;
665 if (!plane_quadrangle_next_i(pts, 0)) {
666 return FALSE;
667 }
668 else {
669 pt1 = pts[0];
670 pt2 = pts[1];
671 pt3 = pts[2];
672 pt4 = pts[3];
673 return TRUE;
674 }
675}
676
678{
679 int v = m, pt0;
680
681 if (i > 0)
682 pt0 = pt[i - 1] + 1;
683 else
684 pt0 = 0;
685 for (pt[i] = pt0; pt[i] < v; pt[i]++) {
686 if (i == 2) {
687 if (plane_points_collinear(pt[0], pt[1], pt[2]))
688 continue;
689 }
690 else if (i == 3) {
691 if (plane_points_collinear(pt[0], pt[1], pt[3]))
692 continue;
693 if (plane_points_collinear(pt[0], pt[2], pt[3]))
694 continue;
695 if (plane_points_collinear(pt[1], pt[2], pt[3]))
696 continue;
697 }
698
699 if (i == 3)
700 return TRUE;
701 else {
702 if (!plane_quadrangle_first_i(pt, i + 1))
703 continue;
704 else
705 return TRUE;
706 }
707 }
708 return FALSE;
709}
710
712{
713 int v = m;
714
715 if (i < 3) {
716 if (plane_quadrangle_next_i(pt, i + 1))
717 return TRUE;
718 }
719 while (pt[i] < v) {
720 pt[i]++;
721 if (i == 2) {
722 if (plane_points_collinear(pt[0], pt[1], pt[2]))
723 continue;
724 }
725 else if (i == 3) {
726 if (plane_points_collinear(pt[0], pt[1], pt[3]))
727 continue;
728 if (plane_points_collinear(pt[0], pt[2], pt[3]))
729 continue;
730 if (plane_points_collinear(pt[1], pt[2], pt[3]))
731 continue;
732 }
733 if (i == 3)
734 return TRUE;
735 else {
736 if (!plane_quadrangle_first_i(pt, i + 1))
737 continue;
738 else
739 return TRUE;
740 }
741 }
742 return FALSE;
743}
744
745void point_line::coordinatize_plane(int O, int I, int X, int Y,
746 int *MOLS, int verbose_level)
747// needs pt_labels, points, pts_on_line_x_eq_y, pts_on_line_x_eq_y_labels,
748// lines_through_X, lines_through_Y, pts_on_line, MOLS to be allocated
749{
750 int f_v = (verbose_level >= 1);
751 int i, j, ii, jj, x, y, l, pt, line, pt2, pt3, b, pt_label;
752 int slope;
753
754
755 quad_O = O;
756 quad_I = I;
757 quad_X = X;
758 quad_Y = Y;
763
764 if (f_v) {
765 cout << "coordinatizing plane with O=" << O
766 << " I=" << I << " X=" << X << " Y=" << Y << endl;
767 cout << "plane_order=" << plane_order << endl;
768 cout << "m=" << m << endl;
769 }
770
771 // label the points on the line y = x:
772 // first we label them as points in the coordinatized plane,
773 // second we label them as elements from 0 to plane_order
774 // O = (0,0) = 0
775 // I = (1,1) = 1
776 // C = (1) = plane_order
777 // the remaining points are labeled (l,l)
778 // in arbitrary order, 2 \le l < plane_order
779
780
783 line_infty); // the point at infinity (1)
784 l = 2;
785 for (i = 0; i <= plane_order; i++) {
786 pt = pts_on_line_x_eq_y[i];
787 if (pt == O) {
789 pt_labels[pt] = 0 * plane_order + 0;
790 }
791 else if (pt == I) {
793 pt_labels[pt] = 1 * plane_order + 1;
794 }
795 else if (pt == quad_C) {
798 }
799 else {
801 pt_labels[pt] = l * plane_order + l;
802 l++;
803 }
804 }
805 if (f_v) {
806 cout << "points on line y=x:" << endl;
807 for (i = 0; i <= plane_order; i++) {
808 cout << pts_on_line_x_eq_y[i] << " : "
809 << pts_on_line_x_eq_y_labels[i] << endl;
810 }
811 }
812
813 // label the affine points:
814 // (x,y) = x * plane_order + y
817
818 for (i = 0; i <= plane_order; i++) {
819 if (lines_through_X[i] == line_infty)
820 continue;
822 y = pt_labels[ii] % plane_order;
823 // cout << "ii=" << ii << " y=" << y << endl;
824
825 for (j = 0; j <= plane_order; j++) {
826 if (lines_through_Y[j] == line_infty)
827 continue;
829 x = pt_labels[jj] % plane_order;
830 // cout << "jj=" << jj << " x=" << x << endl;
831
834
835 points[x * plane_order + y] = pt;
836 pt_labels[pt] = x * plane_order + y;
837 }
838 }
839 if (f_v) {
840 cout << "the affine points (x,y):" << endl;
841 for (x = 0; x < plane_order; x++) {
842 for (y = 0; y < plane_order; y++) {
843 cout << "(" << x << ", " << y << ")="
844 << points[x * plane_order + y] << endl;
845 }
846 }
847 }
848
849 // label the points at infinity:
850 if (f_v) {
851 cout << "the points at infinity:" << endl;
852 }
853 for (y = 0; y < plane_order; y++) {
854 pt = points[1 * plane_order + y];
855 line = plane_line_through_two_points(O, pt);
857 pt_labels[pt2] = plane_order * plane_order + y;
858 points[plane_order * plane_order + y] = pt2;
859 if (f_v) {
860 cout << "y=" << y << " pt " << pt2 << endl;
861 }
862 }
863 pt_labels[Y] = plane_order * plane_order + plane_order; // (infty)
864
865 if (f_v) {
866 cout << "all point labels:" << endl;
867 for (i = 0; i < m; i++) {
868 cout << i << " : " << pt_labels[i] << endl;
869 }
870 }
871
872 // get the mutually orthogonal latin squares:
873 // first we fill MOLS {1,2,...,plane_order-1}
874
875 for (slope = 1; slope < plane_order; slope++) {
876
877 pt2 = points[plane_order * plane_order + slope];
878 // the point (slope) at infinity
879
880 for (b = 0; b < plane_order; b++) {
881
882 // we consider the line: y = slope * x + b
883 // we let the (x,b) entry in the MOL
884 // corresponding to slope be y
885
886 pt = points[0 * plane_order + b]; // y intercept
887
888 line = plane_line_through_two_points(pt, pt2);
889 // this is the line y = slope * x + b
890
891
893 // we loop over all affine points on this line
894 // i.e., all points except for (slope)
895
896 for (i = 0; i <= plane_order; i++) {
897 pt3 = pts_on_line[i];
898 if (pt3 == pt2)
899 continue; // skip (slope)
900
901 pt_label = pt_labels[pt3];
902 x = pt_label / plane_order;
903 y = pt_label % plane_order;
904 MOLSsxb(slope, x, b) = y;
905 //MOLS[slope * plane_order *
906 //plane_order + x * plane_order + b] = y;
907 }
908 }
909 }
910
911 // we can recover addition from the slope-1 lines as y = x + b
912 // this information will go into MOLS 0
913 slope = 1;
914 for (x = 0; x < plane_order; x++) {
915 for (b = 0; b < plane_order; b++) {
916 y = MOLSsxb(slope, x, b);
917 //y = MOLS[slope * plane_order * plane_order
918 //+ x * plane_order + b];
919 MOLSsxb(0, x, b) = y;
920 //MOLS[0 * plane_order * plane_order
921 // + x * plane_order + b] = y;
922 }
923 }
924 // we can recover multiplication from the lines
925 // with y-intercept 0 as y = slope * x + 0
926 // this information will go into MOLS plane_order
927 b = 0;
928 for (slope = 0; slope < plane_order; slope++) {
929 for (x = 0; x < plane_order; x++) {
930 if (slope == 0 || x == 0)
931 y = 0;
932 else {
933 y = MOLSsxb(slope, x, b);
934 //y = MOLS[slope * plane_order *
935 // plane_order + x * plane_order + b];
936 }
937 MOLSsxb(plane_order, slope, x) = y;
938 //MOLS[plane_order * plane_order * plane_order
939 // + slope * plane_order + x] = y;
940 }
941 }
942
943 if (f_v) {
944 print_MOLS(cout);
945 cout << "finished" << endl;
946 }
947}
948
949int &point_line::MOLSsxb(int s, int x, int b)
950{
951 return MOLS[s * plane_order * plane_order + x * plane_order + b];
952}
953
954int &point_line::MOLSaddition(int a, int b)
955{
956 return MOLSsxb(0, a, b);
957}
958
960{
961 return MOLSsxb(plane_order, a, b);
962}
963
964int point_line::ternary_field_is_linear(int *MOLS, int verbose_level)
965{
966 int f_v = (verbose_level >= 1);
967 int x, m, b, y1, mx, y2;
968 int *addition = MOLS;
969 int *multiplication = MOLS + plane_order * plane_order * plane_order;
970
971 for (m = 1; m < plane_order; m++) {
972 for (x = 0; x < plane_order; x++) {
973 mx = multiplication[m * plane_order + x];
974 for (b = 0; b < plane_order; b++) {
975 y1 = MOLS[m * plane_order * plane_order + x * plane_order + b];
976 y2 = addition[mx * plane_order + b];
977 if (y1 != y2) {
978 if (f_v) {
979 cout << "not linear:" << endl;
980 cout << "m=" << m << endl;
981 cout << "x=" << x << endl;
982 cout << "b=" << b << endl;
983 cout << "y1=" << y1 << endl;
984 cout << "mx=" << mx << endl;
985 cout << "y2=" << y2 << endl;
986 }
987 return FALSE;
988 }
989 }
990 }
991 }
992 return TRUE;
993}
994
995void point_line::print_MOLS(ostream &ost)
996{
997 int *M, slope, i, j;
998
999 ost << "all mutually orthogonal latin squares:" << endl;
1000 ost << "addition:" << endl;
1001 get_MOLm(MOLS, plane_order, 0, M);
1002 for (i = 0; i < plane_order; i++) {
1003 for (j = 0; j < plane_order; j++) {
1004 ost << setw(2) << M[i * plane_order + j] << " ";
1005 }
1006 ost << endl;
1007 }
1008 FREE_int(M);
1009 ost << "multiplication:" << endl;
1011 for (i = 0; i < plane_order; i++) {
1012 for (j = 0; j < plane_order; j++) {
1013 ost << setw(2) << M[i * plane_order + j] << " ";
1014 }
1015 ost << endl;
1016 }
1017 FREE_int(M);
1018 for (slope = 1; slope < plane_order; slope++) {
1019 ost << "for slope=" << slope << endl;
1020 get_MOLm(MOLS, plane_order, slope, M);
1021 for (i = 0; i < plane_order; i++) {
1022 for (j = 0; j < plane_order; j++) {
1023 ost << setw(2) << M[i * plane_order + j] << " ";
1024 }
1025 ost << endl;
1026 }
1027 FREE_int(M);
1028 }
1029}
1030
1032 int &order, int verbose_level)
1033// if it is a projective plane, the order is returned.
1034// otherwise, 0 is returned.
1035{
1036 int f_v = (verbose_level >= 1);
1037 int f_vv = (verbose_level >= 2);
1038 int v, n, r, k, lambda, mu;
1039
1040 if (f_v) {
1041 cout << "point_line::is_projective_plane checking for projective plane:" << endl;
1042 }
1043 if (P.ht != 2) {
1044 if (f_vv) {
1045 cout << "not a projective plane: "
1046 "partition has more than two parts" << endl;
1047 }
1048 return FALSE;
1049 }
1050 if (P.cellSize[0] != P.cellSize[1]) {
1051 if (f_vv) {
1052 cout << "not a projective plane: "
1053 "partition classes have different sizes" << endl;
1054 }
1055 return FALSE;
1056 }
1057 v = P.cellSize[0];
1058 r = count_RC(P, 0, 1);
1059 if (r == -1) {
1060 if (f_vv) {
1061 cout << "not a projective plane: "
1062 "r not constant" << endl;
1063 }
1064 return FALSE;
1065 }
1066 k = count_CR(P, 1, 0);
1067 if (k == -1) {
1068 if (f_vv) {
1069 cout << "not a projective plane: "
1070 "k not constant" << endl;
1071 }
1072 return FALSE;
1073 }
1074 if (f_vv) {
1075 cout << "r = " << r << endl;
1076 cout << "k = " << k << endl;
1077 }
1078 if (r != k) {
1079 if (f_vv) {
1080 cout << "not a projective plane: r != k" << endl;
1081 }
1082 return FALSE;
1083 }
1084 if (r < 3) {
1085 if (f_vv) {
1086 cout << "not a projective plane: r < 3" << endl;
1087 }
1088 return FALSE;
1089 }
1090 n = r - 1;
1091 if (v != n * n + n + 1) {
1092 if (f_vv) {
1093 cout << "not a projective plane: "
1094 "v != n^2 + n + 1" << endl;
1095 }
1096 return FALSE;
1097 }
1098 lambda = count_pairs_RRC(P, 0, 0, 1);
1099 if (lambda != 1) {
1100 if (f_vv) {
1101 cout << "not a projective plane: "
1102 "rows are not joined correctly" << endl;
1103 }
1104 return FALSE;
1105 }
1106 mu = count_pairs_CCR(P, 1, 1, 0);
1107 if (mu != 1) {
1108 if (f_vv) {
1109 cout << "not a projective plane: "
1110 "cols are not joined correctly" << endl;
1111 }
1112 return FALSE;
1113 }
1114 if (f_vv) {
1115 cout << "lambda = " << lambda << endl;
1116 cout << "mu = " << mu << endl;
1117 }
1118 if (f_v) {
1119 cout << "detected a projective plane of order " << n << endl;
1120 }
1121 order = n;
1122 return TRUE;
1123}
1124
1126 int row_cell, int col_cell)
1127{
1128 int l1, i, nb = -1, nb1;
1129
1130 l1 = P.cellSize[row_cell];
1131 for (i = 0; i < l1; i++) {
1133 row_cell, i, col_cell);
1134 if (nb1 == -1)
1135 return -1;
1136 if (nb == -1) {
1137 nb = nb1;
1138 }
1139 else {
1140 if (nb1 != nb)
1141 return -1;
1142 }
1143 }
1144 return nb;
1145}
1146
1148 int col_cell, int row_cell)
1149{
1150 int l1, i, nb = -1, nb1;
1151
1152 l1 = P.cellSize[col_cell];
1153 for (i = 0; i < l1; i++) {
1154 nb1 = count_CR_representative(P, col_cell, i, row_cell);
1155 if (nb1 == -1)
1156 return -1;
1157 if (nb == -1) {
1158 nb = nb1;
1159 }
1160 else {
1161 if (nb1 != nb)
1162 return -1;
1163 }
1164 }
1165 return nb;
1166}
1167
1169 int row_cell, int row_cell_pt, int col_cell)
1170{
1171 int f1, f2, /*l1,*/ l2, e1, e2, j, s = 0;
1172 int first_column_element = P.startCell[1];
1173
1174 f1 = P.startCell[row_cell];
1175 f2 = P.startCell[col_cell];
1176 //l1 = P.cellSize[row_cell];
1177 l2 = P.cellSize[col_cell];
1178 e1 = P.pointList[f1 + row_cell_pt];
1179 for (j = 0; j < l2; j++) {
1180 e2 = P.pointList[f2 + j] - first_column_element;
1181 // cout << "e1=" << e1 << " e2=" << e2 << endl;
1182 if (a[e1 * n + e2])
1183 s++;
1184 }
1185 return s;
1186}
1187
1189 int col_cell, int col_cell_pt, int row_cell)
1190{
1191 int f1, f2, l1, /*l2,*/ e1, e2, i, s = 0;
1192 int first_column_element = P.startCell[1];
1193
1194 f1 = P.startCell[row_cell];
1195 f2 = P.startCell[col_cell];
1196 l1 = P.cellSize[row_cell];
1197 //l2 = P.cellSize[col_cell];
1198 e2 = P.pointList[f2 + col_cell_pt] - first_column_element;
1199 for (i = 0; i < l1; i++) {
1200 e1 = P.pointList[f1 + i];
1201 // cout << "e1=" << e1 << " e2=" << e2 << endl;
1202 if (a[e1 * n + e2])
1203 s++;
1204 }
1205 return s;
1206}
1207
1209 int row_cell1, int row_cell2, int col_cell)
1210{
1211 int l1, i, nb = -1, nb1;
1212
1213 l1 = P.cellSize[row_cell1];
1214 for (i = 0; i < l1; i++) {
1216 row_cell1, i, row_cell2, col_cell);
1217 if (nb1 == -1)
1218 return -1;
1219 if (nb == -1) {
1220 nb = nb1;
1221 }
1222 else {
1223 if (nb1 != nb)
1224 return -1;
1225 }
1226 }
1227 return nb;
1228}
1229
1231 int col_cell1, int col_cell2, int row_cell)
1232{
1233 int l1, i, nb = -1, nb1;
1234
1235 l1 = P.cellSize[col_cell1];
1236 for (i = 0; i < l1; i++) {
1238 col_cell1, i, col_cell2, row_cell);
1239 if (nb1 == -1)
1240 return -1;
1241 if (nb == -1) {
1242 nb = nb1;
1243 }
1244 else {
1245 if (nb1 != nb)
1246 return -1;
1247 }
1248 }
1249 return nb;
1250}
1251
1253 int row_cell1, int row_cell_pt, int row_cell2, int col_cell)
1254// returns the number of joinings from a point of
1255// row_cell1 to elements of row_cell2 within col_cell
1256// if that number exists, -1 otherwise
1257{
1258 int f1, f2, f3, /*l1,*/ l2, l3, e1, e2, e3, u, j, nb = -1, nb1;
1259 int first_column_element = P.startCell[1];
1260
1261 f1 = P.startCell[row_cell1];
1262 f2 = P.startCell[row_cell2];
1263 f3 = P.startCell[col_cell];
1264 //l1 = P.cellSize[row_cell1];
1265 l2 = P.cellSize[row_cell2];
1266 l3 = P.cellSize[col_cell];
1267 e1 = P.pointList[f1 + row_cell_pt];
1268 for (u = 0; u < l2; u++) {
1269 e2 = P.pointList[f2 + u];
1270 if (e1 == e2)
1271 continue;
1272 nb1 = 0;
1273 for (j = 0; j < l3; j++) {
1274 e3 = P.pointList[f3 + j] - first_column_element;
1275 if (a[e1 * n + e3] && a[e2 * n + e3]) {
1276 nb1++;
1277 }
1278 }
1279 // cout << "e1=" << e1 << " e2=" << e2
1280 //<< " e3=" << e3 << " nb=" << nb1 << endl;
1281 if (nb == -1) {
1282 nb = nb1;
1283 }
1284 else {
1285 if (nb1 != nb)
1286 return -1;
1287 }
1288 }
1289 return nb;
1290}
1291
1292
1294 int col_cell1, int col_cell_pt, int col_cell2, int row_cell)
1295// returns the number of joinings from a point of
1296// col_cell1 to elements of col_cell2 within row_cell
1297// if that number exists, -1 otherwise
1298{
1299 int f1, f2, f3, /*l1,*/ l2, l3, e1, e2, e3, u, i, nb = -1, nb1;
1300 int first_column_element = P.startCell[1];
1301
1302 f1 = P.startCell[col_cell1];
1303 f2 = P.startCell[col_cell2];
1304 f3 = P.startCell[row_cell];
1305 //l1 = P.cellSize[col_cell1];
1306 l2 = P.cellSize[col_cell2];
1307 l3 = P.cellSize[row_cell];
1308 e1 = P.pointList[f1 + col_cell_pt] - first_column_element;
1309 for (u = 0; u < l2; u++) {
1310 e2 = P.pointList[f2 + u] - first_column_element;
1311 if (e1 == e2)
1312 continue;
1313 nb1 = 0;
1314 for (i = 0; i < l3; i++) {
1315 e3 = P.pointList[f3 + i];
1316 if (a[e3 * n + e1] && a[e3 * n + e2]) {
1317 nb1++;
1318 }
1319 }
1320 // cout << "e1=" << e1 << " e2=" << e2 << " e3=" << e3
1321 //<< " nb=" << nb1 << endl;
1322 if (nb == -1) {
1323 nb = nb1;
1324 }
1325 else {
1326 if (nb1 != nb)
1327 return -1;
1328 }
1329 }
1330 return nb;
1331}
1332
1333
1334void point_line::get_MOLm(int *MOLS, int order, int m, int *&M)
1335{
1336 int x, b, y, *mol = MOLS + m * order * order;
1337
1338 M = NEW_int(order * order);
1339 for (x = 0; x < order; x++) {
1340 for (b = 0; b < order; b++) {
1341 y = mol[x * order + b];
1342 M[x * order + b] = y;
1343 }
1344 }
1345}
1346
1347}}}
1348
void set_print(std::ostream &ost, int *v, int len)
Definition: int_vec.cpp:1043
data structure for set partitions following Jeffrey Leon
int count_pairs_CCR(data_structures::partitionstack &P, int col_cell1, int col_cell2, int row_cell)
void init_projective_plane(int order, int verbose_level)
Definition: point_line.cpp:382
void plane_get_lines_through_point(int pt, int *lines)
Definition: point_line.cpp:587
int count_pairs_CCR_representative(data_structures::partitionstack &P, int col_cell1, int col_cell_pt, int col_cell2, int row_cell)
int ternary_field_is_linear(int *MOLS, int verbose_level)
Definition: point_line.cpp:964
data_structures::partitionstack * P
Definition: geometry.h:1699
int count_CR_representative(data_structures::partitionstack &P, int col_cell, int col_cell_pt, int row_cell)
int count_CR(data_structures::partitionstack &P, int col_cell, int row_cell)
int plane_next_quadrangle(int &pt1, int &pt2, int &pt3, int &pt4)
Definition: point_line.cpp:656
int count_RC_representative(data_structures::partitionstack &P, int row_cell, int row_cell_pt, int col_cell)
int plane_first_quadrangle(int &pt1, int &pt2, int &pt3, int &pt4)
Definition: point_line.cpp:633
int count_pairs_RRC(data_structures::partitionstack &P, int row_cell1, int row_cell2, int col_cell)
void coordinatize_plane(int O, int I, int X, int Y, int *MOLS, int verbose_level)
Definition: point_line.cpp:745
int plane_lines_concurrent(int line1, int line2, int line3)
Definition: point_line.cpp:623
int is_projective_plane(data_structures::partitionstack &P, int &order, int verbose_level)
void get_MOLm(int *MOLS, int order, int m, int *&M)
int count_RC(data_structures::partitionstack &P, int row_cell, int col_cell)
int count_pairs_RRC_representative(data_structures::partitionstack &P, int row_cell1, int row_cell_pt, int row_cell2, int col_cell)
int identify_field_not_of_prime_order(int verbose_level)
Definition: point_line.cpp:164
int plane_points_collinear(int pt1, int pt2, int pt3)
Definition: point_line.cpp:613
#define FREE_int(p)
Definition: foundations.h:640
#define NEW_int(n)
Definition: foundations.h:625
#define TRUE
Definition: foundations.h:231
#define FALSE
Definition: foundations.h:234
orbiter_kernel_system::orbiter_session * Orbiter
global Orbiter session
the orbiter library for the classification of combinatorial objects