def selmer_group_iterator(self, S, m, proof=True): r""" Return an iterator through elements of the finite group `\QQ(S,m)`. INPUT: - ``S`` -- a set of primes - ``m`` -- a positive integer - ``proof`` -- ignored OUTPUT: An iterator yielding the distinct elements of `\QQ(S,m)`. See the docstring for :meth:`selmer_group` for more information. EXAMPLES:: sage: list(QQ.selmer_group_iterator((), 2)) [1, -1] sage: list(QQ.selmer_group_iterator((2,), 2)) [1, 2, -1, -2] sage: list(QQ.selmer_group_iterator((2,3), 2)) [1, 3, 2, 6, -1, -3, -2, -6] sage: list(QQ.selmer_group_iterator((5,), 2)) [1, 5, -1, -5] """ KSgens, ords = self.selmer_group(S=S, m=m, proof=proof, orders=True) one = self.one_element() from sage.misc.all import prod, cartesian_product_iterator for ev in cartesian_product_iterator([range(o) for o in ords]): yield prod([p**e for p,e in zip(KSgens, ev)], one)
def selmer_group_iterator(self, S, m, proof=True): r""" Return an iterator through elements of the finite group `\QQ(S,m)`. INPUT: - ``S`` -- a set of primes - ``m`` -- a positive integer - ``proof`` -- ignored OUTPUT: An iterator yielding the distinct elements of `\QQ(S,m)`. See the docstring for :meth:`selmer_group` for more information. EXAMPLES:: sage: list(QQ.selmer_group_iterator((), 2)) [1, -1] sage: list(QQ.selmer_group_iterator((2,), 2)) [1, 2, -1, -2] sage: list(QQ.selmer_group_iterator((2,3), 2)) [1, 3, 2, 6, -1, -3, -2, -6] sage: list(QQ.selmer_group_iterator((5,), 2)) [1, 5, -1, -5] """ KSgens, ords = self.selmer_group(S=S, m=m, proof=proof, orders=True) one = self.one_element() from sage.misc.all import prod, cartesian_product_iterator for ev in cartesian_product_iterator([range(o) for o in ords]): yield prod([p**e for p, e in zip(KSgens, ev)], one)
def __iter__(self): """ Return iterator over the elements of this affine space when defined over a finite field. EXAMPLES:: sage: FF = FiniteField(3) sage: AA = AffineSpace(FF, 0) sage: [ x for x in AA ] [()] sage: AA = AffineSpace(FF, 1, 'Z') sage: [ x for x in AA ] [(0), (1), (2)] sage: AA.<z,w> = AffineSpace(FF, 2) sage: [ x for x in AA ] [(0, 0), (0, 1), (0, 2), (1, 0), (1, 1), (1, 2), (2, 0), (2, 1), (2, 2)] AUTHOR: - David Kohel """ n = self.dimension_relative() R = self.base_ring() AHom = self.point_homset() C = AHom.codomain() for v in cartesian_product_iterator([R for _ in range(n)]): yield C._point(AHom, v, check=False)
def solve_mod(eqns, modulus, solution_dict=False): r""" Return all solutions to an equation or list of equations modulo the given integer modulus. Each equation must involve only polynomials in 1 or many variables. By default the solutions are returned as `n`-tuples, where `n` is the number of variables appearing anywhere in the given equations. The variables are in alphabetical order. INPUT: - ``eqns`` - equation or list of equations - ``modulus`` - an integer - ``solution_dict`` - bool (default: False); if True or non-zero, return a list of dictionaries containing the solutions. If there are no solutions, return an empty list (rather than a list containing an empty dictionary). Likewise, if there's only a single solution, return a list containing one dictionary with that solution. EXAMPLES:: sage: var('x,y') (x, y) sage: solve_mod([x^2 + 2 == x, x^2 + y == y^2], 14) [(4, 2), (4, 6), (4, 9), (4, 13)] sage: solve_mod([x^2 == 1, 4*x == 11], 15) [(14,)] Fermat's equation modulo 3 with exponent 5:: sage: var('x,y,z') (x, y, z) sage: solve_mod([x^5 + y^5 == z^5], 3) [(0, 0, 0), (0, 1, 1), (0, 2, 2), (1, 0, 1), (1, 1, 2), (1, 2, 0), (2, 0, 2), (2, 1, 0), (2, 2, 1)] We can solve with respect to a bigger modulus if it consists only of small prime factors:: sage: [d] = solve_mod([5*x + y == 3, 2*x - 3*y == 9], 3*5*7*11*19*23*29, solution_dict = True) sage: d[x] 12915279 sage: d[y] 8610183 For cases where there are relatively few solutions and the prime factors are small, this can be efficient even if the modulus itself is large:: sage: sorted(solve_mod([x^2 == 41], 10^20)) [(4538602480526452429,), (11445932736758703821,), (38554067263241296179,), (45461397519473547571,), (54538602480526452429,), (61445932736758703821,), (88554067263241296179,), (95461397519473547571,)] We solve a simple equation modulo 2:: sage: x,y = var('x,y') sage: solve_mod([x == y], 2) [(0, 0), (1, 1)] .. warning:: The current implementation splits the modulus into prime powers, then naively enumerates all possible solutions (starting modulo primes and then working up through prime powers), and finally combines the solution using the Chinese Remainder Theorem. The interface is good, but the algorithm is very inefficient if the modulus has some larger prime factors! Sage *does* have the ability to do something much faster in certain cases at least by using Groebner basis, linear algebra techniques, etc. But for a lot of toy problems this function as is might be useful. At least it establishes an interface. TESTS: Make sure that we short-circuit in at least some cases:: sage: solve_mod([2*x==1], 2*next_prime(10^50)) [] Try multi-equation cases:: sage: x, y, z = var("x y z") sage: solve_mod([2*x^2 + x*y, -x*y+2*y^2+x-2*y, -2*x^2+2*x*y-y^2-x-y], 12) [(0, 0), (4, 4), (0, 3), (4, 7)] sage: eqs = [-y^2+z^2, -x^2+y^2-3*z^2-z-1, -y*z-z^2-x-y+2, -x^2-12*z^2-y+z] sage: solve_mod(eqs, 11) [(8, 5, 6)] Confirm that modulus 1 now behaves as it should:: sage: x, y = var("x y") sage: solve_mod([x==1], 1) [(0,)] sage: solve_mod([2*x^2+x*y, -x*y+2*y^2+x-2*y, -2*x^2+2*x*y-y^2-x-y], 1) [(0, 0)] """ from sage.rings.all import Integer, Integers, crt_basis from sage.symbolic.expression import is_Expression from sage.misc.all import cartesian_product_iterator from sage.modules.all import vector from sage.matrix.all import matrix if not isinstance(eqns, (list, tuple)): eqns = [eqns] eqns = [eq if is_Expression(eq) else (eq.lhs() - eq.rhs()) for eq in eqns] modulus = Integer(modulus) if modulus < 1: raise ValueError("the modulus must be a positive integer") vars = list(set(sum([list(e.variables()) for e in eqns], []))) vars.sort(key=repr) if modulus == 1: # degenerate case ans = [tuple(Integers(1)(0) for v in vars)] return ans factors = modulus.factor() crt_basis = vector(Integers(modulus), crt_basis([p**i for p, i in factors])) solutions = [] has_solution = True for p, i in factors: solution = _solve_mod_prime_power(eqns, p, i, vars) if len(solution) > 0: solutions.append(solution) else: has_solution = False break ans = [] if has_solution: for solution in cartesian_product_iterator(solutions): solution_mat = matrix(Integers(modulus), solution) ans.append( tuple( c.dot_product(crt_basis) for c in solution_mat.columns())) # if solution_dict == True: # Relaxed form suggested by Mike Hansen (#8553): if solution_dict: sol_dict = [dict(zip(vars, solution)) for solution in ans] return sol_dict else: return ans
def _solve_mod_prime_power(eqns, p, m, vars): r""" Internal help function for solve_mod, does little checking since it expects solve_mod to do that Return all solutions to an equation or list of equations modulo p^m. Each equation must involve only polynomials in 1 or many variables. The solutions are returned as `n`-tuples, where `n` is the number of variables in vars. INPUT: - ``eqns`` - equation or list of equations - ``p`` - a prime - ``i`` - an integer > 0 - ``vars`` - a list of variables to solve for EXAMPLES:: sage: var('x,y') (x, y) sage: solve_mod([x^2 + 2 == x, x^2 + y == y^2], 14) [(4, 2), (4, 6), (4, 9), (4, 13)] sage: solve_mod([x^2 == 1, 4*x == 11], 15) [(14,)] Fermat's equation modulo 3 with exponent 5:: sage: var('x,y,z') (x, y, z) sage: solve_mod([x^5 + y^5 == z^5], 3) [(0, 0, 0), (0, 1, 1), (0, 2, 2), (1, 0, 1), (1, 1, 2), (1, 2, 0), (2, 0, 2), (2, 1, 0), (2, 2, 1)] We solve a simple equation modulo 2:: sage: x,y = var('x,y') sage: solve_mod([x == y], 2) [(0, 0), (1, 1)] .. warning:: Currently this constructs possible solutions by building up from the smallest prime factor of the modulus. The interface is good, but the algorithm is horrible if the modulus isn't the product of many small primes! Sage *does* have the ability to do something much faster in certain cases at least by using the Chinese Remainder Theorem, Groebner basis, linear algebra techniques, etc. But for a lot of toy problems this function as is might be useful. At the very least, it establishes an interface. TESTS: Confirm we can reproduce the first few terms of :oeis:`A187719`:: sage: from sage.symbolic.relation import _solve_mod_prime_power sage: [sorted(_solve_mod_prime_power([x^2==41], 10, i, [x]))[0][0] for i in [1..13]] [1, 21, 71, 1179, 2429, 47571, 1296179, 8703821, 26452429, 526452429, 13241296179, 19473547571, 2263241296179] """ from sage.rings.all import Integers, PolynomialRing from sage.modules.all import vector from sage.misc.all import cartesian_product_iterator mrunning = 1 ans = [] for mi in range(m): mrunning *= p R = Integers(mrunning) S = PolynomialRing(R, len(vars), vars) eqns_mod = [S(eq) for eq in eqns] if mi == 0: possibles = cartesian_product_iterator( [range(len(R)) for _ in range(len(vars))]) else: shifts = cartesian_product_iterator( [range(p) for _ in range(len(vars))]) pairs = cartesian_product_iterator([shifts, ans]) possibles = (tuple(vector(t) + vector(shift) * (mrunning // p)) for shift, t in pairs) ans = list(t for t in possibles if all(e(*t) == 0 for e in eqns_mod)) if not ans: return ans return ans
def solve_mod(eqns, modulus, solution_dict = False): r""" Return all solutions to an equation or list of equations modulo the given integer modulus. Each equation must involve only polynomials in 1 or many variables. By default the solutions are returned as `n`-tuples, where `n` is the number of variables appearing anywhere in the given equations. The variables are in alphabetical order. INPUT: - ``eqns`` - equation or list of equations - ``modulus`` - an integer - ``solution_dict`` - bool (default: False); if True or non-zero, return a list of dictionaries containing the solutions. If there are no solutions, return an empty list (rather than a list containing an empty dictionary). Likewise, if there's only a single solution, return a list containing one dictionary with that solution. EXAMPLES:: sage: var('x,y') (x, y) sage: solve_mod([x^2 + 2 == x, x^2 + y == y^2], 14) [(4, 2), (4, 6), (4, 9), (4, 13)] sage: solve_mod([x^2 == 1, 4*x == 11], 15) [(14,)] Fermat's equation modulo 3 with exponent 5:: sage: var('x,y,z') (x, y, z) sage: solve_mod([x^5 + y^5 == z^5], 3) [(0, 0, 0), (0, 1, 1), (0, 2, 2), (1, 0, 1), (1, 1, 2), (1, 2, 0), (2, 0, 2), (2, 1, 0), (2, 2, 1)] We can solve with respect to a bigger modulus if it consists only of small prime factors:: sage: [d] = solve_mod([5*x + y == 3, 2*x - 3*y == 9], 3*5*7*11*19*23*29, solution_dict = True) sage: d[x] 12915279 sage: d[y] 8610183 For cases where there are relatively few solutions and the prime factors are small, this can be efficient even if the modulus itself is large:: sage: sorted(solve_mod([x^2 == 41], 10^20)) [(4538602480526452429,), (11445932736758703821,), (38554067263241296179,), (45461397519473547571,), (54538602480526452429,), (61445932736758703821,), (88554067263241296179,), (95461397519473547571,)] We solve a simple equation modulo 2:: sage: x,y = var('x,y') sage: solve_mod([x == y], 2) [(0, 0), (1, 1)] .. warning:: The current implementation splits the modulus into prime powers, then naively enumerates all possible solutions (starting modulo primes and then working up through prime powers), and finally combines the solution using the Chinese Remainder Theorem. The interface is good, but the algorithm is very inefficient if the modulus has some larger prime factors! Sage *does* have the ability to do something much faster in certain cases at least by using Groebner basis, linear algebra techniques, etc. But for a lot of toy problems this function as is might be useful. At least it establishes an interface. TESTS: Make sure that we short-circuit in at least some cases:: sage: solve_mod([2*x==1], 2*next_prime(10^50)) [] Try multi-equation cases:: sage: x, y, z = var("x y z") sage: solve_mod([2*x^2 + x*y, -x*y+2*y^2+x-2*y, -2*x^2+2*x*y-y^2-x-y], 12) [(0, 0), (4, 4), (0, 3), (4, 7)] sage: eqs = [-y^2+z^2, -x^2+y^2-3*z^2-z-1, -y*z-z^2-x-y+2, -x^2-12*z^2-y+z] sage: solve_mod(eqs, 11) [(8, 5, 6)] Confirm that modulus 1 now behaves as it should:: sage: x, y = var("x y") sage: solve_mod([x==1], 1) [(0,)] sage: solve_mod([2*x^2+x*y, -x*y+2*y^2+x-2*y, -2*x^2+2*x*y-y^2-x-y], 1) [(0, 0)] """ from sage.rings.all import Integer, Integers, crt_basis from sage.symbolic.expression import is_Expression from sage.misc.all import cartesian_product_iterator from sage.modules.all import vector from sage.matrix.all import matrix if not isinstance(eqns, (list, tuple)): eqns = [eqns] eqns = [eq if is_Expression(eq) else (eq.lhs()-eq.rhs()) for eq in eqns] modulus = Integer(modulus) if modulus < 1: raise ValueError("the modulus must be a positive integer") vars = list(set(sum([list(e.variables()) for e in eqns], []))) vars.sort(key=repr) if modulus == 1: # degenerate case ans = [tuple(Integers(1)(0) for v in vars)] return ans factors = modulus.factor() crt_basis = vector(Integers(modulus), crt_basis([p**i for p,i in factors])) solutions = [] has_solution = True for p,i in factors: solution =_solve_mod_prime_power(eqns, p, i, vars) if len(solution) > 0: solutions.append(solution) else: has_solution = False break ans = [] if has_solution: for solution in cartesian_product_iterator(solutions): solution_mat = matrix(Integers(modulus), solution) ans.append(tuple(c.dot_product(crt_basis) for c in solution_mat.columns())) # if solution_dict == True: # Relaxed form suggested by Mike Hansen (#8553): if solution_dict: sol_dict = [dict(zip(vars, solution)) for solution in ans] return sol_dict else: return ans
def _solve_mod_prime_power(eqns, p, m, vars): r""" Internal help function for solve_mod, does little checking since it expects solve_mod to do that Return all solutions to an equation or list of equations modulo p^m. Each equation must involve only polynomials in 1 or many variables. The solutions are returned as `n`-tuples, where `n` is the number of variables in vars. INPUT: - ``eqns`` - equation or list of equations - ``p`` - a prime - ``i`` - an integer > 0 - ``vars`` - a list of variables to solve for EXAMPLES:: sage: var('x,y') (x, y) sage: solve_mod([x^2 + 2 == x, x^2 + y == y^2], 14) [(4, 2), (4, 6), (4, 9), (4, 13)] sage: solve_mod([x^2 == 1, 4*x == 11], 15) [(14,)] Fermat's equation modulo 3 with exponent 5:: sage: var('x,y,z') (x, y, z) sage: solve_mod([x^5 + y^5 == z^5], 3) [(0, 0, 0), (0, 1, 1), (0, 2, 2), (1, 0, 1), (1, 1, 2), (1, 2, 0), (2, 0, 2), (2, 1, 0), (2, 2, 1)] We solve a simple equation modulo 2:: sage: x,y = var('x,y') sage: solve_mod([x == y], 2) [(0, 0), (1, 1)] .. warning:: Currently this constructs possible solutions by building up from the smallest prime factor of the modulus. The interface is good, but the algorithm is horrible if the modulus isn't the product of many small primes! Sage *does* have the ability to do something much faster in certain cases at least by using the Chinese Remainder Theorem, Groebner basis, linear algebra techniques, etc. But for a lot of toy problems this function as is might be useful. At the very least, it establishes an interface. TESTS: Confirm we can reproduce the first few terms of :oeis:`A187719`:: sage: from sage.symbolic.relation import _solve_mod_prime_power sage: [sorted(_solve_mod_prime_power([x^2==41], 10, i, [x]))[0][0] for i in [1..13]] [1, 21, 71, 1179, 2429, 47571, 1296179, 8703821, 26452429, 526452429, 13241296179, 19473547571, 2263241296179] """ from sage.rings.all import Integers, PolynomialRing from sage.modules.all import vector from sage.misc.all import cartesian_product_iterator mrunning = 1 ans = [] for mi in range(m): mrunning *= p R = Integers(mrunning) S = PolynomialRing(R, len(vars), vars) eqns_mod = [S(eq) for eq in eqns] if mi == 0: possibles = cartesian_product_iterator([range(len(R)) for _ in range(len(vars))]) else: shifts = cartesian_product_iterator([range(p) for _ in range(len(vars))]) pairs = cartesian_product_iterator([shifts, ans]) possibles = (tuple(vector(t)+vector(shift)*(mrunning//p)) for shift, t in pairs) ans = list(t for t in possibles if all(e(*t) == 0 for e in eqns_mod)) if not ans: return ans return ans
def enum_projective_rational_field(X, B): r""" Enumerates projective, rational points on scheme ``X`` of height up to bound ``B``. INPUT: - ``X`` - a scheme or set of abstract rational points of a scheme. - ``B`` - a positive integer bound. OUTPUT: - a list containing the projective points of ``X`` of height up to ``B``, sorted. EXAMPLES:: sage: P.<X,Y,Z> = ProjectiveSpace(2, QQ) sage: C = P.subscheme([X+Y-Z]) sage: from sage.schemes.projective.projective_rational_point import enum_projective_rational_field sage: enum_projective_rational_field(C(QQ), 6) [(-5 : 6 : 1), (-4 : 5 : 1), (-3 : 4 : 1), (-2 : 3 : 1), (-3/2 : 5/2 : 1), (-1 : 1 : 0), (-1 : 2 : 1), (-2/3 : 5/3 : 1), (-1/2 : 3/2 : 1), (-1/3 : 4/3 : 1), (-1/4 : 5/4 : 1), (-1/5 : 6/5 : 1), (0 : 1 : 1), (1/6 : 5/6 : 1), (1/5 : 4/5 : 1), (1/4 : 3/4 : 1), (1/3 : 2/3 : 1), (2/5 : 3/5 : 1), (1/2 : 1/2 : 1), (3/5 : 2/5 : 1), (2/3 : 1/3 : 1), (3/4 : 1/4 : 1), (4/5 : 1/5 : 1), (5/6 : 1/6 : 1), (1 : 0 : 1), (6/5 : -1/5 : 1), (5/4 : -1/4 : 1), (4/3 : -1/3 : 1), (3/2 : -1/2 : 1), (5/3 : -2/3 : 1), (2 : -1 : 1), (5/2 : -3/2 : 1), (3 : -2 : 1), (4 : -3 : 1), (5 : -4 : 1), (6 : -5 : 1)] sage: enum_projective_rational_field(C,6) == enum_projective_rational_field(C(QQ),6) True :: sage: P3.<W,X,Y,Z> = ProjectiveSpace(3, QQ) sage: enum_projective_rational_field(P3, 1) [(-1 : -1 : -1 : 1), (-1 : -1 : 0 : 1), (-1 : -1 : 1 : 0), (-1 : -1 : 1 : 1), (-1 : 0 : -1 : 1), (-1 : 0 : 0 : 1), (-1 : 0 : 1 : 0), (-1 : 0 : 1 : 1), (-1 : 1 : -1 : 1), (-1 : 1 : 0 : 0), (-1 : 1 : 0 : 1), (-1 : 1 : 1 : 0), (-1 : 1 : 1 : 1), (0 : -1 : -1 : 1), (0 : -1 : 0 : 1), (0 : -1 : 1 : 0), (0 : -1 : 1 : 1), (0 : 0 : -1 : 1), (0 : 0 : 0 : 1), (0 : 0 : 1 : 0), (0 : 0 : 1 : 1), (0 : 1 : -1 : 1), (0 : 1 : 0 : 0), (0 : 1 : 0 : 1), (0 : 1 : 1 : 0), (0 : 1 : 1 : 1), (1 : -1 : -1 : 1), (1 : -1 : 0 : 1), (1 : -1 : 1 : 0), (1 : -1 : 1 : 1), (1 : 0 : -1 : 1), (1 : 0 : 0 : 0), (1 : 0 : 0 : 1), (1 : 0 : 1 : 0), (1 : 0 : 1 : 1), (1 : 1 : -1 : 1), (1 : 1 : 0 : 0), (1 : 1 : 0 : 1), (1 : 1 : 1 : 0), (1 : 1 : 1 : 1)] ALGORITHM: We just check all possible projective points in correct dimension of projective space to see if they lie on ``X``. AUTHORS: - John Cremona and Charlie Turner (06-2010) """ from sage.schemes.projective.projective_space import is_ProjectiveSpace if (is_Scheme(X)): if (not is_ProjectiveSpace(X.ambient_space())): raise TypeError( "ambient space must be projective space over the rational field" ) X = X(X.base_ring()) else: if (not is_ProjectiveSpace(X.codomain().ambient_space())): raise TypeError( "codomain must be projective space over the rational field") n = X.codomain().ambient_space().ngens() zero = (0, ) * n pts = [] for c in cartesian_product_iterator([srange(-B, B + 1) for _ in range(n)]): if gcd(c) == 1 and c > zero: try: pts.append(X(c)) except TypeError: pass pts.sort() return pts
def enum_projective_finite_field(X): """ Enumerates projective points on scheme ``X`` defined over a finite field. INPUT: - ``X`` - a scheme defined over a finite field or a set of abstract rational points of such a scheme. OUTPUT: - a list containing the projective points of ``X`` over the finite field, sorted. EXAMPLES:: sage: F = GF(53) sage: P.<X,Y,Z> = ProjectiveSpace(2,F) sage: from sage.schemes.projective.projective_rational_point import enum_projective_finite_field sage: len(enum_projective_finite_field(P(F))) 2863 sage: 53^2+53+1 2863 :: sage: F = GF(9,'a') sage: P.<X,Y,Z> = ProjectiveSpace(2,F) sage: C = Curve(X^3-Y^3+Z^2*Y) sage: enum_projective_finite_field(C(F)) [(0 : 0 : 1), (0 : 1 : 1), (0 : 2 : 1), (1 : 1 : 0), (a + 1 : 2*a : 1), (a + 1 : 2*a + 1 : 1), (a + 1 : 2*a + 2 : 1), (2*a + 2 : a : 1), (2*a + 2 : a + 1 : 1), (2*a + 2 : a + 2 : 1)] :: sage: F = GF(5) sage: P2F.<X,Y,Z> = ProjectiveSpace(2,F) sage: enum_projective_finite_field(P2F) [(0 : 0 : 1), (0 : 1 : 0), (0 : 1 : 1), (0 : 2 : 1), (0 : 3 : 1), (0 : 4 : 1), (1 : 0 : 0), (1 : 0 : 1), (1 : 1 : 0), (1 : 1 : 1), (1 : 2 : 1), (1 : 3 : 1), (1 : 4 : 1), (2 : 0 : 1), (2 : 1 : 0), (2 : 1 : 1), (2 : 2 : 1), (2 : 3 : 1), (2 : 4 : 1), (3 : 0 : 1), (3 : 1 : 0), (3 : 1 : 1), (3 : 2 : 1), (3 : 3 : 1), (3 : 4 : 1), (4 : 0 : 1), (4 : 1 : 0), (4 : 1 : 1), (4 : 2 : 1), (4 : 3 : 1), (4 : 4 : 1)] ALGORITHM: Checks all points in projective space to see if they lie on ``X``. .. WARNING:: If ``X`` is defined over an infinite field, this code will not finish! AUTHORS: - John Cremona and Charlie Turner (06-2010). """ from sage.schemes.projective.projective_space import is_ProjectiveSpace if (is_Scheme(X)): if (not is_ProjectiveSpace(X.ambient_space())): raise TypeError( "ambient space must be projective space over a finite") X = X(X.base_ring()) else: if (not is_ProjectiveSpace(X.codomain().ambient_space())): raise TypeError( "codomain must be projective space over a finite field") n = X.codomain().ambient_space().ngens() - 1 F = X.value_ring() pts = [] for k in range(n + 1): for c in cartesian_product_iterator([F for _ in range(k)]): try: pts.append(X(list(c) + [1] + [0] * (n - k))) except TypeError: pass pts.sort() return pts
def enum_projective_rational_field(X,B): r""" Enumerates projective, rational points on scheme ``X`` of height up to bound ``B``. INPUT: - ``X`` - a scheme or set of abstract rational points of a scheme; - ``B`` - a positive integer bound. OUTPUT: - a list containing the projective points of ``X`` of height up to ``B``, sorted. EXAMPLES:: sage: P.<X,Y,Z> = ProjectiveSpace(2,QQ) sage: C = P.subscheme([X+Y-Z]) sage: from sage.schemes.projective.projective_rational_point import enum_projective_rational_field sage: enum_projective_rational_field(C(QQ),6) [(-5 : 6 : 1), (-4 : 5 : 1), (-3 : 4 : 1), (-2 : 3 : 1), (-3/2 : 5/2 : 1), (-1 : 1 : 0), (-1 : 2 : 1), (-2/3 : 5/3 : 1), (-1/2 : 3/2 : 1), (-1/3 : 4/3 : 1), (-1/4 : 5/4 : 1), (-1/5 : 6/5 : 1), (0 : 1 : 1), (1/6 : 5/6 : 1), (1/5 : 4/5 : 1), (1/4 : 3/4 : 1), (1/3 : 2/3 : 1), (2/5 : 3/5 : 1), (1/2 : 1/2 : 1), (3/5 : 2/5 : 1), (2/3 : 1/3 : 1), (3/4 : 1/4 : 1), (4/5 : 1/5 : 1), (5/6 : 1/6 : 1), (1 : 0 : 1), (6/5 : -1/5 : 1), (5/4 : -1/4 : 1), (4/3 : -1/3 : 1), (3/2 : -1/2 : 1), (5/3 : -2/3 : 1), (2 : -1 : 1), (5/2 : -3/2 : 1), (3 : -2 : 1), (4 : -3 : 1), (5 : -4 : 1), (6 : -5 : 1)] sage: enum_projective_rational_field(C,6) == enum_projective_rational_field(C(QQ),6) True :: sage: P3.<W,X,Y,Z> = ProjectiveSpace(3,QQ) sage: enum_projective_rational_field(P3,1) [(-1 : -1 : -1 : 1), (-1 : -1 : 0 : 1), (-1 : -1 : 1 : 0), (-1 : -1 : 1 : 1), (-1 : 0 : -1 : 1), (-1 : 0 : 0 : 1), (-1 : 0 : 1 : 0), (-1 : 0 : 1 : 1), (-1 : 1 : -1 : 1), (-1 : 1 : 0 : 0), (-1 : 1 : 0 : 1), (-1 : 1 : 1 : 0), (-1 : 1 : 1 : 1), (0 : -1 : -1 : 1), (0 : -1 : 0 : 1), (0 : -1 : 1 : 0), (0 : -1 : 1 : 1), (0 : 0 : -1 : 1), (0 : 0 : 0 : 1), (0 : 0 : 1 : 0), (0 : 0 : 1 : 1), (0 : 1 : -1 : 1), (0 : 1 : 0 : 0), (0 : 1 : 0 : 1), (0 : 1 : 1 : 0), (0 : 1 : 1 : 1), (1 : -1 : -1 : 1), (1 : -1 : 0 : 1), (1 : -1 : 1 : 0), (1 : -1 : 1 : 1), (1 : 0 : -1 : 1), (1 : 0 : 0 : 0), (1 : 0 : 0 : 1), (1 : 0 : 1 : 0), (1 : 0 : 1 : 1), (1 : 1 : -1 : 1), (1 : 1 : 0 : 0), (1 : 1 : 0 : 1), (1 : 1 : 1 : 0), (1 : 1 : 1 : 1)] ALGORITHM: We just check all possible projective points in correct dimension of projective space to see if they lie on ``X``. AUTHORS: - John Cremona and Charlie Turner (06-2010) """ from sage.schemes.projective.projective_space import is_ProjectiveSpace if(is_Scheme(X)): if (not is_ProjectiveSpace(X.ambient_space())): raise TypeError("Ambient space must be projective space over the rational field") X = X(X.base_ring()) else: if (not is_ProjectiveSpace(X.codomain().ambient_space())): raise TypeError("Codomain must be projective space over the rational field") n = X.codomain().ambient_space().ngens() zero = (0,) * n pts = [] for c in cartesian_product_iterator([srange(-B,B+1) for _ in range(n)]): if gcd(c) == 1 and c > zero: try: pts.append(X(c)) except TypeError: pass pts.sort() return pts
def enum_projective_finite_field(X): """ Enumerates projective points on scheme ``X`` defined over a finite field. INPUT: - ``X`` - a scheme defined over a finite field or a set of abstract rational points of such a scheme. OUTPUT: - a list containing the projective points of ``X`` over the finite field, sorted. EXAMPLES:: sage: F = GF(53) sage: P.<X,Y,Z> = ProjectiveSpace(2,F) sage: from sage.schemes.projective.projective_rational_point import enum_projective_finite_field sage: len(enum_projective_finite_field(P(F))) 2863 sage: 53^2+53+1 2863 :: sage: F = GF(9,'a') sage: P.<X,Y,Z> = ProjectiveSpace(2,F) sage: C = Curve(X^3-Y^3+Z^2*Y) sage: enum_projective_finite_field(C(F)) [(0 : 0 : 1), (0 : 1 : 1), (0 : 2 : 1), (1 : 1 : 0), (a + 1 : 2*a : 1), (a + 1 : 2*a + 1 : 1), (a + 1 : 2*a + 2 : 1), (2*a + 2 : a : 1), (2*a + 2 : a + 1 : 1), (2*a + 2 : a + 2 : 1)] :: sage: F = GF(5) sage: P2F.<X,Y,Z> = ProjectiveSpace(2,F) sage: enum_projective_finite_field(P2F) [(0 : 0 : 1), (0 : 1 : 0), (0 : 1 : 1), (0 : 2 : 1), (0 : 3 : 1), (0 : 4 : 1), (1 : 0 : 0), (1 : 0 : 1), (1 : 1 : 0), (1 : 1 : 1), (1 : 2 : 1), (1 : 3 : 1), (1 : 4 : 1), (2 : 0 : 1), (2 : 1 : 0), (2 : 1 : 1), (2 : 2 : 1), (2 : 3 : 1), (2 : 4 : 1), (3 : 0 : 1), (3 : 1 : 0), (3 : 1 : 1), (3 : 2 : 1), (3 : 3 : 1), (3 : 4 : 1), (4 : 0 : 1), (4 : 1 : 0), (4 : 1 : 1), (4 : 2 : 1), (4 : 3 : 1), (4 : 4 : 1)] ALGORITHM: Checks all points in projective space to see if they lie on X. .. WARNING:: If ``X`` is defined over an infinite field, this code will not finish! AUTHORS: - John Cremona and Charlie Turner (06-2010). """ from sage.schemes.projective.projective_space import is_ProjectiveSpace if(is_Scheme(X)): if (not is_ProjectiveSpace(X.ambient_space())): raise TypeError("Ambient space must be projective space over a finite") X = X(X.base_ring()) else: if (not is_ProjectiveSpace(X.codomain().ambient_space())): raise TypeError("Codomain must be projective space over a finite field") n = X.codomain().ambient_space().ngens()-1 F = X.value_ring() pts = [] for k in range(n+1): for c in cartesian_product_iterator([F for _ in range(k)]): try: pts.append(X(list(c)+[1]+[0]*(n-k))) except TypeError: pass pts.sort() return pts
def enum_affine_finite_field(X): r""" Enumerates affine points on scheme ``X`` defined over a finite field. INPUT: - ``X`` - a scheme defined over a finite field or a set of abstract rational points of such a scheme. OUTPUT: - a list containing the affine points of ``X`` over the finite field, sorted. EXAMPLES:: sage: F = GF(7) sage: A.<w,x,y,z> = AffineSpace(4, F) sage: C = A.subscheme([w^2+x+4, y*z*x-6, z*y+w*x]) sage: from sage.schemes.affine.affine_rational_point import enum_affine_finite_field sage: enum_affine_finite_field(C(F)) [] sage: C = A.subscheme([w^2+x+4, y*z*x-6]) sage: enum_affine_finite_field(C(F)) [(0, 3, 1, 2), (0, 3, 2, 1), (0, 3, 3, 3), (0, 3, 4, 4), (0, 3, 5, 6), (0, 3, 6, 5), (1, 2, 1, 3), (1, 2, 2, 5), (1, 2, 3, 1), (1, 2, 4, 6), (1, 2, 5, 2), (1, 2, 6, 4), (2, 6, 1, 1), (2, 6, 2, 4), (2, 6, 3, 5), (2, 6, 4, 2), (2, 6, 5, 3), (2, 6, 6, 6), (3, 1, 1, 6), (3, 1, 2, 3), (3, 1, 3, 2), (3, 1, 4, 5), (3, 1, 5, 4), (3, 1, 6, 1), (4, 1, 1, 6), (4, 1, 2, 3), (4, 1, 3, 2), (4, 1, 4, 5), (4, 1, 5, 4), (4, 1, 6, 1), (5, 6, 1, 1), (5, 6, 2, 4), (5, 6, 3, 5), (5, 6, 4, 2), (5, 6, 5, 3), (5, 6, 6, 6), (6, 2, 1, 3), (6, 2, 2, 5), (6, 2, 3, 1), (6, 2, 4, 6), (6, 2, 5, 2), (6, 2, 6, 4)] :: sage: A.<x,y,z> = AffineSpace(3, GF(3)) sage: S = A.subscheme(x+y) sage: enum_affine_finite_field(S) [(0, 0, 0), (0, 0, 1), (0, 0, 2), (1, 2, 0), (1, 2, 1), (1, 2, 2), (2, 1, 0), (2, 1, 1), (2, 1, 2)] ALGORITHM: Checks all points in affine space to see if they lie on X. .. WARNING:: If ``X`` is defined over an infinite field, this code will not finish! AUTHORS: - John Cremona and Charlie Turner (06-2010) """ from sage.schemes.affine.affine_space import is_AffineSpace if is_Scheme(X): if not is_AffineSpace(X.ambient_space()): raise TypeError( "ambient space must be affine space over a finite field") X = X(X.base_ring()) elif not is_AffineSpace(X.codomain().ambient_space()): raise TypeError("codomain must be affine space over a finite field") n = X.codomain().ambient_space().ngens() F = X.value_ring() pts = [] for c in cartesian_product_iterator([F] * n): try: pts.append(X(c)) except Exception: pass pts.sort() return pts
def enum_affine_finite_field(X): r""" Enumerates affine points on scheme ``X`` defined over a finite field. INPUT: - ``X`` - a scheme defined over a finite field or a set of abstract rational points of such a scheme. OUTPUT: - a list containing the affine points of ``X`` over the finite field, sorted. EXAMPLES:: sage: F = GF(7) sage: A.<w,x,y,z> = AffineSpace(4,F) sage: C = A.subscheme([w^2+x+4,y*z*x-6,z*y+w*x]) sage: from sage.schemes.affine.affine_rational_point import enum_affine_finite_field sage: enum_affine_finite_field(C(F)) [] sage: C = A.subscheme([w^2+x+4,y*z*x-6]) sage: enum_affine_finite_field(C(F)) [(0, 3, 1, 2), (0, 3, 2, 1), (0, 3, 3, 3), (0, 3, 4, 4), (0, 3, 5, 6), (0, 3, 6, 5), (1, 2, 1, 3), (1, 2, 2, 5), (1, 2, 3, 1), (1, 2, 4, 6), (1, 2, 5, 2), (1, 2, 6, 4), (2, 6, 1, 1), (2, 6, 2, 4), (2, 6, 3, 5), (2, 6, 4, 2), (2, 6, 5, 3), (2, 6, 6, 6), (3, 1, 1, 6), (3, 1, 2, 3), (3, 1, 3, 2), (3, 1, 4, 5), (3, 1, 5, 4), (3, 1, 6, 1), (4, 1, 1, 6), (4, 1, 2, 3), (4, 1, 3, 2), (4, 1, 4, 5), (4, 1, 5, 4), (4, 1, 6, 1), (5, 6, 1, 1), (5, 6, 2, 4), (5, 6, 3, 5), (5, 6, 4, 2), (5, 6, 5, 3), (5, 6, 6, 6), (6, 2, 1, 3), (6, 2, 2, 5), (6, 2, 3, 1), (6, 2, 4, 6), (6, 2, 5, 2), (6, 2, 6, 4)] :: sage: A.<x,y,z> = AffineSpace(3,GF(3)) sage: S = A.subscheme(x+y) sage: enum_affine_finite_field(S) [(0, 0, 0), (0, 0, 1), (0, 0, 2), (1, 2, 0), (1, 2, 1), (1, 2, 2), (2, 1, 0), (2, 1, 1), (2, 1, 2)] ALGORITHM: Checks all points in affine space to see if they lie on X. .. WARNING:: If ``X`` is defined over an infinite field, this code will not finish! AUTHORS: - John Cremona and Charlie Turner (06-2010) """ if is_Scheme(X): X = X(X.base_ring()) n = X.codomain().ambient_space().ngens() F = X.value_ring() pts = [] for c in cartesian_product_iterator([F]*n): try: pts.append(X(c)) except Exception: pass pts.sort() return pts