Improve Height Functionality for SageMath - Google Summer of Code 2022

This summer, I worked on a Google Summer of Code (GSoC) project to improve height functionality for SageMath. I would like to thank my mentors Prof. Ben Hutz and Alexander Galarraga for helpful meetings and email exchanges. I would also like to thank Prof. Paul Fili for teaching me the basics of the Arakelov-Zhang pairing.

You can see my commits on GitHub.

Is it important and useful, or why should I care?

Height functions allow mathematicians to quantify the complexity of mathematical objects, such as rational points or the size of solutions to Diophantine equations in Diophantine geometry.

For instance, the classical or naive height over the rational numbers is the maximum of the numerators and denominators of the coordinates. For example, the height of \((3/9, 1/2)\) is \(3\).

For interested readers, Heights in Diophantine Geometry by Enrico Bombieri is really helpful.

What have I done?

I contributed to 8 tickets in five different components (algebra, algebraic geometry, dynamics, and number theory). Each ticket represents a separate task and contains the implementation, tests, and documentation:

I fixed a bug in the degree function in affine_morphism.py to get me started. This function returns the degree of the affine morphism. It now not only supports polynomial affine maps, but also rational ones as well.

A morphism from an affine scheme to an affine scheme is determined by rational functions that define what the morhism does on points in the ambient affine space.

In the past, the height of a dynamical system was incorrectly implemented as the maximum of the heights of the coefficients. It means that the code below would return \(25\), which is wrong.

sage: P.<x,y> = ProjectiveSpace(QQ, 1)
sage: f = DynamicalSystem([1/25*x^2 + 25/3*x*y + y^2, 1*y^2])
sage: exp(f.global_height())

Now we resort to the approach of treating the coefficients of all coordinate functions as a projective point, and take its height, which would give the correct answer \(625\).

Similarly to previous ticket, the height of a polynomial typically is not the maximum of the heights of the coefficients:

h = max([c.global_height(prec) for g in CoeffPolys for c in (g).coefficients()])

We again think of the height of the polynomial as a projective point (i.e., the height is independent of scaling).

h = max([g.global_height(prec) for g in CoeffPolys])

It means that for the following example:

sage: P.<x,y,z> = ProjectiveSpace(ZZ, 2)
sage: f = DynamicalSystem_projective([4*x^2 + 100*y^2, 210*x*y, 10000*z^2])

In the past it returned the incorrect value \(11.4075649493124\), and now it would output the correct value \(10.3089526606443\).

We added the support for height functions for polynomial on number fields, which means that, for instance, the following example is now valid:

sage: R.<x,y> = PolynomialRing(QQbar, 2)
sage: f = QQbar(i)*x^2 + 3*x*y
sage: f.global_height()
1.09861228866811

Other than global_height, I also implemented local_height and local_height_arch.

The global_height for polynomials would fail when passed the zero polynomial, since number_of_terms would return \(0\), and then it would create a projective space of dimension \(-1\):

sage: R.<x> = QQ[]
sage: f = 0 * x
sage: f.global_height()

Which meant that the above code would err. It now would correctly return \(0\).

I implemented logarithmic_embedding for number fields and relative number fields. Interested readers may see Definition 4.9.6 in A Course in Computational Algebraic Number Theory written by Henri Cohen.

Before this ticket, the points_of_bounded_height function for projective spaces would return points that are larger than the specified bound:

B = 3
K.<v> = QuadraticField(3)
P.<x,y,z> = ProjectiveSpace(K,2)
for Q in P.points_of_bounded_height(bound=B):
    if exp(Q.global_height()) > B + 0.001:
        print(Q,exp(Q.global_height()))

If you run the above code, it would return a lot of unnecessary points whose heights are larger than \(3\).

With the help of Dr. David Krumm’s paper and code, we successfully resolved this issue.

Prof. Fili wrote the original documentation and function definition many years ago. Some of the functions used and coding conventions might be slightly outdated, so I help to update it.

What happens after the coding period?

After the official coding period, I hope continue to contribute to open-source software and SageMath. I will implement the height functions for projective subvarieties as well.