Skip to content
This repository has been archived by the owner on Jan 30, 2023. It is now read-only.

Commit

Permalink
20774: Implement multiplicity, tangents, and is_ordinary_singularity
Browse files Browse the repository at this point in the history
  • Loading branch information
gsjorgenson committed Jun 10, 2016
1 parent 4fce7ed commit 4655c72
Show file tree
Hide file tree
Showing 3 changed files with 367 additions and 5 deletions.
184 changes: 184 additions & 0 deletions src/sage/schemes/curves/affine_curve.py
Original file line number Diff line number Diff line change
Expand Up @@ -34,8 +34,10 @@
# http://www.gnu.org/licenses/
#*****************************************************************************

from sage.categories.fields import Fields
from sage.categories.homset import Hom
from sage.interfaces.all import singular
import sage.libs.singular

from sage.misc.all import add

Expand Down Expand Up @@ -142,6 +144,58 @@ def projective_closure(self, i=0, PP=None):
from constructor import Curve
return Curve(AlgebraicScheme_subscheme_affine.projective_closure(self, i, PP))

def multiplicity(self, P):
r"""
Return the multiplicity of this affine curve at the point ``P``.
This is computed as the multiplicity of the local ring of self corresponding to ``P``. This
curve must be defined over a field.
INPUT:
- ``P`` -- a point in the ambient space of this curve.
OUTPUT:
- an integer.
EXAMPLES::
sage: A.<x,y,z> = AffineSpace(QQ, 3)
sage: C = A.curve([y - x^2, z - x^3])
sage: Q1 = A([1,1,1])
sage: C.multiplicity(Q1)
1
sage: Q2 = A([1,2,1])
sage: C.multiplicity(Q2)
0
::
sage: A.<x,y,z,w> = AffineSpace(QQ, 4)
sage: C = A.curve([y^9 - x^5, z^10 - w - y^4, z - y])
sage: C.multiplicity(A([0,0,0,0]))
5
"""
if not self.base_ring() in Fields():
raise TypeError("curve must be defined over a field")

# Check whether P is in the ambient space of this curve
try:
P = self.ambient_space()(P)
except TypeError:
raise TypeError("(=%s) must be a point on (=%s)"%(P,self))

# Apply a linear change of coordinates to self so that P is sent to the origin
AA = self.ambient_space()
chng_coords = [AA.gens()[i] + P[i] for i in range(AA.dimension_relative())]
I = AA.coordinate_ring().ideal([f(chng_coords) for f in self.defining_polynomials()])

# Compute the multiplicity of the local ring of the new curve defined by I
# corresponding to the point (0,...,0)
R = AA.coordinate_ring().change_ring(order='negdegrevlex')
return singular.mult(singular.std(I.change_ring(R))).sage()

