Path: blob/master/sage/schemes/generic/rational_point.py
4069 views
r"""1Enumeration of rational points on affine and projective schemes23Naive algorithms for enumerating rational points over `\QQ` or finite fields4over for general schemes.56.. WARNING::78Incorrect results and infinite loops may occur if using a wrong function.9(For instance using an affine function for a projective scheme or a finite10field function for a scheme defined over an infinite field.)1112EXAMPLES:1314Projective, over `\QQ`::1516sage: from sage.schemes.generic.rational_point import enum_projective_rational_field17sage: P.<X,Y,Z> = ProjectiveSpace(2,QQ)18sage: C = P.subscheme([X+Y-Z])19sage: enum_projective_rational_field(C,3)20[(-2 : 3 : 1), (-1 : 1 : 0), (-1 : 2 : 1), (-1/2 : 3/2 : 1),21(0 : 1 : 1), (1/3 : 2/3 : 1), (1/2 : 1/2 : 1), (2/3 : 1/3 : 1),22(1 : 0 : 1), (3/2 : -1/2 : 1), (2 : -1 : 1), (3 : -2 : 1)]2324Affine, over `\QQ`::2526sage: from sage.schemes.generic.rational_point import enum_affine_rational_field27sage: A.<x,y,z> = AffineSpace(3,QQ)28sage: S = A.subscheme([2*x-3*y])29sage: enum_affine_rational_field(S,2)30[(0, 0, -2), (0, 0, -1), (0, 0, -1/2), (0, 0, 0),31(0, 0, 1/2), (0, 0, 1), (0, 0, 2)]3233Projective over a finite field::3435sage: from sage.schemes.generic.rational_point import enum_projective_finite_field36sage: E = EllipticCurve('72').change_ring(GF(19))37sage: enum_projective_finite_field(E)38[(0 : 1 : 0), (1 : 0 : 1), (3 : 0 : 1), (4 : 9 : 1), (4 : 10 : 1),39(6 : 6 : 1), (6 : 13 : 1), (7 : 6 : 1), (7 : 13 : 1), (9 : 4 : 1),40(9 : 15 : 1), (12 : 8 : 1), (12 : 11 : 1), (13 : 8 : 1), (13 : 11 : 1),41(14 : 3 : 1), (14 : 16 : 1), (15 : 0 : 1), (16 : 9 : 1), (16 : 10 : 1),42(17 : 7 : 1), (17 : 12 : 1), (18 : 9 : 1), (18 : 10 : 1)]4344Affine over a finite field::4546sage: from sage.schemes.generic.rational_point import enum_affine_finite_field47sage: A.<w,x,y,z> = AffineSpace(4,GF(2))48sage: enum_affine_finite_field(A(GF(2)))49[(0, 0, 0, 0), (0, 0, 0, 1), (0, 0, 1, 0), (0, 0, 1, 1), (0, 1, 0, 0),50(0, 1, 0, 1), (0, 1, 1, 0), (0, 1, 1, 1), (1, 0, 0, 0), (1, 0, 0, 1),51(1, 0, 1, 0), (1, 0, 1, 1), (1, 1, 0, 0), (1, 1, 0, 1), (1, 1, 1, 0),52(1, 1, 1, 1)]5354AUTHORS:5556- David R. Kohel <[email protected]>: original version.5758- John Cremona and Charlie Turner <[email protected]> (06-2010):59improvements to clarity and documentation.60"""616263#*******************************************************************************64# Copyright (C) 2010 William Stein, David Kohel, John Cremona, Charlie Turner65# Distributed under the terms of the GNU General Public License (GPL)66# http://www.gnu.org/licenses/67#*******************************************************************************686970from sage.rings.arith import gcd71from sage.rings.all import ZZ72from sage.misc.all import srange, cartesian_product_iterator73from sage.schemes.all import is_Scheme7475def enum_projective_rational_field(X,B):76r"""77Enumerates projective, rational points on scheme ``X`` of height up to78bound ``B``.7980INPUT:8182- ``X`` - a scheme or set of abstract rational points of a scheme;83- ``B`` - a positive integer bound.8485OUTPUT:8687- a list containing the projective points of ``X`` of height up to ``B``,88sorted.8990EXAMPLES::9192sage: P.<X,Y,Z> = ProjectiveSpace(2,QQ)93sage: C = P.subscheme([X+Y-Z])94sage: from sage.schemes.generic.rational_point import enum_projective_rational_field95sage: enum_projective_rational_field(C(QQ),6)96[(-5 : 6 : 1), (-4 : 5 : 1), (-3 : 4 : 1), (-2 : 3 : 1),97(-3/2 : 5/2 : 1), (-1 : 1 : 0), (-1 : 2 : 1), (-2/3 : 5/3 : 1),98(-1/2 : 3/2 : 1), (-1/3 : 4/3 : 1), (-1/4 : 5/4 : 1),99(-1/5 : 6/5 : 1), (0 : 1 : 1), (1/6 : 5/6 : 1), (1/5 : 4/5 : 1),100(1/4 : 3/4 : 1), (1/3 : 2/3 : 1), (2/5 : 3/5 : 1), (1/2 : 1/2 : 1),101(3/5 : 2/5 : 1), (2/3 : 1/3 : 1), (3/4 : 1/4 : 1), (4/5 : 1/5 : 1),102(5/6 : 1/6 : 1), (1 : 0 : 1), (6/5 : -1/5 : 1), (5/4 : -1/4 : 1),103(4/3 : -1/3 : 1), (3/2 : -1/2 : 1), (5/3 : -2/3 : 1), (2 : -1 : 1),104(5/2 : -3/2 : 1), (3 : -2 : 1), (4 : -3 : 1), (5 : -4 : 1),105(6 : -5 : 1)]106sage: enum_projective_rational_field(C,6) == enum_projective_rational_field(C(QQ),6)107True108109::110111sage: P3.<W,X,Y,Z> = ProjectiveSpace(3,QQ)112sage: enum_projective_rational_field(P3,1)113[(-1 : -1 : -1 : 1), (-1 : -1 : 0 : 1), (-1 : -1 : 1 : 0), (-1 : -1 : 1 : 1),114(-1 : 0 : -1 : 1), (-1 : 0 : 0 : 1), (-1 : 0 : 1 : 0), (-1 : 0 : 1 : 1),115(-1 : 1 : -1 : 1), (-1 : 1 : 0 : 0), (-1 : 1 : 0 : 1), (-1 : 1 : 1 : 0),116(-1 : 1 : 1 : 1), (0 : -1 : -1 : 1), (0 : -1 : 0 : 1), (0 : -1 : 1 : 0),117(0 : -1 : 1 : 1), (0 : 0 : -1 : 1), (0 : 0 : 0 : 1), (0 : 0 : 1 : 0),118(0 : 0 : 1 : 1), (0 : 1 : -1 : 1), (0 : 1 : 0 : 0), (0 : 1 : 0 : 1),119(0 : 1 : 1 : 0), (0 : 1 : 1 : 1), (1 : -1 : -1 : 1), (1 : -1 : 0 : 1),120(1 : -1 : 1 : 0), (1 : -1 : 1 : 1), (1 : 0 : -1 : 1), (1 : 0 : 0 : 0),121(1 : 0 : 0 : 1), (1 : 0 : 1 : 0), (1 : 0 : 1 : 1), (1 : 1 : -1 : 1),122(1 : 1 : 0 : 0), (1 : 1 : 0 : 1), (1 : 1 : 1 : 0), (1 : 1 : 1 : 1)]123124ALGORITHM:125126We just check all possible projective points in correct dimension127of projective space to see if they lie on ``X``.128129AUTHORS:130131- John Cremona and Charlie Turner (06-2010)132"""133if is_Scheme(X):134X = X(X.base_ring())135n = X.codomain().ambient_space().ngens()136zero = (0,) * n137pts = []138for c in cartesian_product_iterator([srange(-B,B+1) for _ in range(n)]):139if gcd(c) == 1 and c > zero:140try:141pts.append(X(c))142except TypeError:143pass144pts.sort()145return pts146147def enum_affine_rational_field(X,B):148"""149Enumerates affine rational points on scheme ``X`` (defined over `\QQ`) up150to bound ``B``.151152INPUT:153154- ``X`` - a scheme or set of abstract rational points of a scheme;155- ``B`` - a positive integer bound.156157OUTPUT:158159- a list containing the affine points of ``X`` of height up to ``B``,160sorted.161162EXAMPLES::163164sage: A.<x,y,z> = AffineSpace(3,QQ)165sage: from sage.schemes.generic.rational_point import enum_affine_rational_field166sage: enum_affine_rational_field(A(QQ),1)167[(-1, -1, -1), (-1, -1, 0), (-1, -1, 1), (-1, 0, -1), (-1, 0, 0), (-1, 0, 1),168(-1, 1, -1), (-1, 1, 0), (-1, 1, 1), (0, -1, -1), (0, -1, 0), (0, -1, 1),169(0, 0, -1), (0, 0, 0), (0, 0, 1), (0, 1, -1), (0, 1, 0), (0, 1, 1), (1, -1, -1),170(1, -1, 0), (1, -1, 1), (1, 0, -1), (1, 0, 0), (1, 0, 1), (1, 1, -1), (1, 1, 0),171(1, 1, 1)]172173::174175sage: A.<w,x,y,z> = AffineSpace(4,QQ)176sage: S = A.subscheme([x^2-y*z+3,w^3+z+y^2])177sage: enum_affine_rational_field(S(QQ),2)178[]179sage: enum_affine_rational_field(S(QQ),3)180[(-2, 0, -3, -1)]181182::183184sage: A.<x,y> = AffineSpace(2,QQ)185sage: C = Curve(x^2+y-x)186sage: enum_affine_rational_field(C,10)187[(-2, -6), (-1, -2), (0, 0), (1, 0), (2, -2), (3, -6)]188189190AUTHORS:191192- David R. Kohel <[email protected]>: original version.193194- Charlie Turner (06-2010): small adjustments.195"""196if is_Scheme(X):197X = X(X.base_ring())198n = X.codomain().ambient_space().ngens()199if X.value_ring() is ZZ:200Q = [ 1 ]201else: # rational field202Q = range(1, B + 1)203R = [ 0 ] + [ s*k for k in range(1, B+1) for s in [1, -1] ]204pts = []205P = [0] * n206m = ZZ(0)207try:208pts.append(X(P))209except TypeError:210pass211iters = [ iter(R) for _ in range(n) ]212for it in iters:213it.next()214i = 0215while i < n:216try:217a = ZZ(iters[i].next())218except StopIteration:219iters[i] = iter(R) # reset220P[i] = iters[i].next() # reset P[i] to 0 and increment221i += 1222continue223m = m.gcd(a)224P[i] = a225for b in Q:226if m.gcd(b) == 1:227try:228pts.append(X([ num/b for num in P ]))229except TypeError:230pass231i = 0232m = ZZ(0)233pts.sort()234return pts235236def enum_projective_finite_field(X):237"""238Enumerates projective points on scheme ``X`` defined over a finite field.239240INPUT:241242- ``X`` - a scheme defined over a finite field or a set of abstract243rational points of such a scheme.244245OUTPUT:246247- a list containing the projective points of ``X`` over the finite field,248sorted.249250EXAMPLES::251252sage: F = GF(53)253sage: P.<X,Y,Z> = ProjectiveSpace(2,F)254sage: from sage.schemes.generic.rational_point import enum_projective_finite_field255sage: len(enum_projective_finite_field(P(F)))2562863257sage: 53^2+53+12582863259260::261262sage: F = GF(9,'a')263sage: P.<X,Y,Z> = ProjectiveSpace(2,F)264sage: C = Curve(X^3-Y^3+Z^2*Y)265sage: enum_projective_finite_field(C(F))266[(0 : 0 : 1), (0 : 1 : 1), (0 : 2 : 1), (1 : 1 : 0), (a + 1 : 2*a : 1),267(a + 1 : 2*a + 1 : 1), (a + 1 : 2*a + 2 : 1), (2*a + 2 : a : 1),268(2*a + 2 : a + 1 : 1), (2*a + 2 : a + 2 : 1)]269270::271272sage: F = GF(5)273sage: P2F.<X,Y,Z> = ProjectiveSpace(2,F)274sage: enum_projective_finite_field(P2F)275[(0 : 0 : 1), (0 : 1 : 0), (0 : 1 : 1), (0 : 2 : 1), (0 : 3 : 1), (0 : 4 : 1),276(1 : 0 : 0), (1 : 0 : 1), (1 : 1 : 0), (1 : 1 : 1), (1 : 2 : 1), (1 : 3 : 1),277(1 : 4 : 1), (2 : 0 : 1), (2 : 1 : 0), (2 : 1 : 1), (2 : 2 : 1), (2 : 3 : 1),278(2 : 4 : 1), (3 : 0 : 1), (3 : 1 : 0), (3 : 1 : 1), (3 : 2 : 1), (3 : 3 : 1),279(3 : 4 : 1), (4 : 0 : 1), (4 : 1 : 0), (4 : 1 : 1), (4 : 2 : 1), (4 : 3 : 1),280(4 : 4 : 1)]281282ALGORITHM:283284Checks all points in projective space to see if they lie on X.285286.. WARNING::287288If ``X`` is defined over an infinite field, this code will not finish!289290AUTHORS:291292- John Cremona and Charlie Turner (06-2010).293"""294if is_Scheme(X):295X = X(X.base_ring())296n = X.codomain().ambient_space().ngens()-1297F = X.value_ring()298pts = []299for k in range(n+1):300for c in cartesian_product_iterator([F for _ in range(k)]):301try:302pts.append(X(list(c)+[1]+[0]*(n-k)))303except TypeError:304pass305pts.sort()306return pts307308def enum_affine_finite_field(X):309r"""310Enumerates affine points on scheme ``X`` defined over a finite field.311312INPUT:313314- ``X`` - a scheme defined over a finite field or a set of abstract315rational points of such a scheme.316317OUTPUT:318319- a list containing the affine points of ``X`` over the finite field,320sorted.321322EXAMPLES::323324sage: F = GF(7)325sage: A.<w,x,y,z> = AffineSpace(4,F)326sage: C = A.subscheme([w^2+x+4,y*z*x-6,z*y+w*x])327sage: from sage.schemes.generic.rational_point import enum_affine_finite_field328sage: enum_affine_finite_field(C(F))329[]330sage: C = A.subscheme([w^2+x+4,y*z*x-6])331sage: enum_affine_finite_field(C(F))332[(0, 3, 1, 2), (0, 3, 2, 1), (0, 3, 3, 3), (0, 3, 4, 4), (0, 3, 5, 6),333(0, 3, 6, 5), (1, 2, 1, 3), (1, 2, 2, 5), (1, 2, 3, 1), (1, 2, 4, 6),334(1, 2, 5, 2), (1, 2, 6, 4), (2, 6, 1, 1), (2, 6, 2, 4), (2, 6, 3, 5),335(2, 6, 4, 2), (2, 6, 5, 3), (2, 6, 6, 6), (3, 1, 1, 6), (3, 1, 2, 3),336(3, 1, 3, 2), (3, 1, 4, 5), (3, 1, 5, 4), (3, 1, 6, 1), (4, 1, 1, 6),337(4, 1, 2, 3), (4, 1, 3, 2), (4, 1, 4, 5), (4, 1, 5, 4), (4, 1, 6, 1),338(5, 6, 1, 1), (5, 6, 2, 4), (5, 6, 3, 5), (5, 6, 4, 2), (5, 6, 5, 3),339(5, 6, 6, 6), (6, 2, 1, 3), (6, 2, 2, 5), (6, 2, 3, 1), (6, 2, 4, 6),340(6, 2, 5, 2), (6, 2, 6, 4)]341342::343344sage: A.<x,y,z> = AffineSpace(3,GF(3))345sage: S = A.subscheme(x+y)346sage: enum_affine_finite_field(S)347[(0, 0, 0), (0, 0, 1), (0, 0, 2), (1, 2, 0), (1, 2, 1), (1, 2, 2),348(2, 1, 0), (2, 1, 1), (2, 1, 2)]349350ALGORITHM:351352Checks all points in affine space to see if they lie on X.353354.. WARNING::355356If ``X`` is defined over an infinite field, this code will not finish!357358AUTHORS:359360- John Cremona and Charlie Turner (06-2010)361"""362if is_Scheme(X):363X = X(X.base_ring())364n = X.codomain().ambient_space().ngens()365F = X.value_ring()366pts = []367for c in cartesian_product_iterator([F]*n):368try:369pts.append(X(c))370except:371pass372pts.sort()373return pts374375376