Repository: LMFDB/lmfdb

Issue:
Minor problem when entering genus 2 curve coefficients in the jump box
Running master locally the input "[[1,1,0,0,0,1],[]]" works in the genus 2 jump box, taking you to the page http://127.0.0.1:37777/Genus2Curve/Q/123648/e/865536/1 as it should, but on https://beta.lmfdb.org this does not work (but [x^5+x+1,0] does).

 I don't understand the difference in behavior, they are running the same code (I even tried running my own copy of master on blue with the same result).


Discussion:
this is a regex issue, your original regex assumed nonempty lists. I will fix it.
something is off, my changes on master have been lost
What is really strange is that it works when I run my master branch, and Github does not think my master is ahead of the LMFDB.
@roed314 and I are investigating what is going on...
What is even stranger is that I am running code with a ZLIST_RE that looks like it should should not work (empty list not allowed), but it is working.
The changes were undone here: https://github.com/LMFDB/lmfdb/pull/4957/files#diff-bae38784bed1720930872ce012b1b023c4acf70a68ddc4a4a5135d3b3f24e83e

looks like only my changes were undone, thus I will resubmit them later on today
I don't understand why this happened, since I did not touch those lines, and git did not highlight them as a merge conflict (there was a merge conflict at the top of the file that I fixed).  I guess git got confused.

But I'm still intrigued by the behavior on my local branch. If I type "[[1,1,0,0,0,1],[]]" into the jump box it does not call genus2_jump, even though it is registered, and yet it somehow magically does the right thing.
Got it, `\[\d+(,\d+)*\]` matches the the substring `[1,1,0,0,0,1]` in `[[1,1,0,0,0,1],[]]`
But apparently not on https://beta.lmfdb.org/Genus2Curve/Q/ ?

In any case, I recommend using .fullmatch to avoid this kind of confusion.  I should get an error if I type [1,2,3,4,5,6]banana or banana[1,2,3,4,5,6]
agree

On Tue, Jan 25, 2022 at 7:54 PM Andrew Sutherland ***@***.***>
wrote:

> But apparently not on https://beta.lmfdb.org/Genus2Curve/Q/ ?
>
> In any case, I recommend using .fullmatch to avoid this kind of confusion.
> I should get an error if I type [1,2,3,4,5]banana
>
> —
> Reply to this email directly, view it on GitHub
> <https://github.com/LMFDB/lmfdb/issues/4968#issuecomment-1021750694>, or
> unsubscribe
> <https://github.com/notifications/unsubscribe-auth/AACO2BTN327GMQAE3A6RKGLUX5A2JANCNFSM5MZQHUDA>
> .
> Triage notifications on the go with GitHub Mobile for iOS
> <https://apps.apple.com/app/apple-store/id1477376905?ct=notification-email&mt=8&pt=524675>
> or Android
> <https://play.google.com/store/apps/details?id=com.github.android&referrer=utm_campaign%3Dnotification-email%26utm_medium%3Demail%26utm_source%3Dgithub>.
>
> You are receiving this because you were assigned.Message ID:
> ***@***.***>
>

Perhaps there are different version of the python re module in play which could accout for different behaviour of the same code?

Resolving patch:
diff --git a/lmfdb/genus2_curves/main.py b/lmfdb/genus2_curves/main.py
--- a/lmfdb/genus2_curves/main.py
+++ b/lmfdb/genus2_curves/main.py
@@ -5,7 +5,7 @@
 from collections import defaultdict
 
 from flask import render_template, url_for, request, redirect, abort
-from sage.all import ZZ, QQ, PolynomialRing, magma, prod, factor
+from sage.all import ZZ, QQ, PolynomialRing, magma, prod, factor, latex
 
 from lmfdb import db
 from lmfdb.utils import (
@@ -19,9 +19,11 @@
     TextBox,
     TextBoxWithSelect,
     YesNoBox,
+    coeff_to_poly,
     comma,
     display_knowl,
     flash_error,
+    flash_info,
     formatters,
     parse_bool,
     parse_bracketed_posints,
@@ -151,6 +153,8 @@
     "48.29": r"$\GL(2,3)$",
 }
 
+
+
 ###############################################################################
 # Routing for top level and random_curve
 ###############################################################################
@@ -364,32 +368,62 @@ def class_from_curve_label(label):
 # Searching
 ################################################################################
 
-def genus2_lookup_equation(f):
-    f.replace(" ", "")
-    # TODO allow other variables, if so, fix the error message accordingly
+### Regex patterns used in lookup
+TERM_RE = r"(\+|-)?(\d*[A-Za-z]|\d+\*[A-Za-z]|\d+)(\^\d+)?"
+STERM_RE = r"(\+|-)(\d*[A-Za-z]|\d+\*[A-Za-z]|\d+)(\^\d+)?"
+POLY_RE = re.compile(TERM_RE + "(" + STERM_RE + ")*")
+POLYLIST_RE = re.compile(r"(\[|)" + POLY_RE.pattern + r"," + POLY_RE.pattern + r"(\]|)")
+ZLIST_RE = re.compile(r"\[(|((|-)\d+)*(,(|-)\d+)*)\]")
+ZLLIST_RE = re.compile(r"(\[|)" + ZLIST_RE.pattern + r"," + ZLIST_RE.pattern + r"(\]|)")
+G2_LOOKUP_RE = re.compile(
+    r"(" + "|".join([elt.pattern for elt in [POLY_RE, POLYLIST_RE, ZLIST_RE, ZLLIST_RE]]) + r")"
+)
+
+
+def genus2_lookup_equation(input_str):
+    # retuns:
+    # label, C_str
+    # None, C_str when it couldn't find it in the DB
+    # "", input_str when it fails to parse
+    # 0, C_str when it fails to start magma
     R = PolynomialRing(QQ, "x")
