// ------------------------------------------------------------------------ // SCHEMES // ------------------------------------------------------------------------ // In this example we write down a monomial scheme // and analyze the basic properties of its components. // Declare affine 3-space over the rationals. A := AffineSpace(Rationals(),3); A; // Define the subscheme of A defined by a sequence of polynomials. X := Scheme(A,[x*y^2,x^4*z]); X; // Invariants and predicates. Dimension(X); IsReduced(X); Xprim := PrimaryComponents(X); Xprim; // Xprim is a sequence of components; to access elements, use brackets. Xprim[1]; PrimeComponents(X); Xred, f := ReducedSubscheme(X); Xred; // f is the inclusion map f:Xred -> X. f; AmbientSpace(X); // Comparison in Magma is "eq" AmbientSpace(X) eq A; I := DefiningIdeal(X); I; // The ring containing I. R := Generic(I); // Define a subscheme of projective space. Proj(R/I); // -------------------------------------------------------------------------- // GROEBNER BASES // -------------------------------------------------------------------------- // We compute the Groebner basis of the "Cyclic-6" ideal with respect // to the lexicographical order. P := PolynomialRing(Rationals(), 6); P; // Declare the ideal. I := ideal

; // Declare the ideal in a more clever way. sigma := hom

P | [y,z,t,u,v,x]>; sigma(x); gens := [ &+[ (sigma^i)(m) : i in [1..6] ] : m in [x,x*y,x*y*z,x*y*z*t,x*y*z*t*u] ] cat [x*y*z*t*u*v - 1]; gens eq Generators(I); time gb := GroebnerBasis(I); #gb; Dimension(I); // Since the ideal is zero-dimensional and the monomial order is lex, // the last polynomial in the lex Groebner basis is univariate. gb[17]; time Factorization(gb[17]); Roots(UnivariatePolynomial(gb[17]), ComplexField()); // Now compute the elimination ideal of I which eliminates // variables 1 through 4. EliminationIdeal(I, 4); // We write a "short" function for creating the cyclic n-ideal. function CyclicNIdeal(n); P := PolynomialRing(Rationals(), n); sigma := hom

P | [P.i : i in [2..n] cat [1]]>; monoms := [P.1]; for i := 2 to n do Append(~monoms, monoms[i-1]*P.i); end for; gens := [ &+[ (sigma^i)(m) : i in [1..n] ] : m in monoms[1..n-1] ] cat [ monoms[n] - 1]; return ideal

; end function; // Instruct the Faugere algorithm to be chatty so we can watch // the progression of the computation. SetVerbose("Groebner", 1); time gb := GroebnerBasis(CyclicNIdeal(7)); // Notice that special algorithms are being used here by default. // The Groebner basis is computed using Faugere's F4 algorithm. // The ideal is first homogenized and then the homogenizing variable // is removed. // Most of the time was spent in the FGLM algorithm, which changes the // easy term order (chosen by Magma, grevlex) to lex. // ... (See the description in the Magma documentation) // And now for the univariate polynomial. gb[#gb]; // Turn verbosity off! SetVerbose("Groebner", 0); // Magma can work with many different kinds of term orders and ground rings. Z := IntegerRing(); // Construct polynomial ring with weight order and x > y > z P := PolynomialRing(Z, 3, "weight", [4,2,1, 1,2,3, 1,1,1]); a+b+c; (a+b^2+c^3)^4; // -------------------------------------------------------------------------- // POINTS, CURVES, and FINITE FIELDS // -------------------------------------------------------------------------- // We define a curve over a finite field and play with it. k := FiniteField(7); P2 := ProjectiveSpace(k,2); X := Scheme(P2, x^4 + y^4 + z^4); // To obtain the point (2:3:1) on X, // coerce the sequence [2,3,1] as a point on X. X ! [2,3,1]; // Create an extension of k of degree 2, generated by the element w. l := ext; // Try to coerce points onto X IsCoercible(X,[w^10, 1, 1]); IsCoercible(X(l),[w^10, 1, 1]); // Finding those points was not simply good luck. // We can for this small example by naively listing them. Points(X); Random(Points(X)); #Points(X,l); // Count the number of points on X over extension fields up to degree 5. time ptcnt := [ #Points(X, ext) : n in [1..5] ]; ptcnt; // This is already pretty slow when n is 5. ZetaFunction(X); ZetaFunction; C := Curve(X); Type(C); Type(X); Z := ZetaFunction(C); Z; // Assign name to the dummy variable Parent(Z); _ := Parent(Z); Z; // The zeta function encodes the number of points on X over every // finite extension of k! cf := Coefficients(PowerSeriesRing(Rationals())!(Derivative(Z)/Z)); cf; cf[1..5] eq ptcnt; // Just to show off. p := RandomPrime(100); p; #EllipticCurveFromjInvariant(GF(p)!1); // Now a curve, we can do many things with C. // First, we compute some fundamental invariants. IsNonsingular(C); Genus(C); KC := FunctionField(C); BasisOfDifferentialsFirstKind(C); AutC := AutomorphismGroup(C); IdentifyGroup(AutC); AutCsol := SolvableQuotient(AutC); #AutCsol eq #AutC; AutCsol; Centre(AutCsol); // Next, we compute the image of C under "twice" the canonical embedding. K := CanonicalDivisor(C); Dimension(2*K); phi := DivisorMap(2*K); phi; // We give names to the variables in the codomain. P5<[u]> := Codomain(phi); phi(C); Dimension(phi(C)); // Many other invariants are defined. #WeierstrassPlaces(C); Cl := ClassGroup(C); Cl; // From the places of degree 1 on C and thrice the canonical divisor, // we obtain an algebraic-geometry code. AlgebraicGeometricCode(Places(C,1), 3*K); // We now define a morphism from C to an elliptic curve. phi := map P2 | [x^2,y*z,z^2]>; // The image is some curve D. D := Image(phi); Genus(D); Q := phi(X![2,3,1]); // D has the structure of an elliptic curve when equipped with // the point Q. E := EllipticCurve(D, Q); E; jInvariant(E); AbelianGroup(E); IsSupersingular(E); // We compute the ramification divisor, which is an effective divisor // supported at 2 points each of degree 2. R := RamificationDivisor(Restriction(phi,C,D)); Degree(R); Support(R); Points(Cluster(R), l); // -------------------------------------------------------------------------- // MULTIVARIATE POLYNOMIAL SYSTEMS OVER GF(2) // -------------------------------------------------------------------------- // // We construct a sequence B of 4 polynomials in 5 variables, // and note that the GrC6bner basis of B contains monomials having // degrees greater than 1. P := PolynomialRing(GF(2), 5); B := [a*b + c*d + 1, a*c*e + d*e, a*b*e + c*e, b*c + c*d*e + 1]; GroebnerBasis(B); // To solve over GF(2) itself, one can add the field polynomials // a^2 + a, b^2 + b, etc. Magma recognizes these extra polynomials // and uses an optimized representation; this makes the computation // much faster for larger examples. L := [P.i^2 + P.i: i in [1 .. Rank(P)]]; BB := B cat L; BB; GroebnerBasis(BB); I := ideal

