Skip to content

Commit

Permalink
Trac #20676: Projective closure and affine patches for algebraic curves
Browse files Browse the repository at this point in the history
Given a curve in affine space, find its projective closure. Conversely,
given a projective curve, find its affine patches with respect to the
standard affine coordinate charts.

This could be done more efficiently by using the
projective_embedding/affine patches functionality for affine/projective
subschemes. Currently the projective_embedding function for affine
subschemes doesn't always have the right codomain:

{{{
A.<x,y,z> = AffineSpace(3,QQ)
X = A.subscheme([y-x^2,z-x^3])
X.projective_embedding().codomain()
}}}

so this should be addressed here, along with creating a
projective_closure function for affine subschemes.

URL: http://trac.sagemath.org/20676
Reported by: gjorgenson
Ticket author(s): Grayson Jorgenson
Reviewer(s): Ben Hutz
  • Loading branch information
Release Manager authored and vbraun committed Jun 9, 2016
2 parents 10f6d91 + 91bc630 commit 6348bb7
Show file tree
Hide file tree
Showing 4 changed files with 172 additions and 9 deletions.
6 changes: 3 additions & 3 deletions src/sage/schemes/affine/affine_morphism.py
Expand Up @@ -431,9 +431,9 @@ def homogenize(self, n):
sage: f.homogenize(2)
Scheme endomorphism of Closed subscheme of Projective Space
of dimension 2 over Integer Ring defined by:
-x1^2 + x0*x2
Defn: Defined on coordinates by sending (x0 : x1 : x2) to
(9*x1^2 : 3*x1*x2 : x2^2)
x1^2 - x0*x2
Defn: Defined on coordinates by sending (x0 : x1 : x2) to
(9*x1^2 : 3*x1*x2 : x2^2)
::
Expand Down
54 changes: 54 additions & 0 deletions src/sage/schemes/curves/affine_curve.py
Expand Up @@ -34,6 +34,7 @@
# http://www.gnu.org/licenses/
#*****************************************************************************

from sage.categories.homset import Hom
from sage.interfaces.all import singular

from sage.misc.all import add
Expand All @@ -43,8 +44,10 @@
from sage.rings.polynomial.polynomial_ring_constructor import PolynomialRing

from sage.schemes.affine.affine_space import is_AffineSpace

from sage.schemes.generic.algebraic_scheme import AlgebraicScheme_subscheme_affine

from sage.schemes.projective.projective_space import ProjectiveSpace

from curve import Curve_generic

Expand Down Expand Up @@ -88,6 +91,57 @@ def __init__(self, A, X):
if d != 1:
raise ValueError("defining equations (=%s) define a scheme of dimension %s != 1"%(X,d))

def projective_closure(self, i=0, PP=None):
r"""
Return the projective closure of this affine curve.
INPUT:
- ``i`` -- (default: 0) the index of the affine coordinate chart of the projective space that the affine
ambient space of this curve embeds into.
- ``PP`` -- (default: None) ambient projective space to compute the projective closure in. This is
constructed if it is not given.
OUTPUT:
- a curve in projective space.
EXAMPLES::
sage: A.<x,y,z> = AffineSpace(QQ, 3)
sage: C = Curve([y-x^2,z-x^3], A)
sage: C.projective_closure()
Projective Curve over Rational Field defined by x1^2 - x0*x2,
x1*x2 - x0*x3, x2^2 - x1*x3
::
sage: A.<x,y,z> = AffineSpace(QQ, 3)
sage: C = Curve([y - x^2, z - x^3], A)
sage: C.projective_closure()
Projective Curve over Rational Field defined by
x1^2 - x0*x2, x1*x2 - x0*x3, x2^2 - x1*x3
::
sage: A.<x,y> = AffineSpace(CC, 2)
sage: C = Curve(y - x^3 + x - 1, A)
sage: C.projective_closure(1)
Projective Plane Curve over Complex Field with 53 bits of precision defined by
x0^3 - x0*x1^2 + x1^3 - x1^2*x2
::
sage: A.<x,y> = AffineSpace(QQ, 2)
sage: P.<u,v,w> = ProjectiveSpace(QQ, 2)
sage: C = Curve([y - x^2], A)
sage: C.projective_closure(1, P).ambient_space() == P
True
"""
from constructor import Curve
return Curve(AlgebraicScheme_subscheme_affine.projective_closure(self, i, PP))

