1 | /////////////////////////////////////////////////////////////////////////////// |
---|
2 | version="version enumpoints.lib 4.3.0.0 Jan_2022 "; // $Id$ |
---|
3 | |
---|
4 | category="General purpose"; |
---|
5 | info=" |
---|
6 | LIBRARY: enumpoints.lib enumerating rational points |
---|
7 | AUTHOR: Jieao Song (8d1h) |
---|
8 | KEYWORDS: multivariate equations; finite field |
---|
9 | |
---|
10 | PROCEDURES: |
---|
11 | points(ideal I) points in the zero set of I |
---|
12 | projPoints(ideal I) projective points in the zero set of the homogeneous I |
---|
13 | "; |
---|
14 | /////////////////////////////////////////////////////////////////////////////// |
---|
15 | // utility function that lists all elements in the ground field |
---|
16 | static proc listFieldElements() |
---|
17 | { |
---|
18 | int k; |
---|
19 | int ch = char(basering); |
---|
20 | list els = list(); |
---|
21 | if (npars(basering)==0) { // Fp for p prime |
---|
22 | for (k=ch-1;k>=0;k--) { els[k+1]=k; } |
---|
23 | } |
---|
24 | else |
---|
25 | { // Fq defined by a minpoly |
---|
26 | ideal fct = factorize(var(1)^(ch^pardeg(minpoly))-var(1),1); |
---|
27 | for (k=size(fct);k>0;k--) |
---|
28 | { |
---|
29 | els[k]= -coeffs(fct[k],var(1))[1][1]; |
---|
30 | } |
---|
31 | } |
---|
32 | return(els); |
---|
33 | } |
---|
34 | /////////////////////////////////////////////////////////////////////////////// |
---|
35 | // enumerate points coordinate by coordinate using elimination |
---|
36 | // i: the current coordinate to enumerate |
---|
37 | // part: partially determined coordinates |
---|
38 | // els: elements of the field |
---|
39 | static proc enumPoints(ideal I,int i,list part,list els) |
---|
40 | { |
---|
41 | int k; ideal I1; list part1; |
---|
42 | list ans = list(); |
---|
43 | int n = nvars(basering); |
---|
44 | poly rest = 1; |
---|
45 | for (k=i+1;k<=n;k++) { rest = rest*var(k); } |
---|
46 | poly g = eliminate(I,rest)[1]; |
---|
47 | if (g!=0) |
---|
48 | { // when the eliminant is non-trivial, only enumerate its zeros |
---|
49 | vector cc; poly v; |
---|
50 | ideal fct = factorize(g,1); |
---|
51 | for (k=1;k<=ncols(fct);k++) |
---|
52 | { |
---|
53 | if (deg(fct[k])==1) |
---|
54 | { |
---|
55 | cc = coeffs(fct[k],var(i))[1]; |
---|
56 | part1 = part + list(-cc[1]/cc[2]); |
---|
57 | if (i==n) { ans[size(ans)+1]=part1; } |
---|
58 | else |
---|
59 | { |
---|
60 | I1 = std(reduce(I,fct[k])); |
---|
61 | ans = ans + enumPoints(I1,i+1,part1,els); |
---|
62 | } |
---|
63 | } |
---|
64 | // this can help find the splitting field |
---|
65 | // else { printf(" // %p", fct[k]); } |
---|
66 | } |
---|
67 | } |
---|
68 | else |
---|
69 | { // otherwise enumerate over the entire field |
---|
70 | for (k=1;k<=size(els);k++) |
---|
71 | { |
---|
72 | I1 = std(subst(I,var(i),els[k])); |
---|
73 | if (dim(I1)>-1) |
---|
74 | { |
---|
75 | part1 = part + list(els[k]); |
---|
76 | if (i==n) { ans[size(ans)+1]=part1; } |
---|
77 | else { ans = ans + enumPoints(I1,i+1,part1,els); } |
---|
78 | } |
---|
79 | } |
---|
80 | } |
---|
81 | return(ans); |
---|
82 | } |
---|
83 | /////////////////////////////////////////////////////////////////////////////// |
---|
84 | // enumerate points on a homogeneous ideal |
---|
85 | static proc enumProjPoints(ideal I,int i,list part,list els) |
---|
86 | { |
---|
87 | int j; int k; ideal I1; list part1; |
---|
88 | list ans = list(); |
---|
89 | int n = nvars(basering); |
---|
90 | for (k=i;k<=n;k++) |
---|
91 | { // find points of the form (1,..), (0,1,..), etc. |
---|
92 | I1 = I; |
---|
93 | part1 = part; |
---|
94 | for (j=i;j<k;j++) |
---|
95 | { |
---|
96 | part1 = part1 + list(0); |
---|
97 | I1 = subst(I1,var(j),0); |
---|
98 | } |
---|
99 | part1 = part1 + list(1); |
---|
100 | I1 = std(subst(I1,var(k),1)); |
---|
101 | if (dim(I1)>-1) |
---|
102 | { |
---|
103 | if (k==n) { ans = ans + list(part1); } |
---|
104 | else { ans = ans + enumPoints(I1,k+1,part1,els); } |
---|
105 | } |
---|
106 | } |
---|
107 | return(ans); |
---|
108 | } |
---|
109 | /////////////////////////////////////////////////////////////////////////////// |
---|
110 | // main interface |
---|
111 | proc points(ideal I) |
---|
112 | "USAGE: points(I); I homogeneous ideal |
---|
113 | RETURN: list of coordinates of points on the zero set of I |
---|
114 | ASSUMES: dim(I)==0 |
---|
115 | " |
---|
116 | { |
---|
117 | if (char(basering)==0 and dim(I) > 0) { ERROR("over number fields the ideal must be 0-dimensional")}; |
---|
118 | return(enumPoints(I,1,list(),listFieldElements())); |
---|
119 | } |
---|
120 | /////////////////////////////////////////////////////////////////////////////// |
---|
121 | proc projPoints(ideal I) |
---|
122 | // enumerate points on a homogeneous ideal |
---|
123 | "USAGE: projPoints(I); I homogeneous ideal |
---|
124 | RETURN: list of coordinates of points on the zero set of I |
---|
125 | ASSUMES: dim(I)==0 |
---|
126 | " |
---|
127 | { |
---|
128 | if (!homog(I)) { ERROR("the ideal is not homogeneous"); } |
---|
129 | if (char(basering)==0 and dim(I) > 1) { ERROR("over number fields the ideal must be 0-dimensional")}; |
---|
130 | return(enumProjPoints(I,1,list(),listFieldElements())); |
---|
131 | } |
---|
132 | example |
---|
133 | { |
---|
134 | // The set of nodes is a 0-dimensional variety over a number field. |
---|
135 | ring R2 = (0,q),(x,y,z,w),dp; |
---|
136 | minpoly = q16-q12+q8-q4+1; |
---|
137 | poly s = 2q13-q9-q7+q5-q3-q; |
---|
138 | ideal Togliatti = 64*(x-w)*(x^4 -4*x^3*w -10*x^2*y^2 -4*x^2*w^2 +16*x*w^3 -20*x*y^2*w+5*y^4 +16*w^4 -20*y^2*w^2) -5*s*(2*z -s*w)*(4*(x^2+y^2-z^2) +(1+3*(5-s^2))*w^2)^2; |
---|
139 | matrix Jac = jacob(Togliatti); |
---|
140 | ideal I2 = Togliatti+Jac; |
---|
141 | list L=projPoints(std(I2)); |
---|
142 | L[1]; |
---|
143 | size(L); |
---|
144 | } |
---|
145 | /////////////////////////////////////////////////////////////////////////////// |
---|
146 | |
---|