Subsections


16. Algebraic geometry


16.1 Plotting curves

To plot a curve in SAGE, you can use Singular and surf (http://surf.sourceforge.net/) or use matplotlib (included with SAGE).

16.1.1 matplotlib

Here are several examples. To view them, type p.save("<path>/my_plot.png") (where <path> is a directory path which you have write permissions to where you want to save the plot) and view it in a viewer (such as GIMP).

A blue conchoid of Nicomedes:

        sage: L = [[1+5*cos(pi/2+pi*i/100), tan(pi/2+pi*i/100)*(1+5*cos(pi/2+pi*i/100))] for i in range(1,100)]
        sage: p = line(L, rgbcolor=(1/4,1/8,3/4))

A blue hypotrochoid (3 leaves):

 
        sage: n = 4; h = 3; b = 2
        sage: L = [[n*cos(pi*i/100)+h*cos((n/b)*pi*i/100),n*sin(pi*i/100)-h*sin((n/b)*pi*i/100)] for i in range(200)]
        sage: p = line(L, rgbcolor=(1/4,1/4,3/4))

A blue hypotrochoid (4 leaves):

 
        sage: n = 6; h = 5; b = 2
        sage: L = [[n*cos(pi*i/100)+h*cos((n/b)*pi*i/100),n*sin(pi*i/100)-h*sin((n/b)*pi*i/100)] for i in range(200)]
        sage: p = line(L, rgbcolor=(1/4,1/4,3/4))

A red limacon of Pascal:

 
        sage: L = [[sin(pi*i/100)+sin(pi*i/50),-(1+cos(pi*i/100)+cos(pi*i/50))] for i in range(-100,101)]
        sage: p = line(L, rgbcolor=(1,1/4,1/2))

A light green trisectrix of Maclaurin:

 
        sage: L = [[2*(1-4*cos(-pi/2+pi*i/100)^2),10*tan(-pi/2+pi*i/100)*(1-4*cos(-pi/2+pi*i/100)^2)] for i in range(1,100)]
        sage: p = line(L, rgbcolor=(1/4,1,1/8))

A green lemniscate of Bernoulli:

 
        sage: v = [(1/cos(-pi/2+pi*i/100), tan(-pi/2+pi*i/100)) for i in range(201)]
        sage: L = [(a/(a^2+b^2), b/(a^2+b^2)) for a,b in v]
        sage: p = line(L, rgbcolor=(1/4,3/4,1/8))

16.1.2 surf

In particular, since surf is only available on a unix type OS (and is not included with SAGE), plotting using the commands below in SAGE is only available on such an OS. Incidentally, surf is included with several popular linux distributions.

sage: s = singular.eval
sage: s('LIB "surf.lib";')
      ...
sage: s("ring rr0 = 0,(x1,x2),dp;")
      ...
sage: s("ideal I = x1^3 - x2^2;")
      ''
sage: s("plot(I);")
Press q with the surf window active to exit from surf and return to SAGE.

You can save this plot as a surf script. In the surf window which pops up, just choose file, save as, etc.. (Type ``q'' or select file, quit, to close the window.)

The plot produced is omitted but the gentle reader is encouraged to try it out.


16.2 Plotting surfaces

To plot a surface in SAGE is no different that to plot a curve, though the syntax is slightly different. In particular, you need to have surf loaded.

sage: singular.eval('ring rr1 = 0,(x,y,z),dp;')
''
sage: singular.eval('ideal I(1) = 2x2-1/2x3 +1-y+1;')
''
sage: singular.eval('plot(I(1));')
...


16.3 Point counting on curves

This uses the SAGE-Singular interface. To find the rational points on a curve $ X$ over a finite field $ F$ , there are two approaches.


16.4 Riemann-Roch spaces

To compute a basis for the Riemann-Roch space $ L(D)$ associated to a divisor $ D$ on a curve $ X$ over a field $ F$ , use Singular's BrillNoether command. (For details on this command, see the section Brill-Noether in the Singular online documentation (http://www.singular.uni-kl.de/Manual/html/sing_960.htm and the paper [CF].)

sage: singular.LIB('brnoeth.lib')
sage: _ = singular.ring(5,'(x,y)','lp')
sage: print singular.eval("list X = Adj_div(-x5+y2+x);")
Computing affine singular points ...
Computing all points at infinity ...
Computing affine singular places ...
Computing singular places at infinity ...
Computing non-singular places at infinity ...
Adjunction divisor computed successfully
<BLANKLINE>
The genus of the curve is 2
sage: print singular.eval("X = NSplaces(1..2,X);")
Computing non-singular affine places of degree 1 ...
Computing non-singular affine places of degree 2 ...
sage: print singular("X[3];")
[1]:
   1,1
[2]:
   1,2
[3]:
   1,3
[4]:
   1,4
[5]:
   1,5
[6]:
   1,6

The 6 Places in X[3] are of degree 1. We define the rational divisor G = 4*C[3][1]+4*C[3][2]+4*C[3][3] (of degree 12):

sage: singular.eval("intvec G = 4,4,4,0,0,0;")
      ...
sage: singular.eval("def R = X[1][2];")
      ...
sage: singular.eval("setring R;")
      ...
sage: print singular.eval("list LG = BrillNoether(G,X);")
Forms of degree 6 :
28

Vector basis successfully computed

sage: print singular.eval("LG;") # here is the vector basis of L(G):
[1]:
   _[1] = x2
   _[2] = -x2+z2
..


16.4.1 AG codes

SAGE can compute an AG code $ C=C_X(D,E)$ by calling Singular's BrillNoether to compute a basis of the Riemann Roch space $ L(D)=L_X(D)$ . In addition to the curve $ X$ and the divisor $ D$ , you must also specify the evaluation divisor $ E$ .

Here's an example, one which computes a generator matrix of an associated AG code. This time we use Singular's AGCode_L command.

sage: print singular.eval('LIB "brnoeth.lib";')
sage: singular.eval("ring s = 2,(x,y),lp;")
      ...
sage: print singular.eval("list HC = Adj_div(x3+y2+y);")
Computing affine singular points ...
Computing all points at infinity ...
Computing affine singular places ...
Computing singular places at infinity ...
Computing non-singular places at infinity ...
Adjunction divisor computed successfully

The genus of the curve is 1
sage: print singular.eval("list HC1 = NSplaces(1..2,HC);")
Computing non-singular affine places of degree 1 ...
Computing non-singular affine places of degree 2 ...
sage: print singular.eval("HC = extcurve(2,HC1);")
Total number of rational places : NrRatPl = 9

sage: singular.eval("intvec G = 5;")      # the rational divisor G = 5*HC[3][1]
      ''
sage: singular.eval("def R = HC[1][2];")
      ''
sage: singular.eval("setring R;")
      ''

The vector $ G$ represents the divisor ``5 times the point at infinity''.

Next, we compute the Riemann-Roch space.

sage: print singular.eval("BrillNoether(G,HC);")
Forms of degree 3 :
10

Vector basis successfully computed

[1]:
   _[1] = x
   _[2] = z
[2]:
   _[1] = y
   _[2] = z
[3]:
   _[1] = 1
   _[2] = 1
[4]:
   _[1] = y2+yz
   _[2] = xz
[5]:
   _[1] = y3+y2z
   _[2] = x2z

That was the basis of the Riemann-Roch space, where each pair of fuctions represents the quotient (first function divided by second function). Each of these basis elements get evaluated at certain points to construct the generator matrix of the code. We next construct the points.

sage: singular.eval("def R = HC[1][5];")
      '// ** redefining R **'
sage: singular.eval("setring R;")
      ''
sage: print singular.eval("POINTS;")
[1]:
   [1]:
      0
   [2]:
      1
   [3]:
      0
[2]:
   [1]:
      0
   [2]:
      1
   [3]:
      1
[3]:
   [1]:
      0
   [2]:
      0
   [3]:
      1
[4]:
   [1]:
      1
   [2]:
      (a)
   [3]:
      1

plus 5 more, for a total of $ 9$ rational points on the curve. We define our ``evaluation divisor' $ D$ using a subset of these points (all but the first):

sage: singular.eval("def ER = HC[1][4];")
      ''
sage: singular.eval("setring ER;")
      ''
sage: singular.eval("intvec D = 2..9;")   # D = sum of the rational places no. 2..9 over F_4
      ''
sage: # let us construct the corresponding evaluation AG code :
sage: print singular.eval("matrix C = AGcode_L(G,D,HC);")
Forms of degree 3 :
10

Vector basis successfully computed

sage: # here is a linear code of type [8,5,> = 3] over F_4
sage: print singular.eval("print(C);")
0,0,1,  1,    (a+1),(a),  (a),  (a+1),
1,0,(a),(a+1),(a),  (a+1),(a),  (a+1),
1,1,1,  1,    1,    1,    1,    1,
0,0,1,  1,    (a),  (a+1),(a+1),(a),
0,0,(a),(a+1),1,    1,    (a+1),(a)
sage:

This is, finally, our desired generator matrix, where a represents a generator of the field extension of degree $ 2$ over the base fild $ GF(2)$ .

See About this document... for information on suggesting changes.