class AffinePlaneCurve(AffineCurve):
def __init__(self, A, f):
r"""
Expand Down
43 changes: 43 additions & 0 deletions src/sage/schemes/curves/projective_curve.py
Expand Up @@ -36,9 +36,11 @@
# http://www.gnu.org/licenses/
#*****************************************************************************

from sage.categories.homset import Hom
from sage.interfaces.all import singular
from sage.misc.all import add, sage_eval
from sage.rings.all import degree_lowest_rational_function
from sage.schemes.affine.affine_space import AffineSpace

from sage.schemes.generic.algebraic_scheme import AlgebraicScheme_subscheme_projective
from sage.schemes.projective.projective_space import is_ProjectiveSpace
Expand Down Expand Up @@ -85,6 +87,47 @@ def __init__(self, A, X):
if d != 1:
raise ValueError("defining equations (=%s) define a scheme of dimension %s != 1"%(X,d))

def affine_patch(self, i, AA=None):
r"""
Return the i-th affine patch of this projective curve.
INPUT:
- ``i`` -- affine coordinate chart of the projective ambient space of this curve to compute affine patch
with respect to.
- ``AA`` -- (default: None) ambient affine space, this is constructed if it is not given.
OUTPUT:
- a curve in affine space.
EXAMPLES::
sage: P.<x,y,z,w> = ProjectiveSpace(CC, 3)
sage: C = Curve([y*z - x^2, w^2 - x*y], P)
sage: C.affine_patch(0)
Affine Curve over Complex Field with 53 bits of precision defined by
x0*x1 - 1.00000000000000, x2^2 - x0
::
sage: P.<x,y,z> = ProjectiveSpace(QQ, 2)
sage: C = Curve(x^3 - x^2*y + y^3 - x^2*z, P)
sage: C.affine_patch(1)
Affine Plane Curve over Rational Field defined by x0^3 - x0^2*x1 - x0^2 + 1
::
sage: A.<x,y> = AffineSpace(QQ, 2)
sage: P.<u,v,w> = ProjectiveSpace(QQ, 2)
sage: C = Curve([u^2 - v^2], P)
sage: C.affine_patch(1, A).ambient_space() == A
True
"""
from constructor import Curve
return Curve(AlgebraicScheme_subscheme_projective.affine_patch(self, i, AA))

class ProjectivePlaneCurve(ProjectiveCurve):
def __init__(self, A, f):
r"""
Expand Down
78 changes: 72 additions & 6 deletions src/sage/schemes/generic/algebraic_scheme.py
Expand Up @@ -91,9 +91,9 @@
-x1^2 + x0*x2
To: Closed subscheme of Projective Space of dimension 3
over Rational Field defined by:
-x1^2 + x0*x2,
-x1*x2 + x0*x3,
-x2^2 + x1*x3
x1^2 - x0*x2,
x1*x2 - x0*x3,
x2^2 - x1*x3
Defn: Defined on coordinates by sending (x0, x1, x2) to
(1 : x0 : x1 : x2)
Expand Down Expand Up @@ -1825,6 +1825,9 @@ def projective_embedding(self, i=None, PP=None):
Returns a morphism from this affine scheme into an ambient
projective space of the same dimension.
The codomain of this morphism is the projective closure of this affine scheme in ``PP``,
if given, or otherwise in a new projective space that is constructed.
INPUT:
- ``i`` -- integer (default: dimension of self = last
Expand Down Expand Up @@ -1863,6 +1866,25 @@ def projective_embedding(self, i=None, PP=None):
u0^2 - u2*u3
Defn: Defined on coordinates by sending (x, y, z) to
(x : 1 : y : z)
::
sage: A.<x,y,z> = AffineSpace(QQ, 3)
sage: X = A.subscheme([y - x^2, z - x^3])
sage: X.projective_embedding()
Scheme morphism:
From: Closed subscheme of Affine Space of dimension 3 over Rational
Field defined by:
-x^2 + y,
-x^3 + z
To: Closed subscheme of Projective Space of dimension 3 over
Rational Field defined by:
x0^2 - x1*x3,
x0*x1 - x2*x3,
x1^2 - x0*x2
Defn: Defined on coordinates by sending (x, y, z) to
(x : y : z : 1)
"""
AA = self.ambient_space()
n = AA.dimension_relative()
Expand Down Expand Up @@ -1890,19 +1912,63 @@ def projective_embedding(self, i=None, PP=None):
elif PP.dimension_relative() != n:
raise ValueError("Projective Space must be of dimension %s"%(n))
PR = PP.coordinate_ring()
# Groebner basis w.r.t. a graded monomial order computed here to ensure
# after homogenization, the basis elements will generate the defining
# ideal of the projective closure of this affine subscheme
R = AA.coordinate_ring()
G = self.defining_ideal().groebner_basis()
v = list(PP.gens())
z = v.pop(i)
R = AA.coordinate_ring()
phi = R.hom(v,PR)
v.append(z)
polys = self.defining_polynomials()
X = PP.subscheme([phi(f).homogenize(i) for f in polys ])
X = PP.subscheme([phi(f).homogenize(i) for f in G])
v = list(R.gens())
v.insert(i, R(1))
phi = self.hom(v, X)
self.__projective_embedding[i] = phi
return phi

def projective_closure(self, i=None, PP=None):
r"""
Return the projective closure of this affine subscheme.
INPUT:
- ``i`` -- (default: None) determines the embedding to use to compute the projective
closure of this affine subscheme. The embedding used is the one which has a 1 in the
i-th coordinate, numbered from 0.
- ``PP`` -- (default: None) ambient projective space, i.e., ambient space
of codomain of morphism; this is constructed if it is not given.
OUTPUT:
- a projective subscheme.
EXAMPLES::
sage: A.<x,y,z,w> = AffineSpace(QQ,4)
sage: X = A.subscheme([x^2 - y, x*y - z, y^2 - w, x*z - w, y*z - x*w, z^2 - y*w])
sage: X.projective_closure()
Closed subscheme of Projective Space of dimension 4 over Rational Field
defined by:
x0^2 - x1*x4,
x0*x1 - x2*x4,
x1^2 - x3*x4,
x0*x2 - x3*x4,
x1*x2 - x0*x3,
x2^2 - x1*x3
::
sage: A.<x,y,z> = AffineSpace(QQ, 3)
sage: P.<a,b,c,d> = ProjectiveSpace(QQ, 3)
sage: X = A.subscheme([z - x^2 - y^2])
sage: X.projective_closure(1, P).ambient_space() == P
True
"""
return self.projective_embedding(i, PP).codomain()

def is_smooth(self, point=None):
r"""
Test whether the algebraic subscheme is smooth.
Expand Down

0 comments on commit 6348bb7

Please sign in to comment.