class AffinePlaneCurve(AffineCurve):
def __init__(self, A, f):
r"""
Expand Down Expand Up @@ -348,6 +402,136 @@ def plot(self, *args, **kwds):
I = self.defining_ideal()
return I.plot(*args, **kwds)

def multiplicity(self, P):
r"""
Return the multiplicity of this affine plane curve at the point ``P``.
In the special case of affine plane curves, the multiplicity of an affine
plane curve at the point (0,0) can be computed as the minimum of the degrees
of the homogeneous components of its defining polynomial. To compute the
multiplicity of a different point, a linear change of coordinates is used.
This curve must be defined over a field.
INPUT:
- ``P`` -- a point in the ambient space of this curve.
OUTPUT:
- an integer.
EXAMPLES::
sage: A.<x,y> = AffineSpace(QQ, 2)
sage: C = Curve([y^2 - x^3], A)
sage: Q1 = A([1,0])
sage: C.multiplicity(Q1)
0
sage: Q2 = A([1,1])
sage: C.multiplicity(Q2)
1
sage: Q3 = A([0,0])
sage: C.multiplicity(Q3)
2
"""
if not self.base_ring() in Fields():
raise TypeError("curve must be defined over a field")

# Check whether P in in the ambient space of this curve
try:
P = self.ambient_space()(P)
except TypeError:
raise TypeError("(=%s) must be a point in the ambient space of (=%s)"%(P,self))

# Apply a linear change of coordinates to self so that P becomes (0,0)
AA = self.ambient_space()
f = self.defining_polynomials()[0](AA.gens()[0] + P[0], AA.gens()[1] + P[1])

# Compute the multiplicity of the new curve at (0,0), which is the minimum of the degrees of its
# nonzero terms
return min([g.degree() for g in f.monomials()])

def tangents(self, P):
r"""
Return the tangents of this affine plane curve at the point ``P``.
INPUT:
- ``P`` -- a point on this curve.
OUTPUT:
- a list of polynomials in the coordinate ring of the ambient space of this curve.
EXAMPLES::
sage: R.<a> = QQ[]
sage: K.<b> = NumberField(a^2 - 3)
sage: A.<x,y> = AffineSpace(K, 2)
sage: C = Curve([(x^2 + y^2 - 2*x)^2 - x^2 - y^2], A)
sage: Q = A([0,0])
sage: C.tangents(Q)
[x + (-1/3*b)*y, x + (1/3*b)*y]
"""
r = self.multiplicity(P)
if r < 1:
raise TypeError("(=%s) must be a point on (=%s)"%(P,self))
f = self.defining_polynomials()[0]
vars = self.ambient_space().gens()
deriv = [f.derivative(vars[0],i).derivative(vars[1],r-i)(list(P)) for i in range(r+1)]
from sage.arith.misc import binomial
T = sum([binomial(r,i)*deriv[i]*(vars[0] - P[0])**i*(vars[1] - P[1])**(r-i) for i in range(r+1)])
fact = T.factor()
return [l[0] for l in fact]

def is_ordinary_singularity(self, P):
r"""
Return whether the singular point ``P`` of this affine plane curve is an ordinary singularity.
The point ``P`` is an ordinary singularity of this curve if it is a singular point, and
if the tangents of this curve at ``P`` are distinct.
INPUT:
- ``P`` -- a point on this curve.
OUTPUT:
- Boolean. True or False depending on whether ``P`` is or is not an ordinary singularity of this
curve, respectively.
EXAMPLES::
sage: A.<x,y> = AffineSpace(QQ, 2)
sage: C = Curve([y^2 - x^3], A)
sage: Q = A([0,0])
sage: C.is_ordinary_singularity(Q)
False
::
sage: R.<a> = QQ[]
sage: K.<b> = NumberField(a^2 - 3)
sage: A.<x,y> = AffineSpace(K, 2)
sage: C = Curve([(x^2 + y^2 - 2*x)^2 - x^2 - y^2], A)
sage: Q = A([0,0])
sage: C.is_ordinary_singularity(Q)
True
"""
r = self.multiplicity(P)
if r < 2:
raise TypeError("(=%s) must be a singular point of (=%s)"%(P,self))

T = self.tangents(P)

# when there is a tangent of higher multiplicity
if len(T) < r:
return False

# otherwise they are distinct
return True

class AffinePlaneCurve_finite_field(AffinePlaneCurve):
def rational_points(self, algorithm="enum"):
r"""
Expand Down
32 changes: 27 additions & 5 deletions src/sage/schemes/curves/curve.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
Generic curves.
"""

from sage.categories.fields import Fields
from sage.misc.all import latex


Expand Down Expand Up @@ -202,16 +203,37 @@ def singular_points(self, F=None):
INPUT:
- ``F`` -- a field extension of the base ring of this curve over which to find
singular points.
- ``F`` -- (default: None) field over which to find the singular points. If not given,
the base ring of this curve is used.
OUTPUT:
- a set of points in the ambient space of this curve.
- a list of points in the ambient space of this curve.
EXAMPLES::
sage: A.<x,y,z> = AffineSpace(QQ, 3)
sage: C = Curve([y^2 - x^5, x - z], A)
sage: C.singular_points()
[(0, 0, 0)]
::
sage: R.<a> = QQ[]
sage: K.<b> = NumberField(a^8 - a^4 + 1)
sage: P.<x,y,z> = ProjectiveSpace(QQ, 2)
sage: C = Curve([359/12*x*y^2*z^2 + 2*y*z^4 + 187/12*y^3*z^2 + x*z^4\
+ 67/3*x^2*y*z^2 + 117/4*y^5 + 9*x^5 + 6*x^3*z^2 + 393/4*x*y^4\
+ 145*x^2*y^3 + 115*x^3*y^2 + 49*x^4*y], P)
sage: C.singular_points(K)
[(1/2*b^5 + 1/2*b^3 - 1/2*b - 1 : 1 : 0), (-2/3*b^4 + 1/3 : 0 : 1),
(2/3*b^4 - 1/3 : 0 : 1), (b^6 : -b^6 : 1), (-b^6 : b^6 : 1),
(-1/2*b^5 - 1/2*b^3 + 1/2*b - 1 : 1 : 0)]
"""
if F is None:
if not self.base_ring() in Fields():
raise TypeError("curve must be defined over a field")
elif not F in Fields():
raise TypeError("(=%s) must be a field"%F)
X = self.ambient_space().subscheme(self.Jacobian())
return X.rational_points(F)
return X.rational_points(0, F)

0 comments on commit 4655c72

Please sign in to comment.