Thursday, June 19, 2014

The structure of my GSoC code and a short demo

I'm at the point where I can explain the layout of the code that I've written so far, and even demonstrate some of its functionality.

As mentioned in previous posts, the initial goal of my Google Summer of Code project is to implement in Sage functionality that will allow us to bound the analytic rank of an elliptic curve $E$ via certain explicit formula-type sums relating to the $L$-function of $E$. One could certainly achieve this by simply writing a method on the existing elliptic curve class in Sage. However, the machinery we'll be using to bound rank is useful outside of the context of elliptic curves: it allows us to compute  sums over zeros of any $L$-function that comes from a modular form. In fact, so long as

1. The $L$-function has an Euler product expansion over the primes;
2. The Euler product coefficients - akin to the $a_p$ values we've mentioned previously - are readily computible; and
3. The $L$-function obeys a functional equation which allows us to define and compute with the function inside of the critical strip;

then we can use this explicit-formula methodology to compute sums over the zeros of the $L$-function.

All the code is hosted on GitHub, so you can view it freely here (note: this repository is a branch of the main Sage repo, so it contains an entire copy of the Sage source. I'm only adding a tiny fraction of code in a few files to this codebase; I'll link to these files directly below).

To this effect, it makes sense to write a new class in Sage that can ultimately be made to compute zero sums for any motivic $L$-function. This is what I'll be doing. I've created a file zero_sums.py in the sage/lfunctions/ directory, inside of which I'll write an family of classes that take as input a motivic object, and contain methods to compute various sums and values related to the $L$-function of that object.

I'll start by writing two classes: LFunctionZeroSum_abstract, which will contain all the general methods that can apply to a zero sum estimator attached to any motivic $L$-function. The second class, LFunctionZeroSum_EllipticCurve, inherits from the abstract class, and contains the code specific to elliptic curve $L$-functions.

I have also added a method to the EllipticCurve_rational_field class in the sage/schemes/elliptic_curves/ell_rational_field.py file (the class modeling elliptic curves over the rationals) to access the analytic rank estimation functionality of the zero sum estimator.

Let's see the code in action. To download a copy yourself, say from within a project in cloud.sagemath.com, open up a terminal and type

~$git clone git://github.com/haikona/GSoC_2014.git This will download the code in the repo into a new folder GSoC_2014 in your current directory. CD into that directory, type make and hit enter to build. This will unfortunately take a couple hours to complete, but the good new is you'll only need to do that once. Alternatively, if you have an existing freshly-built copy of the sage source and good github-fu, you should be able to download just the relevant code and apply it, greatly speeding up the build time. Once your copy of sage containing the new LFunctionZeroSum code is built, fire up that copy of sage (e.g. type ./sage while in the GSoC_2014 directory; don't just type sage, as this runs the system-wide copy of sage - not the one we want). This command-line interface will have all the functionality of any other current copy of Sage, but with the extra methods and classes I've written. Let's start by estimating the rank of some elliptic curves: sage: E = EllipticCurve([0,1,1,-2,0]); E Elliptic Curve defined by y^2 + y = x^3 + x^2 - 2*x over Rational Field sage: E.rank(), E.conductor() (2, 389) sage: E.analytic_rank_bound() 2.0375000846 In the code above, I've defined an elliptic curve given by the Weierstrass equation$y^2 +y = x^3+x^2-2x$; for those of you in the know, this is the curve with Cremona label '389a', the rank 2 curve with smallest conductor. I've then printed out the rank of the curve, which is indeed 2. Then I've called my analytic_rank_bound() method on$E$, and it returns a value which is strictly greater than the analytic rank of$E$. Since the analytic rank of an elliptic curve is always a non-negative integer, we can conclude that the analytic rank of$E$is at most 2. How long did this rank estimation computation take? Thankfully Sage has a timing function to answer this question: sage: timeit('E.analytic_rank_bound()') 125 loops, best of 3: 3.33 ms per loop Neat; that was quick. However, this elliptic curve has a small conductor - 389, hence it's Cremona label - so computing with its$L$-function is easy. The great thing with the zero sum code is that you can run it on curves with really large conductors. Here we reproduce the commands above on the curve$y^2 + y = x^3 - 23737x + 960366$, which has rank 8 and conductor$N \sim 4.6\times 10^{14}$: sage: E = EllipticCurve([0,0,1,-23737,960366]); E Elliptic Curve defined by y^2 + y = x^3 - 23737*x + 960366 over Rational Field sage: E.rank(), E.conductor() (8, 457532830151317) sage: E.analytic_rank_bound() 8.51446122452 sage: timeit('E.analytic_rank_bound()') 125 loops, best of 3: 3.37 ms per loop So we see then that this zero sum code doesn't care very much about the size of the conductor of$E$; this is one of its huge plusses. There are of downsides, of course - but we'll save those for another post. Now let's look at the LFunctionZeroSum code. sage: E = EllipticCurve([23,-100]) sage: Z = LFunctionZeroSum(E); Z Zero sum estimator for L-function attached to Elliptic Curve defined by y^2 = x^3 + 23*x - 100 over Rational Field Right now we don't have too much beyond that which you can access from the EllipticCurve class. For one, we can compute the coefficients of the logarithmic derivative, since they are needed to compute the rank-estimating zero sum. We can also return and/or compute one or two other values associated to the zero sum class. As time goes on we'll flesh out more functionality for this class. sage: for n in range(1,11): ....: print(n,Z.logarithmic_derivative_coefficient(n)) ....: (1, 0) (2, 0.0) (3, -1.09861228867) (4, 0.0) (5, 1.28755032995) (6, 0) (7, -0.277987164151) (8, 0.0) (9, -0.366204096223) (10, 0) sage: Z.elliptic_curve() Elliptic Curve defined by y^2 = x^3 + 23*x - 100 over Rational Field sage: Z.elliptic_curve().rank() 1 sage: Z.rankbound(Delta=1.7,function="gaussian") 1.58647787024 All of this code is of course written to Sage spec. That means that every method written has documentation, including expected input, output, examples, and notes/warnings/references where necessary. You can access the docstring for a method from the command line by typing that method followed by a question mark and hitting enter. All my code will initially be written in Python. Our first goal is to replicate the functionality that has already been written by Jonathan Bober in c. As such we're not aiming for speed here; instead the focus is to make sure all the code is mathematically correct. Once that's up and running there are two natural directions to take the project: 1. Speed the code up. Rewrite key parts in Cython, so that computations run faster, and thus analytic rank can be estimated for curves of larger conductor. 2. Generalize the code. Write classes that model zero sum estimators for$L$-functions attached to eigenforms (those modular forms with Euler product expansions) of any level and weight, and allow for more types of sums to be computed. Ultimately write code that can be used to compute sums for any motivic$L\$-function.

I'm going to attack speeding up the code first, since the elliptic curve rank estimation functionality will probably see the most use. If there's time at the end of the project I can look to generalizing the code as much as I can.