Changeset 4146:fef02f066f8b


Ignore:
Timestamp:
04/20/07 13:06:35 (6 years ago)
Author:
Robert Bradshaw <robertwb@…>
Branch:
default
Message:

new monsky-washnitzer special hyperelliptic quotient ring

File:
1 edited

Legend:

Unmodified
Added
Removed
  • sage/schemes/elliptic_curves/monsky_washnitzer.py

    r4143 r4146  
    20152015 
    20162016from sage.misc.profiler import Profiler 
     2017from sage.misc.misc import repr_lincomb 
    20172018 
    20182019def matrix_of_frobenius_general(Q, p, prec): 
     
    20222023    extra_prec_ring = Integers(p**M) # pAdicField(p, M) # SLOW! 
    20232024    real_prec_ring = Integers(p**prec) # pAdicField(p, prec) # To capped absolute? 
    2024     S = SpecialHyperellipticQuotientRing(Q, extra_prec_ring, p, True) 
     2025    S = SpecialHyperellipticQuotientRing_2(Q, extra_prec_ring, p, True) 
     2026#    S = SpecialHyperellipticQuotientRing(Q, extra_prec_ring, p, True) 
    20252027    MW = S.monsky_washnitzer() 
    20262028    prof("frob basis elements") 
     
    20322034    M = M.change_ring(pAdicField(p, prec)) 
    20332035    print prof 
    2034     print len(S._monomials) 
     2036#    print len(S._monomials) 
    20352037    return M.transpose() 
     2038     
     2039     
     2040     
     2041 
     2042         
     2043         
     2044class SpecialHyperellipticQuotientRing_2(CommutativeAlgebra): 
     2045    def __init__(self, Q, R, p, invert_y=False): 
     2046        CommutativeAlgebra.__init__(self, R) 
     2047        self._p = p 
     2048         
     2049        x = PolynomialRing(R, 'x').gen(0) 
     2050        if is_EllipticCurve(Q): 
     2051            E = Q 
     2052            if E.a1() != 0 or E.a2() != 0: 
     2053                raise NotImplementedError, "Curve must be in Weierstrass normal form." 
     2054            Q = E.defining_polynomial()(x,0,1) 
     2055             
     2056        elif is_HyperellipticCurve(Q): 
     2057            C = Q 
     2058            if C.hyperelliptic_polynomials()[1] != 0: 
     2059                raise NotImplementedError, "Curve must be of form y^2 = Q(x)." 
     2060            Q = E.hyperelliptic_polynomials()[0]()(x) 
     2061         
     2062        if is_Polynomial(Q): 
     2063            self._Q = Q.change_ring(R) 
     2064            self._coeffs = self._Q.coeffs() 
     2065            if self._coeffs.pop() != 1: 
     2066                raise NotImplementedError, "Polynomial must be monic." 
     2067         
     2068        else: 
     2069            raise NotImplementedError, "Must be an elliptic curve or polynomial Q for y^2 = Q(x)" 
     2070 
     2071        self._n = degree = int(Q.degree()) 
     2072         
     2073        self._series_ring = (LaurentSeriesRing if invert_y else PolynomialRing)(R, 'y') 
     2074        self._series_ring_y = self._series_ring.gen(0) 
     2075        self._series_ring_0 = self._series_ring(0) 
     2076         
     2077        self._poly_ring = PolynomialRing(self._series_ring, 'x') 
     2078         
     2079        self._x = self(self._poly_ring.gen(0)) 
     2080        self._y = self(self._series_ring.gen(0)) 
     2081         
     2082        self._dQ = Q.derivative().change_ring(self)(self._x) 
     2083        self._monsky_washnitzer = MonskyWashnitzerDifferentialRing(self) 
     2084         
     2085 
     2086    def __call__(self, val): 
     2087        if isinstance(val, SpecialHyperellipticQuotientElement_2) and val.parent() is self: 
     2088            return val 
     2089        return SpecialHyperellipticQuotientElement_2(self, val) 
     2090         
     2091    def gens(self): 
     2092        return self._x, self._y 
     2093         
     2094    def x(self): 
     2095        return self._x 
     2096 
     2097    def y(self): 
     2098        return self._y 
     2099         
     2100    def monomial(self, i, j, b=None): 
     2101        """ 
     2102        Returns $b y^j x^i$, computed quickly. 
     2103        """ 
     2104        i = int(i) 
     2105        j = int(j) 
     2106         
     2107        if 0 < i and i < self._n: 
     2108            if b is None: 
     2109                by_to_j = self._series_ring_y << (j-1) 
     2110            else: 
     2111                by_to_j = self._series_ring(b) << j 
     2112            v = [self._series_ring_0] * self._n 
     2113            v[i] = by_to_j 
     2114            return self(v) 
     2115        else: 
     2116            return (self._x ** i) << j if b is None else self.base_ring()(b) * (self._x ** i) << j 
     2117         
     2118    def Q(self): 
     2119        return self._Q 
     2120         
     2121    def degree(self): 
     2122        return self._n 
     2123         
     2124    def prime(self): 
     2125        return self._p 
     2126         
     2127    def monsky_washnitzer(self): 
     2128        return self._monsky_washnitzer 
     2129         
     2130    def is_field(self): 
     2131        return False 
     2132         
     2133         
     2134 
     2135class SpecialHyperellipticQuotientElement_2(CommutativeAlgebraElement): 
     2136 
     2137    def __init__(self, parent, val=0): 
     2138        CommutativeAlgebraElement.__init__(self, parent) 
     2139        self._f = parent._poly_ring(val) 
     2140         
     2141    def __invert__(self): 
     2142        """ 
     2143        The general element in our ring is not invertible, but y may be.  
     2144        We do not want to pass to the fraction field.  
     2145        """ 
     2146        if self._f.degree() == 0 and self._f[0].is_unit(): 
     2147            return SpecialHyperellipticQuotientElement_2(self.parent(), ~self._f[0]) 
     2148        else: 
     2149            raise ZeroDivisionError, "Element not invertible" 
     2150         
     2151    def is_zero(self): 
     2152        return self._f.is_zero() 
     2153         
     2154    def __eq__(self, other): 
     2155        if not isinstance(other, SpecialHyperellipticQuotientElement_2): 
     2156            other = self.parent()(other) 
     2157        return self._f == other._f 
     2158         
     2159    def _add_(self, other): 
     2160        return SpecialHyperellipticQuotientElement_2(self.parent(), self._f + other._f) 
     2161         
     2162    def _sub_(self, other): 
     2163        return SpecialHyperellipticQuotientElement_2(self.parent(), self._f - other._f) 
     2164         
     2165    def _mul_(self, other): 
     2166        prod = self._f * other._f 
     2167        v = prod.list() 
     2168        Q_coeffs = self.parent().Q().list() 
     2169        n = len(Q_coeffs) - 1 
     2170        y2 = self.parent()._series_ring_y << 1 
     2171        for i in range(len(v)-1, n-1, -1): 
     2172            for j in range(n): 
     2173                v[i-n+j] -= v[i] * Q_coeffs[j] 
     2174            v[i-n] += v[i] * y2 
     2175        return SpecialHyperellipticQuotientElement_2(self.parent(), v[0:n]) 
     2176         
     2177    def _rmul_(self, c): 
     2178        return self.parent()([c*a for a in self._f]) 
     2179             
     2180    def _lmul_(self, c): 
     2181        return self.parent()([a*c for a in self._f]) 
     2182             
     2183    def __lshift__(self, k): 
     2184        return self.parent()([a << k for a in self._f]) 
     2185             
     2186    def __rshift__(self, k): 
     2187        return self.parent()([a >> k for a in self._f]) 
     2188     
     2189    def _repr_(self): 
     2190        x = PolynomialRing(QQ, 'x').gen(0) 
     2191        coeffs = self._f.list() 
     2192        return repr_lincomb([x**i for i in range(len(coeffs))], coeffs) 
     2193         
     2194    def _latex_(self): 
     2195        x = PolynomialRing(QQ, 'x').gen(0) 
     2196        coeffs = self._f.list() 
     2197        return repr_lincomb([x**i for i in range(len(coeffs))], coeffs, is_latex=True) 
     2198 
     2199     
     2200    def diff(self): 
     2201     
     2202#        try: 
     2203#            return self._diff_x 
     2204#        except AttributeError: 
     2205#            pass 
     2206     
     2207        # d(self) = A dx + B dy 
     2208        #         = (2y A + BQ') dx/2y 
     2209        parent = self.parent() 
     2210        R = parent.base_ring() 
     2211        x, y = parent.gens() 
     2212        v = self._f.list() 
     2213        n = len(v) 
     2214        A = parent([R(i) * v[i] for i in range(1,n)]) 
     2215        B = parent([a.derivative() for a in v]) 
     2216        dQ = parent._dQ 
     2217        return parent._monsky_washnitzer( (R(2) * A << 1) + dQ * B ) 
     2218#        self._diff = self.parent()._monsky_washnitzer( two_y * A + dQ * B ) 
     2219#        return self._diff 
     2220         
     2221    def extract_pow_y(self, k): 
     2222        v = [a[k] for a in self._f.list()] 
     2223        while len(v) < self.parent()._n: 
     2224            v.append(0) 
     2225        return v 
     2226         
     2227    def min_pow_y(self): 
     2228        return min([a.valuation() for a in self._f.list()]) 
     2229         
     2230    def max_pow_y(self): 
     2231        return max([a.degree() for a in self._f.list()]) 
     2232 
    20362233 
    20372234class SpecialHyperellipticQuotientRing(FreeAlgebraQuotient): 
     
    21572354    def monsky_washnitzer(self): 
    21582355        return self._monsky_washnitzer 
    2159          
    2160          
     2356 
     2357 
    21612358class SpecialHyperellipticQuotientElement(FreeAlgebraQuotientElement): 
    21622359     
     
    22992496    def frob_Q(self): 
    23002497        x_to_p = self.x_to_p() 
    2301         return self.base_ring()._Q(x_to_p) 
     2498        return self.base_ring()._Q.change_ring(self.base_ring())(x_to_p) 
    23022499 
    23032500    def frob_invariant_differential(self, prec): 
     
    23262523        # We are solving for t = a^{-1/2} = (F_pQ y^{-p})^{-1/2} 
    23272524        # This converges because we know the root is in the same residue class as 1.  
    2328         t = 1 
     2525        t = self.base_ring()(1) 
    23292526        print prec, "->", ceil(log(prec, 2))+1 
    23302527#        for _ in range(prec+1): 
     
    24552652#                    reduced -= gg.diff() 
    24562653                    g += S.monomial(i, j, lin_comb[i]) 
    2457             if g.vector() != 0: 
     2654            if not g.is_zero(): 
    24582655                f += g 
    24592656                reduced -= g.diff() 
Note: See TracChangeset for help on using the changeset viewer.