; // List all points on the reduced zero-dimensional scheme I. Variety(I); // Massive examples are possible, e.g. those coming from HFE // cryptosystems. // -------------------------------------------------------------------------- // RESOLUTION GRAPH OF A CURVE SINGULARITY // -------------------------------------------------------------------------- // // First make a curve with a singularity. A := AffineSpace(Rationals(),2); C := Curve(A,(x^2 - y^3)^2 + x*y^6); // The interesting singularity is at the origin. // Calculate the resolution graph of this singularity and display it. g := ResolutionGraph(C,Origin(A)); g; // The resulting graph has 6 vertices. So the transverse resolution // of this singularity is achieved by 6 blowups. // In brackets, each vertex has a label of the form [s, m, k, t], where: // s is the self-intersection; // m is the multiplicity (dependent on context); // k is the canonical multiplicity; // t is the number of transverse intersections at v. // -------------------------------------------------------------------------- // FUN WITH QUADRICS // -------------------------------------------------------------------------- // P := ProjectiveSpace(RationalField(),4); // Declare an intersection of quadrics. G := [a*d + c*e, a*c + d*e, a^2 - e^2, c^2*e - d^2*e, b^2 + c*d + e^2]; X := Scheme(P,G); Dimension(X); IsReduced(X); Xprim := PrimeComponents(X); Xprim; // X is the union of three (irreducible) curves. [ Dimension(V) : V in Xprim ]; // The points of intersection of these curves will be // singular points of X. SingularPoints(X); Xsing := SingularPointsOverSplittingField(X); Xsing; // The singular points are defined over the algebraic closure // of the rationals! Qbar := Ring(Universe(Xsing)); Qbar; // Now intersect X with a hyperplane. H := Scheme(P, a+b+c+d+e); XcapH := Intersection(X, H); XcapH; Dimension(XcapH); Degree(XcapH); Points(ChangeRing(XcapH,Qbar)); Qbar; Simplify(Qbar); Qbar; // Compute the Galois group acting on the points of X meet H // (together with the singular points). f := AbsolutePolynomial(Qbar); f; L := NumberField(f); // All of the points are defined over L. #Points(XcapH, L); GaloisGroup(L); // Errors happen! This bug has been reported and can be // temporarily fixed by scaling f to have integer coefficients m := Lcm([Denominator(c) : c in Coefficients(f)]); f := ChangeRing(m*f, Integers()); L := NumberField(f); GaloisGroup(L); // The Galois group is biquadratic, as we saw above. Z_L := MaximalOrder(L); Discriminant(Z_L); // Compute a "nice" representation of this number field. OptimizedRepresentation(Z_L); // Now compute the secant variety of X (over Q). // We choose the affine patch corresponding to b <> 0. time SecX := SecantVariety(X : PatchIndex := 2); Dimension(SecX); IsInSecantVariety(X,P![0,1,0,-3,0]); // Magma has much else to experiment with: // - K3 surfaces // - Parametrization of del Pezzo surfaces // - Finite incidence structures (graphs, multigraphs, etc.) // - Representation and Lie theory // - Quaternion algebras // ... // Thank you!