From 8a0c020329824d932d1f3bb846455fad5547d1eb Mon Sep 17 00:00:00 2001 From: Ben Hutz Date: Tue, 10 Nov 2015 16:03:57 -0600 Subject: [PATCH] 19552: rearranged code placement, added checks --- src/sage/schemes/generic/algebraic_scheme.py | 151 ++++++++++++++++++ .../schemes/projective/projective_morphism.py | 28 +--- .../projective/projective_morphism_helper.pyx | 78 --------- 3 files changed, 156 insertions(+), 101 deletions(-) diff --git a/src/sage/schemes/generic/algebraic_scheme.py b/src/sage/schemes/generic/algebraic_scheme.py index 232ba97ebd3..869089bd46e 100644 --- a/src/sage/schemes/generic/algebraic_scheme.py +++ b/src/sage/schemes/generic/algebraic_scheme.py @@ -138,6 +138,7 @@ from sage.rings.ideal import is_Ideal from sage.rings.rational_field import is_RationalField from sage.rings.polynomial.multi_polynomial_ring import is_MPolynomialRing +from sage.rings.polynomial.polynomial_ring_constructor import PolynomialRing from sage.rings.finite_rings.constructor import is_FiniteField from sage.misc.cachefunc import cached_method @@ -2315,6 +2316,156 @@ def nth_iterate(self, f, n , **kwds): Q = f(Q) return(Q) + def forward_image(self, f): + """ + Compute the forward image of the subscheme ``self`` by the map ``f``. + + The forward image is computed through elimination. + In particular, let $X = V(h_1,\ldots, h_t)$ and define the ideal + $I = (h_1,\ldots,h_t,y_0-f_0(\bar{x}), \ldots, y_n-f_n(\bar{x}))$. + Then the elimination ideal $I_{n+1} = I \cap K[y_0,\ldots,y_n]$ is a homogeneous + ideal and $self(X) = V(I_{n+1})$. + + INPUT: + + - ``f`` -- a map whose domain contains ``self`` + + OUTPUT: + + - a subscheme in the codomain of ``f``. + + EXAMPLES:: + + sage: PS. = ProjectiveSpace(QQ, 2) + sage: H = End(PS) + sage: f = H([x^2, y^2-2*z^2, z^2]) + sage: X = PS.subscheme(y-2*z) + sage: f(X) + Closed subscheme of Projective Space of dimension 2 over Rational Field + defined by: + y - 2*z + + :: + + sage: set_verbose(None) + sage: PS. = ProjectiveSpace(ZZ, 3) + sage: H = End(PS) + sage: f = H([y^2, x^2, w^2, z^2]) + sage: X = PS.subscheme([z^2+y*w, x-w]) + sage: f(X) + Closed subscheme of Projective Space of dimension 3 over Integer Ring + defined by: + y - z, + x*z - w^2 + + :: + + sage: PS. = ProjectiveSpace(CC, 3) + sage: H = End(PS) + sage: f = H([x^2 + y^2, y^2, z^2-y^2, w^2]) + sage: X = PS.subscheme([z-2*w]) + sage: f(X) + Closed subscheme of Projective Space of dimension 3 over Complex Field + with 53 bits of precision defined by: + y + z + (-4.00000000000000)*w + + :: + + sage: R. = PolynomialRing(QQ) + sage: P. = ProjectiveSpace(FractionField(R), 2) + sage: H = End(P) + sage: f = H([x^2 + 2*y*z, t^2*y^2, z^2]) + sage: f([t^2*y-z]) + Closed subscheme of Projective Space of dimension 2 over Fraction Field + of Univariate Polynomial Ring in t over Rational Field defined by: + y + (-1/t^2)*z + + :: + + sage: set_verbose(-1) + sage: PS. = ProjectiveSpace(Qp(3), 2) + sage: H = End(PS) + sage: f = H([x^2,2*y^2,z^2]) + sage: X = PS.subscheme([2*x-y,z]) + sage: f(X) + Closed subscheme of Projective Space of dimension 2 over 3-adic Field + with capped relative precision 20 defined by: + z, + x + (1 + 3^2 + 3^4 + 3^6 + 3^8 + 3^10 + 3^12 + 3^14 + 3^16 + 3^18 + + O(3^20))*y + """ + dom = f.domain() + codom = f.codomain() + if self.ambient_space() != dom: + raise TypeError("Subscheme must be in ambient space of domain of map.") + CR_dom = dom.coordinate_ring() + CR_codom = codom.coordinate_ring() + n = CR_dom.ngens() + m = CR_codom.ngens() + #can't call eliminate if the base ring is polynomial so we do it ourselves + #with a lex ordering + R = PolynomialRing(f.base_ring(), n+m, 'y', order = 'lex') + Rvars = R.gens()[0 : n] + phi = CR_dom.hom(Rvars,R) + zero = [0 for _ in range(n)] + psi = R.hom(zero + list(CR_codom.gens()),CR_codom) + #set up ideal + L = R.ideal([phi(t) for t in self.defining_polynomials()] + [R.gen(n+i) - phi(f[i]) for i in range(m)]) + G = L.groebner_basis() #eliminate + newL = [] + #get only the elimination ideal portion + for i in range (len(G)-1,0,-1): + v = G[i].variables() + if all([Rvars[j] not in v for j in range(n)]): + newL.append(psi(G[i])) + return(codom.subscheme(newL)) + + def preimage(self, f): + r""" + Given a subscheme ``self``, return the subscheme that maps to ``self`` by ``f``. + In particular, `f^{-1}(V(h_1,\ldots,h_t)) = V(h_1 \circ f, \ldots, h_t \circ f)`. + + INPUT: + + - ``f`` - a map whose codomain contains ``self`` + + OUTPUT: + + - a subscheme in the domain of ``f``. + + Examples:: + + sage: PS. = ProjectiveSpace(ZZ, 2) + sage: H = End(PS) + sage: f = H([y^2, x^2, z^2]) + sage: X = PS.subscheme([x-y]) + sage: X.preimage(f) + Closed subscheme of Projective Space of dimension 2 over Integer Ring + defined by: + -x^2 + y^2 + + :: + + sage: P. = ProjectiveSpace(QQ, 4) + sage: H = End(P) + sage: f = H([x^2-y^2, z*y, z^2, w^2, t^2+w^2]) + sage: f.rational_preimages(P.subscheme([x-z, t^2, w-t])) + Closed subscheme of Projective Space of dimension 4 over Rational Field + defined by: + x^2 - y^2 - z^2, + w^4 + 2*w^2*t^2 + t^4, + -t^2 + """ + dom = f.domain() + codom = f.codomain() + if self.ambient_space() != codom: + raise TypeError("Subscheme must be in ambient space of codomain.") + R = codom.coordinate_ring() + dict = {} + for i in range(codom.dimension_relative()+1): + dict.update({R.gen(i): f[i]}) + return(dom.subscheme([t.subs(dict) for t in self.defining_polynomials()])) + class AlgebraicScheme_subscheme_product_projective(AlgebraicScheme_subscheme_projective): @cached_method diff --git a/src/sage/schemes/projective/projective_morphism.py b/src/sage/schemes/projective/projective_morphism.py index 376e63feaff..eac3fbfe60c 100644 --- a/src/sage/schemes/projective/projective_morphism.py +++ b/src/sage/schemes/projective/projective_morphism.py @@ -77,7 +77,7 @@ from sage.parallel.use_fork import p_iter_fork from sage.ext.fast_callable import fast_callable from sage.misc.lazy_attribute import lazy_attribute -from sage.schemes.projective.projective_morphism_helper import _fast_possible_periods, _forward_image_subscheme +from sage.schemes.projective.projective_morphism_helper import _fast_possible_periods import sys from sage.categories.number_fields import NumberFields _NumberFields = NumberFields() @@ -209,7 +209,7 @@ def __init__(self, parent, polys, check=True): def __call__(self, x, check=True): """ Compute the forward image of the point or subscheme ``x`` by the map ``self``. - For subschemes, the forward image is compute through elimination. + For subschemes, the forward image is computed through elimination. In particular, let $X = V(h_1,\ldots, h_t)$ and define the ideal $I = (h_1,\ldots,h_t,y_0-f_0(\bar{x}), \ldots, y_n-f_n(\bar{x}))$. Then the elimination ideal $I_{n+1} = I \cap K[y_0,\ldots,y_n]$ is a homogeneous @@ -260,14 +260,14 @@ def __call__(self, x, check=True): x = self.domain().subscheme(x.defining_polynomials()) except (TypeError, NotImplementedError): raise TypeError("%s fails to convert into the map's domain %s, but a `pushforward` method is not properly implemented"%(x, self.domain())) - return _forward_image_subscheme(self,x) #call subscheme eval + return x.forward_image(self) #call subscheme eval else: #not a projective point or subscheme try: x = self.domain()(x) except (TypeError, NotImplementedError): try: x = self.domain().subscheme(x) - return _forward_image_subscheme(self,x) #call subscheme eval + return x.forward_image(self) #call subscheme eval except (TypeError, NotImplementedError): raise TypeError("%s fails to convert into the map's domain %s, but a `pushforward` method is not properly implemented"%(x, self.domain())) @@ -3570,29 +3570,11 @@ def rational_preimages(self, Q): Closed subscheme of Projective Space of dimension 1 over Rational Field defined by: x^2 - y^2 - - :: - - sage: P. = ProjectiveSpace(QQ, 4) - sage: H = End(P) - sage: f = H([x^2-y^2, z*y, z^2, w^2, t^2+w^2]) - sage: f.rational_preimages(P.subscheme([x-z, t^2, w-t])) - Closed subscheme of Projective Space of dimension 4 over Rational Field - defined by: - x^2 - y^2 - z^2, - w^4 + 2*w^2*t^2 + t^4, - -t^2 """ #first check if subscheme from sage.schemes.generic.algebraic_scheme import AlgebraicScheme_subscheme_projective if isinstance(Q, AlgebraicScheme_subscheme_projective): - dom = self.domain() - codom = self.codomain() - R = codom.coordinate_ring() - dict = {} - for i in range(codom.dimension_relative()+1): - dict.update({R.gen(i): self[i]}) - return(dom.subscheme([t.subs(dict) for t in Q.defining_polynomials()])) + return(Q.preimage(self)) #else assume a point BR = self.base_ring() diff --git a/src/sage/schemes/projective/projective_morphism_helper.pyx b/src/sage/schemes/projective/projective_morphism_helper.pyx index fc46594993d..ea3f1ebf62d 100644 --- a/src/sage/schemes/projective/projective_morphism_helper.pyx +++ b/src/sage/schemes/projective/projective_morphism_helper.pyx @@ -275,81 +275,3 @@ def _normalize_coordinates(list point, int prime, int len_points): point[coefficient] = (point[coefficient]*mod_inverse)%prime return point - -def _forward_image_subscheme(self, X): - """ - Compute the forward image of a projective subscheme ``x`` by ``self``. - - The forward image is compute through elimination. - In particular, let $X = V(h_1,\ldots, h_t)$ and define the ideal - $I = (h_1,\ldots,h_t,y_0-f_0(\bar{x}), \ldots, y_n-f_n(\bar{x}))$. - Then the elimination ideal $I_{n+1} = I \cap K[y_0,\ldots,y_n]$ is a homogeneous - ideal and $self(X) = V(I_{n+1})$. - - INPUT: - - - ``X`` - a subscheme in the domain of ``self`` - - OUTPUT: - - - a subscheme in the domain of ``self`` - - EXAMPLES: - - sage: PS. = ProjectiveSpace(CC, 3) - sage: H = End(PS) - sage: f = H([x^2 + y^2, y^2, z^2-y^2, w^2]) - sage: X = PS.subscheme([z-2*w]) - sage: f(X) - Closed subscheme of Projective Space of dimension 3 over Complex Field - with 53 bits of precision defined by: - y + z + (-4.00000000000000)*w - - :: - - sage: R. = PolynomialRing(QQ) - sage: P. = ProjectiveSpace(FractionField(R), 2) - sage: H = End(P) - sage: f = H([x^2 + 2*y*z, t^2*y^2, z^2]) - sage: f([t^2*y-z]) - Closed subscheme of Projective Space of dimension 2 over Fraction Field - of Univariate Polynomial Ring in t over Rational Field defined by: - y + (-1/t^2)*z - - :: - - sage: set_verbose(-1) - sage: PS. = ProjectiveSpace(Qp(3), 2) - sage: H = End(PS) - sage: f = H([x^2,2*y^2,z^2]) - sage: X = PS.subscheme([2*x-y,z]) - sage: f(X) - Closed subscheme of Projective Space of dimension 2 over 3-adic Field - with capped relative precision 20 defined by: - z, - x + (1 + 3^2 + 3^4 + 3^6 + 3^8 + 3^10 + 3^12 + 3^14 + 3^16 + 3^18 + - O(3^20))*y - """ - dom = self.domain() - codom = self.codomain() - CR_dom = dom.coordinate_ring() - CR_codom = codom.coordinate_ring() - n = CR_dom.ngens() - m = CR_codom.ngens() - #can't call eliminate if the base ring is polynomial so we do it ourselves - #with a lex ordering - R = PolynomialRing(self.base_ring(), n+m, 'y', order = 'lex') - Rvars = R.gens()[0 : n] - phi = CR_dom.hom(Rvars,R) - zero = [0 for _ in range(n)] - psi = R.hom(zero + list(CR_codom.gens()),CR_codom) - #set up ideal - L = R.ideal([phi(t) for t in X.defining_polynomials()] + [R.gen(n+i) - phi(self[i]) for i in range(m)]) - G = L.groebner_basis() #eliminate - newL = [] - #get only the elimination ideal portion - for i in range (len(G)-1,0,-1): - v = G[i].variables() - if all([Rvars[j] not in v for j in range(n)]): - newL.append(psi(G[i])) - return(codom.subscheme(newL))