A<y,x> := PolynomialRing(GF(2),2);
P,homogenize := Homogenization(A);
print("f := an improved polynomial for X1(39)");
f := y^2*(y+1)*x^17+(y^2+y+1)^2*y^2*x^16+y^5*(y+1)*x^15+(y^3+y^2+1)^2*y^3*(y+1)*x^14+y^2*(y^8+y^7+y^3+y+1)*(y+1)*x^13+(y^2+y+1)*y^2*(y^5+y^4+y^2+y+1)*(y+1)^2*x^12+(y^6+y^5+y^3+y^2+1)*(y^2+y+1)^2*(y+1)*x^11+(y^7+y^13+y^3+y^2+y^10+y^5+y^4+y^12+1)*x^10+(y^5+y^2+1)*(y^2+y+1)*y*(y^3+y+1)*(y+1)^3*x^9+(y^2+y+1)^2*(y+1)^8*x^8+(y^2+y+1)^2*y^2*(y^3+y+1)*(y+1)^2*x^7+(y^10+y^7+y^5+y^3+y^2+y+1)*(y+1)*x^6+(y^3+y+1)*(y^5+y^4+y^3+y+1)*(y+1)^2*x^5+(y^9+y^4+1)*y*(y+1)^3*x^4+y^6*(y^4+y+1)*(y+1)^4*x^3+y*(y^6+y^4+y^3+y+1)*(y+1)^5*x^2+y*(y+1)^5*(y^5+y^4+y^3+y^2+1)*x+y*(y+1)^8 ;

f := homogenize(f);
XF2 := Scheme(ProjectiveSpace(P),f);
FF := FunctionField(XF2);
AFF := AlgorithmicFunctionField(FF);
plc1 := Places(AFF,1);
divgrp := DivisorGroup(AFF);
div1 := [divgrp ! i : i in plc1];
cuspsum := &+ div1;
load "function_degrees.m";

print("The number of places of degrees 1-9:");
[#Places(AFF,i) : i in [1..9]];

// Our goal is to show that X1(39) has no non-constant functions of degree <14
// over F2 and hence over Q.

// Say f is a function of degree <= 13, since f^(-1)({0,1,infinity}) contains
// all 12 rational points, by the pigeon hole principle we may assume that
// f^(-1)({infinity} contains at least 4 distinct rational points, and so
// the remaining polar-part of f has degree at most 9.

// This contains one place of each diamond-orbit of rational places. In
// this case there is only one such orbit.
orbs := [plc1[1]];


// Cover: a place of degree 2, and the multiplicities of the degree 1
// places are 2,2,2,.. and one <= 5.
s := &cat[FunctionDegrees(2 * cuspsum + 3 * plc1[1] + Q) : Q in Places(AFF,2)];
s;

// Cover: two place of degree 2, and the multiplicities of the degree 1
// places are 2,2,2,.. and one 3
s := &cat[FunctionDegrees(2 * cuspsum + 1 * plc1[1] + Q1+Q2) : Q1 in Places(AFF,2), Q2 in Places(AFF,2)];
s;

// Covered:
//
// [[], [   2, 2, 2, 2, 5]]

// [[], [2, 2, 2, 2, 2, 3]]
// [[], [2, 2, 2, 2, 2, 2]]

// [[2], [   2, 2, 2, 5]]

// [[2], [2, 2, 2, 2, 3]]
// [[2], [2, 2, 2, 2, 2]]

// [[2, 2], [2, 2, 2, 3]]
// [[2, 2], [2, 2, 2, 2]]





// Degree >1 places: []
// Rat-places: [2, 2, 3, 7] (only multiplicities >1 are listed).
s := {(cuspsum + 1*Q1+1*Q2+2*Q3+6*Q4) : Q1 in plc1, Q2 in plc1, Q3 in plc1, Q4 in orbs};

// Degree >1 places: []
// Rat-places: [3, 3, 5, 5] (only multiplicities >1 are listed).
s := s join {(cuspsum + 2*Q1+2*Q2+4*Q3+4*Q4) : Q1 in plc1, Q2 in plc1, Q3 in plc1, Q4 in orbs};

// Degree >1 places: []
// Rat-places: [2, 2, 4, 4, 4] (only multiplicities >1 are listed).
s := s join {(cuspsum + 1*Q1+1*Q2+3*Q3+3*Q4+3*Q5) : Q1 in plc1, Q2 in plc1, Q3 in plc1, Q4 in plc1, Q5 in orbs};
print "The number of RR-computations to be done for this case is:",
#s;
s := &cat[FunctionDegrees(D) : D in s];
if not s eq [] then s := Min(s); end if;
s;

// Degree >1 places: [2]
// Rat-places: [3, 3, 3, 4] (only multiplicities >1 are listed).
s := {(cuspsum + P1 + 2*Q1+2*Q2+2*Q3+3*Q4) : P1 in Places(AFF,2), Q1 in plc1, Q2 in plc1, Q3 in plc1, Q4 in orbs};
print "The number of RR-computations to be done for this case is:",
#s;
s := &cat[FunctionDegrees(D) : D in s];
if not s eq [] then s := Min(s); end if;
s;

// Degree >1 places: [6]
// Rat-places: [2, 2, 2] (only multiplicities >1 are listed).
s := {(cuspsum + P1 + 1*Q1+1*Q2+1*Q3) : P1 in Places(AFF,6), Q1 in plc1, Q2 in plc1, Q3 in orbs};
print "The number of RR-computations to be done for this case is:",
#s;
s := &cat[FunctionDegrees(D) : D in s];
if not s eq [] then s := Min(s); end if;
s;

// Degree >1 places: [8]
// Rat-places: [2] (only multiplicities >1 are listed).
s := {(cuspsum + P1 + 1*Q1) : P1 in Places(AFF,8), Q1 in orbs};
print "The number of RR-computations to be done for this case is:",
#s;
s := &cat[FunctionDegrees(D) : D in s];
if not s eq [] then s := Min(s); end if;
s;

// Degree >1 places: [9]
// Rat-places: [] (only multiplicities >1 are listed).
s := {(cuspsum + P1) : P1 in Places(AFF,9)};
print "The number of RR-computations to be done for this case is:",
#s;
s := &cat[FunctionDegrees(D) : D in s];
if not s eq [] then s := Min(s); end if;
s;

// Degree >1 places: [2, 2]
// Rat-places: [2, 2, 4] (only multiplicities >1 are listed).
s := {(cuspsum + P1+P2 + 1*Q1+1*Q2+3*Q3) : P1 in Places(AFF,2), P2 in Places(AFF,2), Q1 in plc1, Q2 in plc1, Q3 in orbs};

// Degree >1 places: [2, 2]
// Rat-places: [2, 3, 3] (only multiplicities >1 are listed).
s := s join {(cuspsum + P1+P2 + 1*Q1+2*Q2+2*Q3) : P1 in Places(AFF,2), P2 in Places(AFF,2), Q1 in plc1, Q2 in plc1, Q3 in orbs};
print "The number of RR-computations to be done for this case is:",
#s;
s := &cat[FunctionDegrees(D) : D in s];
if not s eq [] then s := Min(s); end if;
s;

// Degree >1 places: [2, 6]
// Rat-places: [2] (only multiplicities >1 are listed).
s := {(cuspsum + P1+P2 + 1*Q1) : P1 in Places(AFF,2), P2 in Places(AFF,6), Q1 in orbs};
print "The number of RR-computations to be done for this case is:",
#s;
s := &cat[FunctionDegrees(D) : D in s];
if not s eq [] then s := Min(s); end if;
s;

// Degree >1 places: [2, 2, 2]
// Rat-places: [2, 2, 2] (only multiplicities >1 are listed).
s := {(cuspsum + P1+P2+P3 + 1*Q1+1*Q2+1*Q3) : P1 in Places(AFF,2), P2 in Places(AFF,2), P3 in Places(AFF,2), Q1 in plc1, Q2 in plc1, Q3 in orbs};
print "The number of RR-computations to be done for this case is:",
#s;
s := &cat[FunctionDegrees(D) : D in s];
if not s eq [] then s := Min(s); end if;
s;

// Degree >1 places: [2, 2, 2, 2]
// Rat-places: [2] (only multiplicities >1 are listed).
s := {(cuspsum + P1+P2+P3+P4 + 1*Q1) : P1 in Places(AFF,2), P2 in Places(AFF,2), P3 in Places(AFF,2), P4 in Places(AFF,2), Q1 in orbs};
print "The number of RR-computations to be done for this case is:",
#s;
s := &cat[FunctionDegrees(D) : D in s];
if not s eq [] then s := Min(s); end if;
s;
