Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Hyperelliptic curve constructor has wrong inheritance #37612

Closed
2 tasks done
GiacomoPope opened this issue Mar 14, 2024 · 3 comments · Fixed by #37613
Closed
2 tasks done

Hyperelliptic curve constructor has wrong inheritance #37612

GiacomoPope opened this issue Mar 14, 2024 · 3 comments · Fixed by #37613

Comments

@GiacomoPope
Copy link
Contributor

Steps To Reproduce

sage: R.<x> = QQ[]
sage: f = x^5 - x^4 + 3
sage: HyperellipticCurve(f).jacobian()
Jacobian of Hyperelliptic Curve over Rational Field defined by y^2 = x^5 - x^4 + 3
sage: HyperellipticCurve(f).jacobian
<bound method HyperellipticCurve_generic.jacobian of Hyperelliptic Curve over Rational Field defined by y^2 = x^5 - x^4 + 3>
sage: type(HyperellipticCurve(f).jacobian())
<class 'sage.schemes.hyperelliptic_curves.jacobian_generic.HyperellipticJacobian_generic_with_category'>

Expected Behavior

For genus two curves, the base class should be hyperelliptic_g2 which has the function

    def jacobian(self):
        """
        Return the Jacobian of the hyperelliptic curve.

        EXAMPLES::

            sage: R.<x> = QQ[]
            sage: f = x^5 - x^4 + 3
            sage: HyperellipticCurve(f).jacobian()
            Jacobian of Hyperelliptic Curve over Rational Field defined by y^2 = x^5 - x^4 + 3
        """
        return jacobian_g2.HyperellipticJacobian_g2(self)

So for a genus two curve, we expect a Jacobian of type HyperellipticJacobian_generic.HyperellipticJacobian_g2_generic but this does not happen as only the jacobian() function of HyperellipticCurve_generic is in scope.

Actual Behavior

Class construction should set the right inheritance so that the genus two functions work, or the genus two special cases should be handled within the generic class instead.

Additional Information

No response

Environment

- **Sage Version**: 10.2

Checklist

  • I have searched the existing issues for a bug report that matches the one I want to file, without success.
  • I have read the documentation and troubleshoot guide
@GiacomoPope
Copy link
Contributor Author

The original dynamic classes were made by @anna-somoza, but I do not know if she is actively working on Sage. I am not an expert in class inheritance so I do not wish to try and fix this.

@GiacomoPope
Copy link
Contributor Author

Direct example of this issue (thanks to @grhkm21)

sage: from sage.schemes.hyperelliptic_curves.jacobian_g2 import HyperellipticJacobian_g2
sage: R.<t> = PolynomialRing(GF(next_prime(10^9)))
....: C = HyperellipticCurve(t^5 + t + 1)
sage: type(HyperellipticJacobian_g2(C))
<class 'sage.schemes.hyperelliptic_curves.jacobian_g2.HyperellipticJacobian_g2_with_category'>
sage: HyperellipticJacobian_g2(C).kummer_surface()
Closed subscheme of Projective Space of dimension 3 over Finite Field of size 1000000007 defined by:
  X0^4 - 4*X0*X1^3 + 4*X0^2*X1*X2 - 4*X0*X1^2*X2 + 2*X0^2*X2^2 + X2^4 - 4*X0^3*X3 - 2*X0^2*X1*X3 - 2*X1*X2^2*X3 + X1^2*X3^2 - 4*X0*X2*X3^2
sage: C.jacobian().kummer_surface()
---------------------------------------------------------------------------
KeyError                                  Traceback (most recent call last)

@GiacomoPope
Copy link
Contributor Author

OK so I have a bad(??) fix for this.

Currently the dynamic class would be made with (for example)

    class_name = "_".join(cls_name)
    cls = dynamic_class(
        class_name,
        (HyperellipticCurve_g2, HyperellipticCurve_finite_field)
        cls=HyperellipticCurve_generic,
        doccls=HyperellipticCurve,
    )

Where both HyperellipticCurve_finite_field and HyperellipticCurve_g2 are children of HyperellipticCurve_generic. When this is the case I get the above bad behaviour.

If I set cls to be None when there are classes within bases (above example bases = (HyperellipticCurve_g2, HyperellipticCurve_finite_field) then the inheritance seems to work?

vbraun pushed a commit to vbraun/sage that referenced this issue Mar 30, 2024
…to allow proper method inheritance

    
While working on some hyperelliptic code, I realised the dynamic class
construction had an issue with inheritance for the genus two classes and
certain methods which should have been available were not.

This is discussed in more detail in the issue
sagemath#37612

I do not know a *good* fix for this, but I have found a fix which at
least allows the functions supposed to be accessed to be accessed.

I have added a small doctest to ensure that the method called for genus
two curves is bound to the correct class.

## Overview of the fix

The original class was constructed as:

```py
    cls = dynamic_class(class_name,
                        tuple(superclass),
                        cls=HyperellipticCurve_generic,
                        doccls=HyperellipticCurve)
```

Where `superclass` is either an empty list, a list with a single child
from:

- `HyperellipticCurve_finite_field`
- `HyperellipticCurve_rational_field`
- `HyperellipticCurve_padic_field`
- `HyperellipticCurve_g2`

Notice that all four of these classes are children of
`HyperellipticCurve_generic`.

Or, in the case of the base field being one of the above AND the curve
being genus two this list is of the form:

```
[HyperellipticCurve_XXX_field, HyperellipticCurve_g2]
```

In this case, I found that the dynamic class insertion into `cls` meant
that the methods shared by one of the "`superclass`" (probably should be
called base classes?) and `cls` itself would call the method from `cls`
rather than the superclass and so all specialised functions were
unavailable, making the genus two optimisations redundant.

In my new fix, if `superclass` has a length of zero, I set `cls` to be
`HyperellipticCurve_generic`, otherwise `cls` is `None`.

This seems to work, but I don't know if this is good practice.

Fixes sagemath#37612
    
URL: sagemath#37613
Reported by: Giacomo Pope
Reviewer(s): Giacomo Pope, Kwankyu Lee
@mkoeppe mkoeppe added this to the sage-10.4 milestone Mar 31, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
2 participants