Ticket #11800: trac_11800_allow_conics.patch

File trac_11800_allow_conics.patch, 6.5 KB (added by davideklund, 8 years ago)

Patch updated. More efficient method to find the points at infinity and added documentation.

  • sage/schemes/hyperelliptic_curves/hyperelliptic_finite_field.py

    # HG changeset patch
    # User David Eklund <daek@kth.se>
    # Date 1331946260 21600
    # Node ID 7137eb28864963b826cf61b0c2dca5d2517fc64d
    # Parent  c239be1054e01526a1b0b62da6691061b9dd5587
    Trac 11800: Do not require that the curve contains the point (0:1:0).
    
    diff --git a/sage/schemes/hyperelliptic_curves/hyperelliptic_finite_field.py b/sage/schemes/hyperelliptic_curves/hyperelliptic_finite_field.py
    a b  
    202202        K = self.base_ring()
    203203        f, h = self.hyperelliptic_polynomials()
    204204        one = K(1)
    205         points = [self.point([K(0), one, K(0)], check=True)]
    206        
     205
     206        # start with the points at infinity
     207        P = self.defining_polynomial()
     208        if not P(K(0), K(1), K(0)):
     209            # (0:1:0) is a point on the curve
     210            points = [self.point([K(0), K(1), K(0)], check=True)]
     211        else:
     212            points=[]
     213        if P.degree() > 2:
     214            # P(1, y, 0) = r*y + s
     215            s = P(K(1), K(0), K(0))
     216            r = P(K(1), K(1), K(0)) - s
     217            if r: # r not zero
     218                points.append(self.point([K(1), -s/r, K(0)], check=True))
     219            # the case r = 0 need not be considered
     220        elif K.characteristic() == 2: # deg(P) = 2 and char(K) = 2
     221            # quadratic equation doesn't work in characteristic 2 so use brute force
     222            points += [self.point([K(1), y, K(0)], check=True) for y in K if not P(K(1), y, K(0))]
     223        else: # deg(P) = 2 and char(K) not 2
     224            # P(1, y, 0) = y^2 + r*y + s
     225            if f.degree() < 2:
     226                s = 0
     227            else:
     228                s = -f.coeffs()[-1]
     229            if h.degree() < 1:
     230                r = 0
     231            else:
     232                r = h.coeffs()[-1]
     233            d = r**2/4 - s
     234            if not d: # d = 0
     235                points.append(self.point([K(1), -r/2, K(0)], check=True))
     236            elif d.is_square():
     237                sqrtd = d.sqrt()
     238                points.append(self.point([K(1), -r/2 + sqrtd, K(0)], check=True))
     239                points.append(self.point([K(1), -r/2 - sqrtd, K(0)], check=True))
     240
    207241        if K.characteristic() == 2:
    208242            # quadratic equation doesn't work in characteristic 2
    209243            if h.is_zero():
     
    276310                square_roots[x*x] = x
    277311        f, h = self.hyperelliptic_polynomials()
    278312        one = K(1)
    279         points = [self.point([K(0), one, K(0)], check=True)]
    280        
     313
     314        # start with the points at infinity
     315        P = self.defining_polynomial()
     316        if not P(K(0), K(1), K(0)):
     317            # (0:1:0) is a point on the curve
     318            points = [self.point([K(0), K(1), K(0)], check=True)]
     319        else:
     320            points=[]
     321        if P.degree() > 2:
     322            # P(1, y, 0) = r*y + s
     323            s = P(K(1), K(0), K(0))
     324            r = P(K(1), K(1), K(0)) - s
     325            if r: # r not zero
     326                points.append(self.point([K(1), -s/r, K(0)], check=True))
     327            # the case r = 0 need not be considered
     328        elif K.characteristic() == 2: # deg(P) = 2 and char(K) = 2
     329            # quadratic equation doesn't work in characteristic 2 so use brute force
     330            points += [self.point([K(1), y, K(0)], check=True) for y in K if not P(K(1), y, K(0))]
     331        else: # deg(P) = 2 and char(K) not 2
     332            # P(1, y, 0) = y^2 + r*y + s
     333            if f.degree() < 2:
     334                s = 0
     335            else:
     336                s = -f.coeffs()[-1]
     337            if h.degree() < 1:
     338                r = 0
     339            else:
     340                r = h.coeffs()[-1]
     341            d = r**2/4 - s
     342            sqrtd = square_roots[d]
     343            if not d: # d = 0
     344                points.append(self.point([K(1), -r/2, K(0)], check=True))
     345            elif sqrtd is not None:
     346                points.append(self.point([K(1), -r/2 + sqrtd, K(0)], check=True))
     347                points.append(self.point([K(1), -r/2 - sqrtd, K(0)], check=True))
     348
    281349        if K.characteristic() == 2 or brute_force:
    282350            # quadratic equation doesn't work in characteristic 2
    283             # but there are only 4 affinte points, so just test them
     351            # but there are only 4 affine points, so just test them
    284352            f = self.defining_polynomial()
    285353            points += [self.point([x, y, one], check=True) for x in K for y in K if not f(x, y, one)]
    286354        elif h.is_zero():
     
    325393            sage: C = HyperellipticCurve(x^5 + x - 1, x^2 + 2)
    326394            sage: len(C.points())
    327395            122
     396
     397        Conics are allowed (the issue reported at #11800 has been resolved)::
     398
     399            sage: R.<x> = GF(7)[]
     400            sage: H = HyperellipticCurve(3*x^2 + 5*x + 1)
     401            sage: H.points()
     402            [(0 : 6 : 1), (0 : 1 : 1), (1 : 4 : 1), (1 : 3 : 1), (2 : 4 : 1), (2 : 3 : 1), (3 : 6 : 1), (3 : 1 : 1)]
     403
     404        The method currently lists points on the plane projective model, that is the closure
     405        in $\mathbb{P}^2$ of the curve defined by $y^2+hy=f$. This means that one point
     406        $(0:1:0)$ at infinity is returned if the degree of the curve is at least 4 and
     407        $\deg(f)>\deg(h)+1$. This point is a singular point of the plane model. Later
     408        implementations may consider a smooth model instead since that would be a more
     409        relevant object. Then, for a curve whose only singularity is at $(0:1:0)$, the point
     410        at infinity would be replaced by a number of rational points of the smooth model.
     411        We illustrate this with an example of a genus 2 hyperelliptic curve::
     412
     413            sage: R.<x>=GF(11)[]
     414            sage: H = HyperellipticCurve(x*(x+1)*(x+2)*(x+3)*(x+4)*(x+5))
     415            sage: H.points()
     416            [(0 : 1 : 0), (0 : 0 : 1), (1 : 7 : 1), (1 : 4 : 1), (5 : 7 : 1), (5 : 4 : 1), (6 : 0 : 1), (7 : 0 : 1), (8 : 0 : 1), (9 : 0 : 1), (10 : 0 : 1)]
     417
     418        The plane model of the genus 2 hyperelliptic curve in the above example is the curve
     419        in $\mathbb{P}^2$ defined by $y^2z^4=g(x,z)$ where $g(x,z)=x(x+z)(x+2z)(x+3z)(x+4z)(x+5z).$
     420        This model has one point at infinity $(0:1:0)$ which is also the only singular point of the
     421        plane model. In contrast, the hyperelliptic curve is smooth and imbeds via the equation
     422        $y^2=g(x,z)$ into weighted projected space $\mathbb{P}(1,3,1)$. The latter model has two
     423        points at infinity: $(1:1:0)$ and $(1:-1:0)$.
    328424        """
    329425        from sage.rings.finite_rings.constructor import zech_log_bound
    330426        try: