alkahest.pari
Optional PARI/GP interop: exact objects from PARI, checked by Alkahest.
Alkahest's number-field layer has arithmetic only: no ring of integers, class
group, units, prime-ideal factorisation or Galois group; it has no elliptic
curve invariants (conductor, a_p, rank, L-values) and no modular
forms. PARI/GP has all of these. This module asks PARI for them and
returns the answers as exact Alkahest objects (Python int /
Fraction, experimental.NumberFieldElement,
ArbBall), then re-checks every cheap consequence of the
answer with Alkahest's own exact arithmetic and records what was and was
not checked in a verification mapping. A PARI answer that contradicts a
check raises PariError (E-PARI-003) instead of being returned.
Licence boundary
PARI/GP is GPL-licensed. Alkahest is not, and never links, bundles, imports
at import alkahest time or redistributes PARI. This module is pure
Python, loads a PARI binding lazily on first use, and works only if you
have installed one yourself:
cypari2(needs a system libpari;pip install cypari2builds against it), orcypari(the SnapPy project's binding; its wheels carry their own libpari —pip install cypari).
Nothing in Alkahest's wheels, Rust crates or default dependencies depends on
either. Without a binding, available() is False and every
function raises PariUnavailable (E-PARI-001). A gp
subprocess is not supported. If you redistribute an application that
installs a PARI binding next to Alkahest, the GPL applies to that
combination; Alkahest itself is unaffected.
Trust levels
Each result states how far it is trusted, in plain strings:
certified
PARI's answer carries a proof (bnfcertify) or Alkahest verified it
outright.
grh_conditional
PARI's class group / units are correct only under the Generalised Riemann
Hypothesis (bnfinit without bnfcertify).
proven / numerical / bounds_only
For elliptic-curve ranks and L-values; see
elliptic_curve_invariants().
Error codes
E-PARI-001 no PARI binding installed; E-PARI-002 unsupported input;
E-PARI-003 a PARI answer failed Alkahest's verification; E-PARI-004
PARI itself raised.
A Galois orbit of normalised Hecke eigenforms of the new subspace.
field is None for rational eigenvalues, otherwise the
NumberField Q[y]/(polynomial) containing them. coefficients
is [a_1, ..., a_nmax] with a_n an int / Fraction (rational
orbit) or a NumberFieldElement.
What elliptic_curve_invariants() returns.
ainvs
(a1, a2, a3, a4, a6) as Fraction s.
discriminant, conductor
int s (discriminant is of the given model).
ap
{p: a_p} for primes p <= ap_bound (a_p for bad p is the
PARI convention 0/±1).
torsion
{"order", "structure", "generators"}; generators are exact
(x, y) Fraction pairs on the given model.
root_number
±1.
analytic_rank / analytic_rank_status
PARI's numerical analytic rank; status "proven" when Alkahest's own
series evaluation shows the leading L-value is non-zero for rank 0
or 1, otherwise "numerical".
l_value
L(E, 1) (rank 0) or L'(E, 1) (rank 1; L(E,1) = 0 exactly
by the functional equation) as an ArbBall
computed from a_n with a rigorous truncation bound, or None
when the analytic rank is >= 2 (value not enclosed).
mw_rank_bounds / mw_rank_status
(lower, upper) from ellrank (2-descent); status "proven"
when they agree, else "bounds_only" (the true rank may be
anywhere in the range; only conditional statements such as BSD
give more).
mw_points
Independent points of infinite order found by ellrank. They
need not generate the Mordell–Weil group (no saturation).
Cusp forms S_k(Gamma_0(N)) with trivial character.
dimension
dim S_k(Gamma_0(N)) (full space, old forms included).
basis
dim lists [a_0, ..., a_nmax] of exact Fraction / int
q-expansion coefficients (PARI's basis; not an eigenbasis).
new_dimension / orbits
New-subspace dimension and its Hecke eigenform orbits.
What number_field_invariants() returns.
fieldThe
NumberFieldthe data is expressed in.discriminantd_K, anint.signature(r1, r2).integral_basisA
Z-basis of the ring of integers asNumberFieldElements.class_number, class_grouphand the cyclic invariants[d1, d2, ...](d1 | d2 | ...) orNonewhenclass_group=False.torsion_units(w, zeta): the order of the roots of unity inKand a generator.fundamental_unitsr1 + r2 - 1multiplicatively independent units (NumberFieldElement).regulatorPARI's decimal string for the regulator (not an exact object).
primes{p: [PrimeIdeal, ...]}for the primes requested.galois{"order", "parity", "name", "transitive_index"}orNone.certification"certified"(bnfcertifysucceeded:h, units, regulator are proven),"grh_conditional"(not run, too expensive, or failed), or"not_computed"whenclass_group=False.verification{check name: True}for every check Alkahest ran, and a"not_checked"list naming what rests on PARI alone.
A prime ideal P = (p, alpha) above a rational prime p.
e is the ramification index, f the residue degree, norm = p**f
and generators = (p, alpha) a two-element presentation with alpha a
NumberFieldElement of the field passed in.
Base error of pari; .code is the stable E-PARI-NNN.
True when a PARI binding (cypari2 or cypari) can be loaded.
Name of the binding in use ("cypari2" / "cypari") or None.
pari.elliptic_curve_invariants(
ainvs: Sequence[Any],
*,
ap_bound: int=100,
rank: bool=True,
l_value: bool=True
) → EllipticCurveData
Conductor, a_p, torsion, rank and L-value of an elliptic curve over Q.
The curve is y^2 + a1 xy + a3 y = x^3 + a2 x^2 + a4 x + a6.
ainvs[a1, a2, a3, a4, a6]or[a4, a6](integers orFractions; the curve must be non-singular). Non-integral coefficients are refused withE-PARI-002.ap_boundReturn
a_pfor all primesp <= ap_bound.rankRun
ellrank(2-descent) andellanalyticrank.l_valueEvaluate the leading
L-value as a ball.
discriminant is recomputed from the b-invariants; the conductor's
primes must divide it; a_p is recounted by brute-force point counting
for good primes p <= 1000 and checked against Hasse; each torsion
generator is checked to lie on the curve and its order is recomputed in
Alkahest's own Pic^0 (FunctionField / DivisorClass) on the
isomorphic short model — it must equal the order PARI claims (this
certifies the listed points, not that no further torsion exists); the
analytic rank must match the parity of the root number; L(E,1) (or
L'(E,1)) is recomputed from the a_n with a rigorous truncation
bound and compared with PARI's lfun; each Mordell–Weil point lies on
the curve and is shown to have infinite order by Pic^0.
analytic_rank_status / mw_rank_status as described on
EllipticCurveData; modularity (the theorem that L(E,s) has
the functional equation used above) is assumed.
>>> from alkahest import pari
>>> e = pari.elliptic_curve_invariants([0, -1, 1, -10, -20]) # 11a1 # doctest: +SKIP
>>> e.conductor, e.torsion["order"], e.analytic_rank # doctest: +SKIP
(11, 5, 0)q-expansions and Hecke eigenvalues of S_k(Gamma_0(N)) via PARI's mf* suite.
N, kLevel
N >= 1and integer weightk >= 1(trivial character).nmaxNumber of coefficients to return (
a_0..a_nmax/a_1..a_nmax).
Returns exact coefficients: int / Fraction for the basis and for
rational eigenforms, NumberFieldElement in the orbit's coefficient
field otherwise.
Every eigenform is re-checked in exact arithmetic: a_1 = 1, full
multiplicativity and the prime-power Hecke recursion
a_{p^{r+1}} = a_p a_{p^r} - [p ∤ N] p^{k-1} a_{p^{r-1}} for all indices
<= nmax; each a_n is an algebraic integer (integral minimal
polynomial); the orbit degrees sum to dim S_k^new. For (N, k) = (1, 12)` the form is compared with `q prod (1 - q^n)^24
(Ramanujan's tau). A failure raises E-PARI-003. The list of
orbits being complete is PARI's claim (not re-derived).
>>> from alkahest import pari
>>> pari.modular_forms(1, 12).basis[0][:4] # tau(n) # doctest: +SKIP
[0, 1, -24, 252]pari.number_field_invariants(
field_or_poly: Any,
*,
primes: Sequence[int]=(),
class_group: bool=True,
galois: bool=True,
certify: bool | str='auto'
) → NumberFieldData
Ring of integers, class group, units, prime splitting and Galois group of a number field.
field_or_polyAn
experimental.NumberField, or an ascending integer coefficient list of a monic irreducible polynomial.primesRational primes whose prime-ideal factorisation to return.
class_groupRun
bnfinit(class group, units, regulator). Disable for large discriminants.galoisCompute the Galois group with
polgalois(degree <= 7 in a stock PARI; refused withE-PARI-002above that unless thegaldatapackage is installed, in which case PARI answers up to degree 11).certifyTruealways runsbnfcertify(can be very slow),Falsenever,"auto"(default) runs it when degree <= 6 and|d_K| < 10**15. The outcome decidescertification.
All of the following are recomputed in Alkahest's exact arithmetic and a
failure raises E-PARI-003: the integral basis spans an order of
discriminant d_K (Gram determinant of Tr(w_i w_j)), is closed under
multiplication, consists of algebraic integers, disc(f) = index^2 d_K,
d_K has the right sign and residue mod 4; every unit has norm ±1
and the torsion generator has the stated order; each prime ideal's
two-element presentation spans a lattice of index exactly p**f,
sum e f = n, and p | d_K exactly when some e > 1; the Galois
parity matches whether disc(f) is a square; for imaginary quadratic
fields h is recounted from reduced binary quadratic forms.
Maximality of the order, fundamentality of the units and the value of
the class group are not re-derived (they are listed under
verification["not_checked"]); they hold unconditionally only when
certification == "certified".
- PariUnavailable
No PARI binding (
E-PARI-001).- PariError
E-PARI-002for non-monic or reducible input,E-PARI-003for a failed check,E-PARI-004when PARI itself fails.
>>> from alkahest import pari
>>> d = pari.number_field_invariants([5, 0, 1]) # Q(sqrt(-5)) # doctest: +SKIP
>>> d.discriminant, d.class_number # doctest: +SKIP
(-20, 2)The PARI library version string, or None when unavailable.
Ramanujan's tau(n) from the product q prod (1 - q^m)^24, exactly.
Pure Python (no PARI); the independent oracle used to check Delta.