-    if ("x" in f and "," in f) or "],[" in f:
-        if "],[" in f:
-            e = f.split("],[")
-            f = [R(literal_eval(e[0][1:] + "]")), R(literal_eval("[" + e[1][0:-1]))]
+    y = PolynomialRing(R, "y").gen()
+    def read_list_coeffs(elt):
+        if not elt:
+            return R(0)
         else:
-            e = f.split(",")
-            f = [R(str(e[0][1:])), R(str(e[1][0:-1]))]
+            return R([int(c) for c in elt.split(",")])
+
+    if ZLLIST_RE.fullmatch(input_str):
+        input_str = input_str.strip('[').strip(']')
+        fg = [read_list_coeffs(elt) for elt in input_str.split('],[')]
+    elif ZLIST_RE.fullmatch(input_str):
+        input_str = input_str.strip('[').strip(']')
+        fg = [read_list_coeffs(input_str), R(0)]
     else:
-        f = R(str(f))
+        print(input_str)
+        input_str = input_str.strip('[').strip(']')
+        fg = [R(list(coeff_to_poly(elt))) for elt in input_str.split(",")]
+    if len(fg) == 1:
+        fg.append(R(0));
+
+    C_str_latex= fr"\({latex(y**2 + y*fg[1])} = {latex(fg[0])}\)"
     try:
-        C = magma.HyperellipticCurve(f)
+        C = magma.HyperellipticCurve(fg)
         g2 = magma.G2Invariants(C)
     except TypeError:
-        return None
+        raise ValueError(f'{C_str_latex} invalid genus 2 curve')
     g2 = str([str(i) for i in g2]).replace(" ", "")
     for r in db.g2c_curves.search({"g2_inv": g2}):
         eqn = literal_eval(r["eqn"])
-        D = magma.HyperellipticCurve(R(eqn[0]), R(eqn[1]))
+        fgD = [R(eqn[0]), R(eqn[1])]
+        D = magma.HyperellipticCurve(fgD)
         # there is recursive bug in sage
         if str(magma.IsIsomorphic(C, D)) == "true":
-            return r["label"]
-    return None
+            if fgD != fg:
+                flash_info(f"The requested genus 2 curve {C_str_latex} is isomorphic to the one below, but uses a different defining polynomial.")
+            return r["label"], ""
+    return None, C_str_latex
 
 
 def geom_inv_to_G2(inv):
@@ -433,43 +467,42 @@ def igusa_to_G2(Jlist):
         return igusa_to_G2(inv)
 
 
-TERM_RE = r"(\+|-)?(\d*x|\d+\*x|\d+)(\^\d+)?"
-STERM_RE = r"(\+|-)(\d*x|\d+\*x|\d+)(\^\d+)?"
-POLY_RE = TERM_RE + "(" + STERM_RE + ")*"
-ZLIST_RE = r"\[\d+(,\d+)*\]"
+
+LABEL_RE = re.compile(r"\d+\.[a-z]+\.\d+\.\d+")
+ISOGENY_LABEL_RE = re.compile(r"\d+\.[a-z]+")
+LHASH_RE = re.compile(r"\#\d+")
 
 
 def genus2_jump(info):
     jump = info["jump"].replace(" ", "")
-    if re.match(r"^\d+\.[a-z]+\.\d+\.\d+$", jump):
+    if LABEL_RE.fullmatch(jump):
         return redirect(url_for_curve_label(jump), 301)
-    elif re.match(r"^\d+\.[a-z]+$", jump):
+    elif ISOGENY_LABEL_RE.fullmatch(jump):
         return redirect(url_for_isogeny_class_label(jump), 301)
-    elif re.match(r"^\#\d+$", jump) and ZZ(jump[1:]) < 2 ** 61:
+    elif LHASH_RE.fullmatch(jump) and ZZ(jump[1:]) < 2 ** 61:
         # Handle direct Lhash input
         c = db.g2c_curves.lucky({"Lhash": jump[1:].strip()}, projection="class")
         if c:
             return redirect(url_for_isogeny_class_label(c), 301)
         else:
             errmsg = "hash %s not found"
-    elif (
-        re.match(r"^" + POLY_RE + r"$", jump)
-        or re.match(r"^\[" + POLY_RE + r"," + POLY_RE + r"\]$", jump)
-        or re.match(r"^" + ZLIST_RE + r"$", jump)
-        or re.match(r"^\[" + ZLIST_RE + r"," + ZLIST_RE + r"\]$", jump)
-    ):
-        label = genus2_lookup_equation(jump)
+    elif G2_LOOKUP_RE.fullmatch(jump):
+        label, eqn_str = genus2_lookup_equation(jump)
         if label:
             return redirect(url_for_curve_label(label), 301)
-        errmsg = "y^2 = %s is not the equation of a genus 2 curve in the database"
+        elif label is None:
+            # the input was parsed
+            errmsg = f"unable to find equation {eqn_str} (interpreted from %s) in the genus 2 curve in the database"
     else:
         errmsg = "%s is not valid input. Expected a label, e.g., 169.a.169.1"
-        errmsg += ", or a univariate polynomial in $x$, e.g., x^5 + 1"
+        errmsg += ", or a univariate polynomial, e.g., x^5 + 1"
         errmsg += "."
     flash_error(errmsg, jump)
     return redirect(url_for(".index"))
 
 
+
+
 class G2C_download(Downloader):
     table = db.g2c_curves
     title = "Genus 2 curves"


Test patch: