Skip to content

Commit

Permalink
Merge pull request #6290 from JohnCremona/ECNF-BSD
Browse files Browse the repository at this point in the history
ECNF:  BSD invariants and display
  • Loading branch information
roed314 authored Dec 9, 2024
2 parents 7e28859 + 81ac07e commit fef99a9
Show file tree
Hide file tree
Showing 2 changed files with 145 additions and 14 deletions.
110 changes: 100 additions & 10 deletions lmfdb/ecnf/WebEllipticCurve.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
from flask import url_for
from urllib.parse import quote
from markupsafe import Markup, escape
from sage.all import (Infinity, PolynomialRing, QQ, RDF, ZZ, KodairaSymbol,
from sage.all import (Infinity, PolynomialRing, QQ, RDF, ZZ, RR, KodairaSymbol,
implicit_plot, plot, prod, rainbow, sqrt, text, var)
from lmfdb import db
from lmfdb.utils import (encode_plot, names_and_urls, web_latex, display_knowl,
Expand Down Expand Up @@ -494,7 +494,8 @@ def make_E(self):
self.mw_struct = "unknown"

# Torsion
self.ntors = web_latex(self.torsion_order)
BSDntors = self.torsion_order
self.ntors = web_latex(BSDntors)
self.tr = len(self.torsion_structure)
if self.tr == 0:
self.tor_struct_pretty = "$0$"
Expand Down Expand Up @@ -563,18 +564,28 @@ def make_E(self):
self.bsd_status = "missing_gens"

# Regulator only in conditional/unconditional cases, or when we know the rank:
BSDReg = None
if self.bsd_status in ["conditional", "unconditional"]:
if self.ar == 0:
self.reg = web_latex(1) # otherwise we only get 1.00000...
BSDReg = 1
self.reg = self.NTreg = web_latex(BSDReg) # otherwise we only get 1.00000...
else:
try:
self.reg = web_latex(self.reg)
R = self.reg
BSDReg = R * K.degree()**self.rank
self.reg = web_latex(R)
self.NTreg = web_latex(BSDReg)
except AttributeError:
self.reg = "not available"
self.NTreg = "not available"
elif self.rk != "not available":
self.reg = web_latex(self.reg) if self.rank else web_latex(1)
R = self.reg
BSDReg = R * K.degree()**self.rank
self.reg = web_latex(R) if self.rank else web_latex(1)
self.NTreg = web_latex(BSDReg) if self.rank else web_latex(1)
else:
self.reg = "not available"
self.NTreg = "not available"

# Generators
try:
Expand All @@ -585,17 +596,31 @@ def make_E(self):
self.gens = []
self.gens_and_heights = []

# Global period
# Global period -- see issue #5409 for why we multiply by
# 2**nc in most cases. However, data computed after
# 2024-07-09 (including all data for imaginary quadratic
# fields of absolute discriminant > 600 as well as some larger
# conductors for other IQFs) already has the extra factor of
# 2. As a fail-safe until we fix the data in all cases, we
# will test (using the BSD formula) whether to remove the
# factor of 2 added here.
BSDomega = None
try:
self.omega = web_latex(self.omega)
BSDomega = self.omega
nc = self.signature[1] # number of complex places
if nc:
BSDomega *= 2**nc
self.omega = web_latex(BSDomega)
except AttributeError:
self.omega = "not available"

# L-value
BSDLvalue = None
try:
r = int(self.analytic_rank)
# lhs = "L(E,1) = " if r==0 else "L'(E,1) = " if r==1 else "L^{{({})}}(E,1)/{}! = ".format(r,r)
self.Lvalue = web_latex(self.Lvalue)
BSDLvalue = self.Lvalue
self.Lvalue = web_latex(BSDLvalue)
except (TypeError, AttributeError):
self.Lvalue = "not available"

Expand All @@ -607,14 +632,79 @@ def make_E(self):
self.tamagawa_factors = r'\cdot'.join(cp_fac)
else:
self.tamagawa_factors = None
self.tamagawa_product = web_latex(prod(tamagawa_numbers,1))
BSDprodcp = prod(tamagawa_numbers,1)
self.tamagawa_product = web_latex(BSDprodcp)

# Analytic Sha
BSDsha = None
try:
self.sha = web_latex(self.sha) + " (rounded)"
BSDsha = self.sha
self.sha = web_latex(BSDsha) + " (rounded)"
except AttributeError:
self.sha = "not available"

# Check analytic Sha value compatible with formula in the knowl (see issue #5409)

BSDrootdisc = RR(K.discriminant().abs()).sqrt()
BSDok = True
if BSDLvalue and BSDsha and BSDReg and (self.rank is not None):
BSDsha_numerator = BSDrootdisc * BSDntors**2
BSDsha_denominator = BSDReg * BSDomega * BSDprodcp
BSDsha_from_formula = BSDLvalue * BSDsha_numerator / BSDsha_denominator
BSDsha_from_formula_rounded = BSDsha_from_formula.round()
BSDok = (BSDsha_from_formula_rounded == BSDsha) and ((BSDsha_from_formula_rounded -BSDsha_from_formula).abs() < 0.001)
#print(f"{BSDsha_from_formula=}")
#print(f"{BSDsha_from_formula_rounded=}")
#print(f"{BSDsha=}")
#print(f"{BSDok=}")
if not BSDok:
# this means that we doubled BSDomega when we should
# not have, so BSDsha_denominator is doubled and
# BSDsha_from formula is halved
print(f"BSD normalization: adjusting Omega for {self.label}: stored Sha = {BSDsha} but formula gives {BSDsha_from_formula}")
BSDok = ((BSDsha/BSDsha_from_formula)-2).abs() < 0.01
if not BSDok:
print(f"BSD normalization issue with {self.label}: stored Sha = {BSDsha} but formula gives {BSDsha_from_formula}")
BSDomega /= 2
BSDsha_denominator /= 2
BSDsha_from_formula *= 2
BSDsha_from_formula_rounded = BSDsha_from_formula.round()
BSDLvalue_from_formula = BSDsha * BSDsha_denominator / BSDsha_numerator
self.BSDsha = web_latex(BSDsha_from_formula)
self.BSDLvalue = web_latex(BSDLvalue_from_formula)

# The BSD formula for display

dot = '\\cdot'
approx = '\\approx'
eq_query = '\\overset{?}{=}'
frac = '\\frac'
Sha = '\\# &#1064;(E/K)'
Om = '\\Omega(E/K)'
Reg = '\\mathrm{Reg}_{\\mathrm{NT}}(E/K)'
prodcp = '\\prod_{\\mathfrak{p}} c_{\\mathfrak{p}}'
tors2 = '\\#E(K)_{\\mathrm{tor}}^2'
rootD = '\\left|d_K\\right|^{1/2}'

lder_name = rf"L^{{({r})}}(E/K,1)/{r}!" if r>=2 else "L'(E/K,1)" if r else "L(E/K,1)"
lhs_num = rf'{Sha} {dot} {Om} {dot} {Reg} {dot} {prodcp}'
lhs_den = rf'{tors2} {dot} {rootD}'
lhs = rf'{frac}{{ {lhs_num} }} {{ {lhs_den} }}'
rhs_num = rf'{BSDsha} {dot} {BSDomega:0.6f} {dot} {BSDReg} {dot} {BSDprodcp}'
if r:
rhs_num = rf'{BSDsha} {dot} {BSDomega:0.6f} {dot} {BSDReg:0.6f} {dot} {BSDprodcp}'
rhs_den = rf'{{{BSDntors}^2 {dot} {BSDrootdisc:0.6f}}}'
rhs = rf'{frac}{{ {rhs_num} }} {{ {rhs_den} }}'
self.bsd_formula = rf'{BSDLvalue:0.9f} {approx} {lder_name} {eq_query} {lhs} {approx} {rhs} {approx} {BSDLvalue_from_formula:0.9f}'

else:
self.BSDsha = "not available"
self.BSDLvalue = "not available"
self.bsd_formula = None

if not BSDok: # don't display the formula if it is not correct
self.bsd_formula = None

# Local data

# The Kodaira symbol is stored as an int in pari encoding. The
Expand Down
49 changes: 45 additions & 4 deletions lmfdb/ecnf/templates/ecnf-curve.html
Original file line number Diff line number Diff line change
Expand Up @@ -274,7 +274,7 @@ <h2> {{ KNOWL('ec.bsdconjecture', title='BSD invariants') }}</h2>
<tr>
<td align='left'>{{ KNOWL('ec.rank', title="Mordell-Weil rank")}}:</td>
{% if ec.rk == "not available" %}
<td>$r$?</td>
<td>$r?$</td>
<td>&nbsp;</td>
{% if ec.rank_bounds != "not available" %}
<td>\({{ ec.rk_lb }} \le r \le {{ec.rk_ub}}\)</td>
Expand All @@ -296,7 +296,7 @@ <h2> {{ KNOWL('ec.bsdconjecture', title='BSD invariants') }}</h2>
{% endif %}
</td>
<td>$\mathrm{Reg}(E/K)$</td>
<td>{% if ec.rk == 0 %}={% else %}&approx;{% endif %}</td>
<td>{% if ec.rank == 0 %}={% else %}&approx;{% endif %}</td>
<td>
{% if ec.reg=='not available' %}
not available
Expand All @@ -305,6 +305,24 @@ <h2> {{ KNOWL('ec.bsdconjecture', title='BSD invariants') }}</h2>
{% endif %}
</td>
</tr>
<tr>
<td align='left'>
{% if ec.bsd_status == "conditional" %}
{{ KNOWL('ec.regulator', title='N&eacute;ron-Tate Regulator*') }}:
{% else %}
{{ KNOWL('ec.regulator', title='N&eacute;ron-Tate Regulator') }}:
{% endif %}
</td>
<td>$\mathrm{Reg}_{\mathrm{NT}}(E/K)$</td>
<td>{% if ec.rank == 0 %}={% else %}&approx;{% endif %}</td>
<td>
{% if ec.NTreg=='not available' %}
not available
{% else %}
{{ ec.NTreg }}
{% endif %}
</td>
</tr>

<tr>
<td align='left'>{{ KNOWL('ec.period', title='Global period') }}:</td>
Expand Down Expand Up @@ -349,8 +367,19 @@ <h2> {{ KNOWL('ec.bsdconjecture', title='BSD invariants') }}</h2>
<td>&#1064;${}_{\mathrm{an}}$</td><td>=</td>
<td> {{ ec.sha }} </td>
</tr>
{#
<tr>
<td align='left'>
{{ KNOWL('ec.analytic_sha_order', title='Analytic order of &#1064; (from formula)') }}:
</td>
<td>&#1064;${}_{\mathrm{an}}$</td><td>=</td>
<td> {{ ec.BSDsha }} </td>
</tr>
#}
</table>
</p>
{# %%%%%%%%%%%%%%%% END OF TABLE %%%%%%%%%%%%%%%%%%% #}
</p>

{% if ec.bsd_status == "conditional" %}
<p>
* Conditional on {{ KNOWL('ec.bsdconjecture', title='BSD') }}: assuming rank = analytic rank.
Expand All @@ -364,10 +393,22 @@ <h2> {{ KNOWL('ec.bsdconjecture', title='BSD invariants') }}</h2>
</p>
{% endif %}
{% endif %}
</div>

{# %%%%%%%%%%%%%%%% END OF TABLE %%%%%%%%%%%%%%%%%%% #}
{% if ec.bsd_formula %}

<h2> {{ KNOWL('ec.bsdconjecture', title='BSD formula') }}</h2>
<div>
<p style="margin:10px 280px;">
$\displaystyle {{ ec.bsd_formula|safe }}$
</p>
<center>
{{ place_code('bsd_formula') }}
</center>
</div>

{% endif %}

<h2>{{KNOWL('ec.local_data', title='Local data')}} at {{KNOWL('ec.bad_reduction', title='primes of bad reduction')}} </h2>
<div>
{{ place_code('localdata') }}
Expand Down

0 comments on commit fef99a9

Please sign in to comment.