This feed contains pages in the "sage" category.
Craig Citro and I submitted a short communication to the Third International Congress on Mathematical Software, and we recently found out it was accepted. It will eventually appear in the Springer Lecture Notes in Computer Science, but in the mean time you can find it on the arXiv: Enumerating Galois representations in Sage.
The paper gives a quick overview of the algorithm and some theoretical results that we obtained, and discusses the Sage implementation and some numerical results. Proofs, more motivation and more details will be part of the preprint we are still working on, but which should be out later this year.
The conference is in mid-September in Kobe, Japan, which should be quite exciting.
A few days ago I put a new preprint on the arXiv, titled Distinguishing Hecke eigenforms. This originated in a rather roundabout way (as many research projects do) from the work Craig Citro and I are doing on enumerating Galois representations. When I gave a talk about this at PRIMA, I mentioned that we had to somehow tell apart two eigenforms of possibly distinct weights by looking at a predictable finite number of Fourier coefficients. Mark Watkins was in the audience and remarked that he had seen a paper by Ram Murty doing something similar.
Murty's paper (Congruences between modular forms) has a wealth
of interesting results and ideas condensed in a mere 10 pages. It
seems that we cannot use the results for our original mod p
problem. But my attention was caught by Theorem 4, which is the
corresponding result in characteristic zero. It says that if
f and g are newforms of different weights on Gamma0(N), then
there exists some
such that
the n-th Fourier coefficients of f and g are different.
Murty's proof is a beautiful argument based on the relation between the Hecke operators T(p^2) and T(p) for a prime p. Unfortunately, it uses an estimate for the smallest prime p not dividing a given integer N, and this estimate does not hold for all N (it misses a few small N's). Of course, one can restate the Theorem as holding for large enough N, or make the explicit upper bound into an O() asymptotic, but for me the charm of the statement was precisely its very explicit nature.
My preprint gives such an explicit bound that holds for all
values of N, namely
; this is based on good explicit estimates on the
Chebyshev theta-function proved by Pierre Dusart in his PhD
thesis. I was curious to see how good the bound is, so I
wanted to test it "in the wild".
Naturally, I used Sage for this. The plan was to fix a level N, compute all the newforms on a large range of weights, and then compare their q-expansions to see how many Fourier coefficients need to be checked to distinguish the forms. I played around with this with some small weights and N=1, and noticed that a_2 seemed to suffice to tell apart the forms. (Note, this is better than the bound of 4 given in the preprint.) So I decided to focus on the case N=1 for a couple of reasons:
- it is very fast to work with high weight forms in level 1, thanks to the Victor Miller basis
- if I assume Maeda's conjecture, I only have to compute the characteristic polynomial of the Hecke operator T_2 for each weight; in fact, I simplified this further by only computing the trace of the Hecke matrix, which is much faster!
With all this, I was able to run through all weights up to 10000 in less than a week. All traces are distinct, which means that all characteristic polynomials are distinct, which (assuming Maeda's conjecture) means that all a_2's are distinct.
The Sage source code and the data computed (traces of the Hecke matrices of T_2 up to weight 10000) can be found in this directory.
(The ideas in this post are based on a worksheet by Jason Grout. Thanks Jason!)
Sage 2D plots use the excellent library matplotlib as a backend, which gives us beautiful publication-quality graphics. Sage only exposes a small subset of matplotlib's capabilities, and this subset is generally sufficient in day-to-day work. However, especially if you are preparing a graph for a class or a presentation, you might need to tweak things to get it to look "just right".
I recently had to produce some graphs of trigonometric functions for my calculus class, and the default tick locations and labels are not really well-suited. Here is one example (code and graph):
var('x')
p = plot(2*sin(x+pi/3)+2, (x, -pi/3, 5*pi/3))
p.save('2sinx_pi_3_2_original.png')
There is too much numerical information displayed, and a lot of it is
just distracting for this function. I would much rather just see some
multiples of (say)
marked along the x-axis,
and a few significant numbers marked along the y-axis. For this we need
to access matplotlib directly. Here is the new code, and the resulting graph:
var('x')
p = plot(2*sin(x+pi/3)+2, (x, -pi/3, 5*pi/3))
fig = p.matplotlib(axes_labels=['$x$', '$y$'])
from matplotlib.backends.backend_agg import FigureCanvasAgg
fig.set_canvas(FigureCanvasAgg(fig))
axes = fig.get_axes()[0]
axes.minorticks_off()
axes.set_xticks([float((j-1/3)*pi) for j in range(0,3)])
axes.set_xticklabels(['$-\pi/3$', '$2\pi/3$', '$5\pi/3$'])
axes.set_yticks([float(2), float(4)])
fig.suptitle('$2\,\sin(x+\pi/3)+2$', color='navy')
fig.savefig('2sinx_pi_3_2_matplotlib.png')
One of the reasons for the popularity of modular forms in number theory is that they are highly computable objects. There is a variety of ways in which you can get your hands on explicit examples (see for instance William Stein's Modular forms: a computational approach or Lloyd Kilford's Modular forms: a classical and computational introduction). And, of course, you can (and probably should) use Sage to generate and play with such examples.
One of the reasons for the lesser popularity of various generalisations of modular forms is that they currently lack good computational infrastructure. The good news is that this is a fairly active field of research. Thinking specifically of Siegel modular forms, there are rumours of an upcoming paper (and code) by Raum-Ryan-Skoruppa-Tornaría. While we wait for this, there is a recent preprint by Martin Raum with the descriptive title Efficiently generated spaces of classical Siegel modular forms and the Böcherer conjecture. More precisely, its algorithmic focus is on genus 2, level 1, scalar-valued Siegel modular forms of high weight and with rational coefficients, and he conjectures the existence of a simple, nice-looking basis for these vector spaces (which we are encouraged to think of as an analogue of the Victor Miller basis for classical modular forms). He checked the conjecture computationally up to weight 172 (which is quite impressive) by using Sage.
This is excellent news, since the Victor Miller basis is a particularly efficient method for computing with classical modular forms, and it is wonderful to have this in the Siegel context. He shows off some of the power of this approach with a few interesting applications.
The newest release of Sage is now out. See this announcement for full details, including a list of tickets closed.
There's one improvement I'm particularly happy about: Dima Pasechnik upgraded the version of GAP included in Sage to the latest upstream, namely 4.4.12. The previous version (4.4.10) was seriously outdated and had several known issues.
Thanks to Dima for the work in upgrading the spkg, and to David Joyner, William Stein, Minh Van Nguyen, and Robert Bradshaw for reviewing the various tickets involved in this upgrade.
It is perhaps not so surprising that modular forms mod p do not always behave the way one would expect based on properties of modular forms in characteristic 0. Here is an example of such a discrepancy. (This is of course "well-known", and as with a lot of "well-known" things, it's not always easy to find a reference.)
It is a classical result that the space of modular forms
has a basis of Hecke
eigenforms. (See for instance Section 4.2.3 in Kilford's Modular forms:
a classical and computational introduction.) If you combine this
with the q-expansion principle, you get a multiplicity one result, i.e.
the eigenspace associated to any system of Hecke eigenvalues occurring in
M is one-dimensional. There are similar results for level N, where
one needs to differentiate between oldforms and newforms. (See for
instance Section 5.8 in Diamond-Shurman's A first course in modular forms.)
Let's now see what happens when we instead work with
,
the space of modular forms mod p. It turns out that this space need
not have a basis of Hecke eigenforms. Here is a sketch of proof:
suppose these spaces have a basis of Hecke eigenforms, then each eigensystem
has multiplicity one by the q-expansion principle. But a theorem of
Serre-Tate says that there are only finitely many Hecke eigensystems
mod p (all weights put together). Say this number is H. Choosing a
weight k such that the space of modular forms of weight k has
dimension greater than H gives us more than H eigensystems in weight
k, contradiction.
The argument tells us where to look for such situations. I'll restrict my attention to cusp forms, but this is not important. If p is 5, then there are only 4 Hecke eigensystems in all weights. So taking a space of dimension at least 5 would do the trick, and indeed the space of cusp forms of weight 60 works. But it is possible to find smaller such examples (of course, the space must be at least two-dimensional for this to work). For p=5, the earliest example comes up in weight 36. Sage makes it easy to explore this as follows. First, we need a basis for the space of cusp forms mod 5 of weight 36, and we'll use the corresponding Victor Miller basis:
sage: bas = victor_miller_basis(k=36, prec=20, cusp_only=True)
sage: bas_mod5 = [ f.change_ring(GF(5)) for f in bas ]
The second line reduces the original Victor Miller basis (which lives over
the integers) modulo 5. Now we figure out the matrix of the Hecke
operator
on this basis. This should just be a
matter of doing hecke_operator_on_basis(bas_mod5, 2, 36), but at the
moment that doesn't work over finite fields (for silly reasons, and this
should be an easy bug to fix).
No matter, we can just do it by hand:
sage: f1, f2, f3 = bas_mod5; print f1; print f2; print f3
q + 3*q^4 + 2*q^6 + 2*q^9 + 2*q^11 + O(q^12)
q^2 + 4*q^4 + 2*q^5 + q^6 + 4*q^7 + 4*q^8 + 3*q^9 + 2*q^10 + O(q^12)
q^3 + 3*q^4 + 4*q^5 + 2*q^6 + q^7 + 3*q^8 + q^9 + 4*q^10 + O(q^12)
sage: hecke_operator_on_qexp(f1, 2, 36)
q^2 + 2*q^3 + O(q^6)
And herein lies the beauty of the Victor Miller basis: we immediately see
that the last result is really
. Similarly:
sage: hecke_operator_on_qexp(f2, 2, 36)
q + 4*q^2 + q^3 + 2*q^4 + 2*q^5 + O(q^6)
sage: hecke_operator_on_qexp(f3, 2, 36)
3*q^2 + 2*q^3 + 3*q^4 + 4*q^5 + O(q^6)
Now we can write down the matrix of
and see what
happens:
sage: t2 = matrix(GF(5), [[0, 1, 0], [1, 4, 3], [2, 1, 2]]); t2
[0 1 0]
[1 4 3]
[2 1 2]
sage: t2.jordan_form()
[4|0 0]
[-+---]
[0|1 1]
[0|0 1]
And there you have it: since the matrix is not diagonalisable, this
space of cusp forms cannot even have a basis of eigenvectors for
, let alone a basis of eigenvectors for all
the Hecke operators.
Another "small" example is p=67, k=32, where the space of cusp
forms is two-dimensional and the matrix of
has
Jordan normal form
sage: t2 = matrix(GF(67), [[0, 1], [5, 28]])
sage: t2.jordan_form()
[14 1]
[ 0 14]

