Local Geometry

Here we discuss some basic functions providing analysis of a point p lying on a curve C. Firstly we describe how to create points on curves and their basic access functions. One should also refer to the comments in Section Rational Points and Point Sets of the general schemes chapter about the point sets of point arguments of these functions where there is a fuller discussion of point sets.

Most functions usually have two arguments, a curve and a point on that curve. In fact, the point need not actually be in a point set of the curve since coercion will be attempted if it is not. Moreover, the curve argument is not strictly necessary either, since if the point does lie in a point set of the curve, it can be recovered automatically. So these functions also work with the curve argument omitted. However, omitting the curve argument should be thought of merely as a convenient shorthand and should be used with care --- it is very easy to use a point from some other space for which the function still makes sense but returns a misleading answer.

Contents

Creation of Points on Curves

Points of a curve C, and indeed points of any scheme in Magma, lie in point sets associated to C rather than C itself. Each point set is the parent of points whose coordinates lie in a particular extension ring of the base ring of the curve. Thus, if k is the base ring of the curve C, points whose coordinates lie in k are elements of the "base ring point set" denoted C(k). If L is an extension ring of k (in the sense of admitting coercion from k or being the codomain of a ring homomorphism from k) then points with coordinates in L lie in the point set C(L).

Here we give the basic point creation methods and access functions. For more information, consult the discussion of points and point sets in Section Rational Points and Point Sets of Chapter SCHEMES on schemes.

C ! [a,...] : Crv,[RngElt] -> Pt
For a sequence of elements a, ... of the base ring of C, this creates the point of C with coordinates (a, ... ). The parent of the resulting point is the base point set of the curve C rather than C itself.
C(L) ! [a,...] : SetPt,[RngElt] -> Pt
For a sequence of elements a, ... of the extension ring L of the base ring of C, this function creates the point of C with coordinates (a, ... ). The parent of the resulting point is the point set C(L) of the curve C rather than C itself. The phrase `extension ring' here means that either L admits automatic coercion from the base ring of C, or that L is the codomain of a ring homomorphism from that base ring.
Curve(p) : Pt -> Crv
The smallest scheme in the inclusion chain above the scheme on which the point p lies which is a curve. If p lies on a curve then the curve will be returned.
Curve(P) : SetPt -> Crv
The smallest scheme in the inclusion chain above the scheme P is a point set of which is a curve. If P is a point set of a curve then this curve will be returned.
Coordinates(p) : Pt -> SeqEnum
The sequence of ring elements corresponding to the coordinates of the point p.
p[i] : Pt, RngIntElt -> RngElt
Coordinate(p, i) : Pt,RngIntElt -> SeqEnum
The ith coordinate of the point p.
p eq q : Pt,Pt -> BoolElt
Returns true if and only if the two points p and q lie in schemes contained in a common ambient space, have coordinates that can be compared (either by lying in the same ring, or by an automatic coercion) and these coordinates are equal.
FormalPoint(P) : Pt -> Pt
Given a non--singular point P in C(K), where C is a curve and K is some extension of the field of definition of C, returns a point in C(LaurentSeriesRing(K)), such that specializing the variable to 0 yields P.

Operations at a Point

Most of the functions in this section report an error if p does not lie on C. Functions having arguments C, p allow the omission of C as long as the parent of p is a point set of C. A few of the functions apply only to plane curves.

p in C : Pt,Sch -> BoolElt
S in C : SeqEnum,Sch -> BoolElt
Returns true if and only if the point p or the sequence of coordinates S lies on the curve C. That is, return true if and only if the coordinates of p satisfy the equation of C.
IsNonsingular(p) : Pt -> BoolElt
IsNonsingular(C, p) : Sch,Pt -> BoolElt
Returns true if and only if p is a nonsingular point of the curve C.
IsSingular(p) : Pt -> BoolElt
IsSingular(C, p) : Sch,Pt -> BoolElt
Returns true if and only if the point p is a singular point on the curve C.
IsInflectionPoint(p) : Pt -> BoolElt,RngIntElt
IsInflectionPoint(C, p) : Sch,Pt -> BoolElt,RngIntElt
IsFlex(C, p) : Sch,Pt -> BoolElt,RngIntElt
IsFlex(p) : Pt -> BoolElt,RngIntElt
Returns true if and only if the point p is a flex of the plane curve C. An error is reported if p is a singular point of C. The second return value is the order of the flex, that is, the local intersection number at p of C with its tangent line at p.
TangentLine(p) : Pt -> Crv
TangentLine(C, p) : Crv,Pt -> Crv
The tangent line to the curve C at the point p embedded as a curve in the same space; an error if p is a singular point of C.

TangentCone(p) : Pt -> Sch
TangentCone(C, p) : Sch,Pt -> Sch
The tangent cone to the curve C at the point p embedded in the same ambient space.
IsTangent(C, D, p) : Sch,Sch,Pt -> BoolElt
Returns true if and only if the plane curves C and D are nonsingular and tangent at the point p.

Singularity Analysis

These functions report an error if p is not a singular point of C. Again, the arguments can be abbreviated to just the point if care is taken about its parent.

Multiplicity(p) : Pt -> RngIntElt
Multiplicity(C, p) : Sch,Pt -> RngIntElt
The multiplicity of the curve C at the point p.

IsDoublePoint(p) : Pt -> BoolElt
IsDoublePoint(C, p) : Crv,Pt -> BoolElt
Returns true if and only if the point p is a double point of the curve C.

IsOrdinarySingularity(p) : Pt -> BoolElt
IsOrdinarySingularity(C, p) : Sch,Pt -> BoolElt
Returns true if and only if the point p is a singular point of the curve C with reduced tangent cone.

IsNode(p) : Pt -> BoolElt
IsNode(C, p) : Sch,Pt -> BoolElt
Returns true if and only if the point p is an ordinary double point of the curve C.

IsCusp(p) : Pt -> BoolElt
IsCusp(C, p) : Crv,Pt -> BoolElt
Returns true if and only if the point p is a nonordinary double point of the curve C.
IsAnalyticallyIrreducible(p) : Pt -> BoolElt
IsAnalyticallyIrreducible(C, p) : CrvPln,Pt -> BoolElt
Returns true if and only if the plane curve C has exactly one place at the point p, or equivalently if the resolution of singularities is injective above p.
DeltaAdjustment(C, p) : Sch, Pt -> RngIntElt
Argument 2, p, is a singular point in a pointset on argument 1, C, a 1-dimensional scheme. Returns the "delta adjustment" of p (or the set of conjugate singularities that p represents if it is defined over a finite extension of the base field of C), which is the amount that p contributes to the difference between the arithmetic genus of C and its geometric genus (i.e. the arithmetic genus of its normalisation). This adjustment is computed via local Hilbert series.

Example Crv_curve-iscusp (H121E6)

Each of the two curves in this example has a double point at the origin. One of these is a node and one is a cusp.
> A<x,y> := AffineSpace(Rationals(),2);
> C := Curve(A,x^2-y^3);
> p := Origin(A);
> IsCusp(C,p);
true
> IsDoublePoint(C,p);
true
> IsReduced(TangentCone(C,p));
false
> D := Curve(A,x^2 - y^3 - y^2);
> IsAnalyticallyIrreducible(D,p);
false
> IsNode(D,p);
true

Resolution of Singularities

Again, all functions in this section only apply to plane curves.

Blowup(C) : CrvPln -> CrvPln, CrvPln
Given the affine plane curve C, return the two affine plane curves lying on the standard patches of the blowup of the affine plane at the origin. Note that the two curves returned are the birational transforms of C on the blowup patches. The patches are contained in the same affine space as the curve itself. If C does not contain the origin this returns an error message.

Blowup(C, M) : CrvPln,Mtrx -> CrvPln, RngIntElt, RngIntElt
This returns the weighted blowup of the plane curve C at the origin defined by the 2 x 2 matrix of integers M. Again, the birational transform of C is returned inside the ambient plane of C. An error is reported if M does not have determinant ∓ 1.

Example Crv_weighted-blowup (H121E7)

It often happens that one can replace a string of ordinary blowups used to resolve a curve singularity by a single weighted blowup.
> A<x,y> := AffineSpace(Rationals(),2);
> C := Curve(A,y^2 - x^7);
> f := map< A -> A | [x^2*y,x^7*y^3] >;
> C @@ f;
Curve over Rational Field defined by
x^14*y^7 - x^14*y^6
> M := Matrix(2,[2,1,7,3]);
> Blowup(C,M);
Curve over Rational Field defined by
-y + 1
14 6
The blowup function takes the total pullback as the underlying map and then removes all copies of the x and y axes. The pair of numbers displayed in the final line is the multiplicity of these factors in the total pullback. The curve returned is the birational pullback of C on some patch of a rational surface arising by a number of blowups above the origin of A. It is clearly nonsingular --- it's linear! --- so this map resolves the singularity at the origin of C.

In fact, Magma has machinery for interpreting strings of blowups in terms of a graph, the resolution graph.

> ResolutionGraph(C);
The resolution graph on the Digraph
Vertex  Neighbours
1 ([ -2, 7, 4, 0 ])     2 ;
2 ([ -1, 14, 8, 1 ])    3 ;
3 ([ -3, 6, 3, 0 ])     4 ;
4 ([ -2, 4, 2, 0 ])     5 ;
5 ([ -2, 2, 1, 0 ])     ;
Consult Chapter RESOLUTION GRAPHS AND SPLICE DIAGRAMS for the full interpretation of this graph. Briefly, one should see this as representing a chain of five blowups which resolve the curve. Each vertex of the graph corresponds to one of the exceptional curves coming from these blowups. The curve extracted by the weighted blowup we saw above corresponds to vertex number 2. Indeed, we can see the multiplicity 14 in the total pullback as the second entry of the labelling sequence. (The multiplicity 6 which we saw above is the corresponding entry in exceptional curve 3.) The fourth entry of that sequence, 1, reports that the birational transform of C to the blownup surface intersects the exceptional curve with multiplicity 1. This is the only nonzero fourth entry of any vertex label, so we conclude that there is exactly one place above the singularity at the origin. This can be confirmed (more quickly!) by the divisor machinery which will be discussed in Section Divisors.
> Places(C ! Origin(A));
[
    Place at (0 : 0 : 1)
]
> Degree($1[1]);
1

Log Canonical Thresholds

For background on log canonical singularities, see for example [Koll{ár 1997, Singularities of pairs] or [Koll{ár 1998, Birational geometry of algebraic varieties].

Let V be a variety with at worst log canonical singularities, P a point on V and D an effective Q-Cartier divisor on V. Then the log canonical threshold (lct) of the log pair (V, D) at P is the number

(lct)P(V, D) = sup{ λ ∈Q | (V, λ D) (is log canonical at ) P} ∈Q ∪{+∞}.

We can also consider the lct of D along the whole of V: eqalign( (lct)(V, D) &= in (lct)P(V, D) | P ∈V
&= sup{ λ ∈Q | (V, λ D) (is log canonical) }.
)

LogCanonicalThreshold(C) : Sch -> FldRatElt, BoolElt
LCT(C) : Sch -> FldRatElt,BoolElt
The log canonical threshold of the curve C computed at its singular k-points, where k is the base field of C.
LogCanonicalThresholdAtOrigin(C) : Sch -> FldRatElt
The local log canonical threshold of the affine curve C computed at the origin.
LogCanonicalThreshold(C, P) : Sch, Pt -> FldRatElt
LCT(C, P) : Sch, Pt -> FldRatElt
The local log canonical threshold of the curve C computed at the point P.
LogCanonicalThresholdOverExtension(C) : Sch -> FldRatElt
The log canonical threshold of the curve C computed at all singular points including those defined over some base field extension.

Example Crv_lct-projective-plane (H121E8)

Consider a cubic curve C on the projective plane, then the singularities of C resemble one of the following examples: a smooth curve, e.g.,
> P2<x,y,z> := ProjectiveSpace(Rationals(),2);
> A := Curve(P2,x^3-y^2*z-3*x*z^2);
> IsNonsingular(A);
true
a curve with ordinary double points (i.e. nodes), e.g.,
> B := Curve(P2,x^3-y^2*z-3*x*z^2+2*z^3);
> IsNodalCurve(B);
true
a curve with one cuspidal point, e.g.,
> C := Curve(P2,x^3-y^2*z);
> #SingularPoints(C) eq 1;
true
> IsCusp(C,SingularPoints(C)[1]);
true
a conic and a line that are tangent, e.g.,
> D := Curve(P2,(x^2+(y-z)^2-z^2)*y);
> #PrimeComponents(D) eq 2;
true
> TangentCone(PrimeComponents(D)[1],P2![0,0,1]) in PrimeComponents(D);
true
three lines intersecting at one (Eckardt) point, e.g.
> E := Curve(P2,x*y*(x-y));
> IsOrdinarySingularity(E,P2![0,0,1]);
true
> Multiplicity(E,P2![0,0,1]);
3
a curve whose support consists of two lines, e.g.,
> F := Curve(P2,x^2*y);
> IsReduced(F);
false
> #SingularPoints(ReducedSubscheme(F)) eq 1;
true
> IsNodalCurve(Curve(ReducedSubscheme(F)));
true
or a curve whose support consists of three lines, e.g.,
> G := Curve(P2,x^3);
> IsReduced(G);
false
> IsNonsingular(ReducedSubscheme(G));
true
It is known that a curve is log canonical whenever its singularities are at worst nodal, thus (lct)((P)2, A) = (lct)((P)2, B) = 1. For the remaining reduced curves we can resolve their singularities and calculate their discrepancies to find their log canonical thresholds.
> curves := [* A,B,C,D,E,F,G *];
> [LogCanonicalThreshold(curve) : curve in curves];
It follows that (lct)((P)2, - K_((P)2)) ≤((1) /(3)). In fact, it is not hard to see that equality holds.

Example Crv_lct-over-ext (H121E9)

Here we exhibit a curve C over the rationals, Q, that has singularities defined over a splitting field, k, where (lct)(C) (over k) < (lct)(C) (over Q). We take a curve C in the projective plane P2 with one ordinary double point and two triple point singularities. Such a curve can be obtained by calling:
> P2<x,y,z> := ProjectiveSpace(Rationals(),2);
> C := RandomPlaneCurve(6,[1,2],P2);
For this example we use the fixed curve C defined below.
> f := x*y^5 + y^6 + x^5*z + x^2*y^3*z + 2095/3402*y^5*z + x^4*z^2 -
>      6244382419/8614788*x^3*y*z^2 -
>      28401292681/8614788*x^2*y^2*z^2 -
>      89017753225/25844364*x*y^3*z^2 -
>      243243649115/232599276*y^4*z^2 -
>      2798099890675/70354102*x^3*z^3 -
>      22754590185549/281416408*x^2*y*z^3 -
>      7190675316787/140708204*x*y^2*z^3 -
>      75304687887883/7598243016*y^3*z^3 +
>      17778098933653/140708204*x^2*z^4 +
>      6098447759659/35177051*x*y*z^4 +
>      24308031251845/422124612*y^2*z^4 -
>      4694415764252/35177051*x*z^5 -
>      77497995284599/844249224*y*z^5 +
>      6592790982389/140708204*z^6;
> C := Curve(P2,f);
> IsSingular(C);
true
> LogCanonicalThreshold(C);
1
> IsNodalCurve(C);
false
Thus C must have singularities defined over some field extension.
> HasSingularPointsOverExtension(C);
true
> LogCanonicalThresholdOverExtension(C);
2/3

Local Intersection Theory

The main function here for a single point uses a standard Euclidean algorithm to calculate local intersection numbers at points where two plane curves meet. It was taken from unpublished lecture notes of Franz Winkler, "Introduction to Commutative Algebra and Algebraic Geometry"; the same algorithm is in Fulton's book [Ful69]. These numbers are also called intersection multiplicities in the literature. In the following sections there are functions for finding the intersection points of two curves.

There is now a variant that uses an algorithm of Jan Hilmar and Chris Smyth described in [HS10]. This computes all intersection points of the two curves as a set of Galois conjugacy classes and their intersection numbers in a single computation. The implementation, adapted into Magma from code contributed by Chris Smyth, returns the sequence of points along with the corresponding local intersection multiplicities.

IsIntersection(C,D,p) : Sch,Sch,Pt -> BoolElt
Returns true if and only if the point p lies on both curves C and D.
IsTransverse(C,D,p) : Sch,Sch,Pt -> BoolElt
Returns true if and only if the point p is a nonsingular point of both plane curves C and D and the curves have distinct tangents there.
IntersectionNumber(C,D,p) : Sch,Sch,Pt -> RngIntElt
The local intersection number Ip(C, D) of the plane curves C and D at the point p. This reports an error if C or D have a common component at p.
IntersectionNumbers(C,D) : CrvPln,CrvPln -> List
IntersectionNumbers(F,G) : RngMPolElt,RngMPolElt -> List
    Global: BoolElt                     Default: false
These intrinsics use the algorithm of Hilmar and Smyth to compute in one go a list of all intersection places along with the corresponding local intersection multiplicities of two projective plane curves C and D defined over k: a finite field, an algebraic field or the rationals Q. Here, intersection place means a point in P2(K), where P2 is the ambient of C and D and K is a finite extension of k, which represents a Galois conjugacy class of ([K:k]) points in the intersection of C and D.

The first intrinsic takes C and D as arguments (which must have no common irreducible component) and returns the result as a list of pairs < p, m >, where p is an element of a pointset P2(K) giving a place in the intersection and m is the corresponding local intersection multiplicity.

The second intrinsic avoids the use of pointsets. It takes two homogeneous polynomials F and G which are relatively prime and lie in the same multivariate polynomial ring P = k[x, y, z]. They represent two plane curves in Proj(P) and the result is a list of intersection places of these curves with intersection multiplicity. The elements of the list are again pairs < p, m >, but here p is represented as in Hilmar and Smyth's paper [HS10], p is a list of three elements of one of three types:

i)
[ * 1, 0, 0 * ]. Represents the plane projective point with these homogeneous coordinates.
ii)
[ * f(y), 1, 0 * ] with f(y) an irreducible polynomial in k[y]. Represents the conjugate points with homogeneous coordinates [α, 1, 0] where α ranges over the roots of f.
iii)
[ * h(x, y), g(y), 1 * ] with g(y) an irreducible polynomial in k[y] and h(x, y) a polynomial in k[x, y] whose image in (k[y]/(g(y)))[x] is irreducible. Represents the conjugate points with homogeneous coordinates [γ, β, 1] where β ranges over the roots of g and, for each β, γ ranges over the roots of h(x, β).

The parameter Global applies to the polynomial version. If it takes its default value false, both the two-variable and one-variable polynomial rings used in the type ii) and iii) representations will be non-global versions with the y and x, y labelling of variables as shown. This may have the disadvantage that elements returned by different calls to the intrinsic cannot be directly compared because they lie in different rings. If Global is true, the global one- and two-variable polynomial rings are used but in this case the variables are not labelled by the intrinsic.

Example Crv_local-intersection-example (H121E10)

The local intersection of two curves at a point where they share a common tangent is calculated. If the curves did not share a tangent, the intersection would be the product of multiplicities which it is not in this case.
> A<x,y> := AffineSpace(Rationals(),2);
> C := Curve(A, y^2 - x^5);
> D := Curve(A, y - x^2);
> p := Origin(A);
> IntersectionNumber(C,D,p);
4
> Multiplicity(C,p) * Multiplicity(D,p);
2
These intersection numbers are often defined to be the length of a particular affine algebra. (See [Har77] Chapter I, Exercise 5.4.) Below it is checked that this definition produces the same result in this case. Note that the algebra is not localised at p so the length calculated is the sum of intersection numbers at all intersection points. At the end one sees that the discrepancy of 1 is accounted for by a single transverse intersection away from the origin.
> RA := CoordinateRing(A);
> I := ideal< RA | DefiningPolynomial(C), DefiningPolynomial(D) >;
> Dimension(RA/I);
5
> IP := IntersectionPoints(C,D);
> IP;
{@ (0, 0), (1, 1) @}
> IsTransverse(C,D,IP[1]);
false
> IsTransverse(C,D,IP[2]);
true

Example Crv_crv:int-nmbrs (H121E11)

This example is taken from the paper of Hilmar and Smyth. We use the polynomial version for which the output is more explicit.
> P<x,y,z> := PolynomialRing(Rationals(),3,"grevlex");
> A := (y-z)*x^5+(y^2-y*z)*x^4+(y^3-y^2*z)*x^3+(-y^2*z^2+y*z^3)*x^2+
>   (-y^3*z^2+y^2*z^3)*x-y^4*z^2+y^3*z^3;
> B := (y^2-2*z^2)*x^2+(y^3-2*y*z^2)*x+y^4-y^2*z^2-2*z^4;
> c := IntersectionNumbers(A,B);
> c;
[* <[* x + y, y^2 + 1, 1 *], 1>, <[* x - y^3, y^4 + 1, 1 *], 1>,
  <[* y^2 + y + 1, 1, 0 *], 2>, <[* x^2 + x + 2, y - 1, 1 *], 1>,
  <[* 1, 0, 0 *], 2>, <[* x^2 + x*y + 2, y^2 - 2, 1 *], 1>,
  <[* x^3 - y, y^2 - 2, 1 *], 1>  *]
V2.28, 13 July 2023