Changeset 7727:8915b2343245


Ignore:
Timestamp:
12/02/07 05:13:19 (5 years ago)
Author:
William Stein <wstein@…>
Branch:
default
Message:

work in progress on residue class fields.

Files:
3 edited

Legend:

Unmodified
Added
Removed
  • sage/rings/number_field/number_field_ideal.py

    r7725 r7727  
    10211021    V, from_V, to_V = K.absolute_vector_space() 
    10221022    M = ZZ**(V.dimension()) 
    1023     C = [to_V(b) for b in B] 
     1023    C = [to_V(K(b.list())) for b in B] 
    10241024    return M.span_of_basis(C) 
    10251025         
     
    10981098     
    10991099    K    = I.number_field() 
    1100     OK   = K.maximal_order(p)  # really only need a p-maximal order. 
     1100    OK   = K.maximal_order()  # will in the long run only really need a p-maximal order. 
    11011101    M_OK = OK.free_module() 
    11021102    M_I  = I.free_module() 
  • sage/rings/residue_field.pyx

    r7726 r7727  
    5050from sage.structure.parent_base import ParentWithBase 
    5151 
     52from sage.modules.free_module_element import FreeModuleElement 
     53 
    5254from sage.rings.polynomial.polynomial_ring import PolynomialRing 
    5355 
     
    8991        sage: k.0^3 - 875 
    9092        2 
     93 
     94    An example where the residue class field is large but of degree 1: 
     95        sage: K.<a> = NumberField(x^3-875); P = K.ideal(2007).factor()[0][0]; k = K.residue_field(P); k 
     96        Residue field of Fractional ideal (-2/25*a^2 - 2/5*a - 3) 
     97        sage: k(a) 
     98        168 
     99        sage: k(a)^3 - 875 
     100        0 
     101 
     102    In this example, 2 is an inessential discriminant divisor, so divides 
     103    the index of ZZ[a] in the maximal order for all a. 
     104        sage: K.<a> = NumberField(x^3 + x^2 - 2*x + 8); P = K.ideal(2).factor()[0][0]; P 
     105        Fractional ideal (1/2*a^2 - 1/2*a + 1) 
     106        sage: F = K.residue_field(P); F 
     107        Residue field of Fractional ideal (1/2*a^2 - 1/2*a + 1) 
     108        sage: F(a) 
     109        0 
     110        sage: B = K.maximal_order().basis(); B 
     111        [1, 1/2*a^2 + 1/2*a, a^2] 
     112        sage: F(B[1]) 
     113        1 
     114        sage: F(B[2]) 
     115        0 
     116        sage: F 
     117        Residue field of Fractional ideal (1/2*a^2 - 1/2*a + 1) 
     118        sage: F.degree() 
     119        1 
    91120    """ 
    92121    if isinstance(names, tuple): 
     
    100129        if k is not None: 
    101130            return k 
    102     if PY_TYPE_CHECK(p, Integer): 
    103         if check and not p.is_prime(): 
     131    if check: 
     132        if not is_NumberFieldIdeal(p): 
     133            raise TypeError, "p must be a prime ideal in the ring of integers of a number field." 
     134        if not p.is_prime(): 
    104135            raise ValueError, "p must be prime" 
    105         if names is None: 
    106             names = 'x' 
    107         k = ResidueFiniteField_prime_modn(p, names) 
    108     elif is_NumberFieldIdeal(p): 
    109         if names is None: 
    110             names = '%sbar'%(p.number_field().variable_name()) 
    111         if check and not p.is_prime(): 
    112             raise ValueError, "p must be prime" 
    113         # Should generalize to allowing residue fields of relative extensions to be extensions of finite fields. 
    114         characteristic = p.smallest_integer() 
    115  
    116         K = p.number_field() 
    117         OK = K.maximal_order() # should change to p.order once this works. 
    118          
    119         U, to_vs, to_order = p._p_quotient(characteristic) 
    120         k = U.base_ring() 
    121         R = PolynomialRing(k, names) 
    122         n = p.residue_class_degree() 
    123         gen_ok = False 
    124         from sage.matrix.constructor import matrix 
    125         try: 
    126             x = K.gen() 
    127             M = matrix(k, n+1, n, [to_vs(x**i).list() for i in range(n+1)]).transpose() 
    128             M.echelonize() 
    129             if M.rank() == n: 
    130                 gen_ok = True 
    131                 f = R((-M.column(n)).list() + [1]) 
    132         except TypeError: 
    133             pass 
    134         if not gen_ok: 
    135             bad = True 
    136             for u in U: # using this iterator may not be optimal, we may get a long string of non-generators 
    137                 if u: 
    138                     x = to_order(u) 
    139                     M = matrix(k, n+1, n, [to_vs(x**i).list() for i in range(n+1)]).transpose() 
    140                     M.echelonize() 
    141                     if M.rank() == n: 
    142                         f = R((-M.column(n)).list() + [1]) 
    143                         bad = False 
    144                         break 
    145             assert not bad, "error -- didn't find a generator." 
    146         if n == 1: 
    147             k = ResidueFiniteField_prime_modn(p, names, im_gen = -f[0], intp = p.smallest_integer()) 
     136 
     137    if names is None: 
     138        names = '%sbar'%(p.number_field().variable_name()) 
     139    # Should generalize to allowing residue fields of relative extensions to be extensions of finite fields. 
     140    characteristic = p.smallest_integer() 
     141 
     142    K = p.number_field() 
     143    OK = K.maximal_order() # should change to p.order once this works. 
     144 
     145    U, to_vs, to_order = p._p_quotient(characteristic) 
     146    k = U.base_ring() 
     147    R = PolynomialRing(k, names) 
     148    n = p.residue_class_degree() 
     149    gen_ok = False 
     150    from sage.matrix.constructor import matrix 
     151    try: 
     152        x = K.gen() 
     153        M = matrix(k, n+1, n, [to_vs(x**i).list() for i in range(n+1)]) 
     154        W = M.transpose().echelon_form() 
     155        if M.rank() == n: 
     156            PB = M.matrix_from_rows(range(n)) 
     157            gen_ok = True 
     158            f = R((-W.column(n)).list() + [1]) 
     159    except TypeError: 
     160        pass 
     161    if not gen_ok: 
     162        bad = True 
     163        for u in U: # using this iterator may not be optimal, we may get a long string of non-generators 
     164            if u: 
     165                x = to_order(u) 
     166                M = matrix(k, n+1, n, [to_vs(x**i).list() for i in range(n+1)]) 
     167                W = M.transpose().echelon_form() 
     168                if W.rank() == n: 
     169                    f = R((-W.column(n)).list() + [1]) 
     170                    PB = M.matrix_from_rows(range(n)) 
     171                    bad = False 
     172                    break 
     173        assert not bad, "error -- didn't find a generator." 
     174    if n == 1: 
     175        k = ResidueFiniteField_prime_modn(p, names, im_gen = -f[0], intp = p.smallest_integer()) 
     176    else: 
     177        q = characteristic**(f.degree()) 
     178        if q < Integer(2)**Integer(16): 
     179            k = ResidueFiniteField_givaro(p, q, names, f, characteristic)             
    148180        else: 
    149             q = characteristic**(f.degree()) 
    150             if q < Integer(2)**Integer(16): 
    151                 k = ResidueFiniteField_givaro(p, q, names, f, characteristic)             
    152             else: 
    153                 k = ResidueFiniteField_ext_pari(p, q, names, f, characteristic) 
    154             k.structure = (U, to_vs, to_order) 
    155     else: # Add support for primes in other rings later. 
    156         raise TypeError, "p must be a prime in the integers or a number field" 
     181            k = ResidueFiniteField_ext_pari(p, q, names, f, characteristic) 
     182    # end creating field. 
     183 
     184    # The reduction map is just x |--> k(to_vs(x) * (PB**(-1))) 
     185    # The lifting map is just x |--> to_order(x * PB) 
     186    pi = ReductionMap(K, k, to_vs, PB**(-1)) 
     187    lift = LiftingMap(K, k, to_order, PB) 
     188    k._structure = (pi, lift) 
     189                 
    157190    residue_field_cache[key] = weakref.ref(k) 
    158191    return k 
     
    232265                return -1 
    233266        return cmp(type(self), type(x)) 
     267 
     268class ReductionMap: 
     269    def __init__(self, K, F, to_vs, PBinv): 
     270        self.__K = K 
     271        self.__F = F   # finite field 
     272        self.__to_vs = to_vs 
     273        self.__PBinv = PBinv 
     274 
     275    def __call__(self, x): 
     276        # The reduction map is just x |--> F(to_vs(x) * (PB**(-1))) 
     277        x = self.__K(x) 
     278        return self.__F(self.__to_vs(x) * self.__PBinv) 
     279 
     280    def __repr__(self): 
     281        return "Partially defined reduction map from %s to %s"%(self.__K, self.__F) 
     282 
     283class LiftingMap: 
     284    def __init__(self, K, F, to_order, PB): 
     285        self.__K = K 
     286        self.__F = F   # finite field 
     287        self.__to_order = to_order 
     288        self.__PB = PB 
     289 
     290    def __call__(self, x): 
     291        # The lifting map is just x |--> to_order(x * PB) 
     292        x = self.__F(x) 
     293        v = x.polynomial().padded_list(self.__F.degree()) 
     294        return self.__to_order(self.__PB.linear_combination_of_rows(v)) 
     295 
     296    def __repr__(self): 
     297        return "Lifting map from %s to %s"%(self.__F, self.__K) 
    234298 
    235299cdef class NFResidueFieldHomomorphism(ResidueFieldHomomorphism): 
     
    276340        """ 
    277341        self.im_gen = im_gen 
    278         self.p = p 
     342        self.p = p  
    279343        ResidueFieldHomomorphism.__init__(self,Hom(p.number_field().maximal_order(), k, Rings())) # should eventually change to p.order() 
    280344 
     
    291355            13*abar^2 + 7*abar + 21 
    292356        """ 
    293         y = x.polynomial().change_ring(self.codomain().base_ring())(self.im_gen)  #polynomial should change to absolute_polynomial? 
     357        #y = x.polynomial().change_ring(self.codomain().base_ring())(self.im_gen)  #polynomial should change to absolute_polynomial? 
     358        y = self.codomain()(x) 
    294359        (<Element>y)._set_parent_c(self.codomain()) 
    295360        return y         
     
    303368            sage: K.<a> = NumberField(x^3-7) 
    304369            sage: P = K.ideal(29).factor()[0][0] 
    305             sage: k =K.residue_field(P) 
     370            sage: k = K.residue_field(P) 
    306371            sage: OK = K.maximal_order() 
    307372            sage: f = k.coerce_map_from(OK) 
     
    315380        if self.domain() is ZZ: 
    316381            return x.lift() 
    317         return self.domain()(x.polynomial().change_ring(self.domain().base_ring())(self.domain().ring_generators()[0]))  #polynomial should change to absolute_polynomial? 
     382        else: 
     383            return self.codomain()._structure[1](x) 
     384            
     385        # return self.domain()(x.polynomial().change_ring(self.domain().base_ring())(self.domain().ring_generators()[0]))  #polynomial should change to absolute_polynomial? 
    318386         
    319387 
     
    346414        """ 
    347415        INPUT: 
    348            p -- An integral prime or a prime ideal of a number field. 
     416           p -- A prime ideal of a number field. 
    349417           name -- the name of the generator of this extension 
    350418           im_gen -- the image of the generator of the number field in this finite field. 
     
    384452        """ 
    385453        try: 
    386             return self.coerce_map_from(self.f.domain())(self.f.domain()(x)) 
    387         except (AttributeError, TypeError): 
    388454            return FiniteField_prime_modn.__call__(self, x) 
     455        except TypeError: 
     456            if isinstance(x, FreeModuleElement): 
     457                return FiniteField_prime_modn.__call__(self, x[0]) 
     458            else: 
     459                return self._structure[0](x) 
     460        #try: 
     461        #    return self.coerce_map_from(self.f.domain())(self.f.domain()(x)) 
     462        #except (AttributeError, TypeError): 
     463        #    return FiniteField_prime_modn.__call__(self, x) 
    389464 
    390465class ResidueFiniteField_ext_pari(ResidueField_generic, FiniteField_ext_pari): 
     
    395470        sage: K.<a> = NumberField(x^3-7) 
    396471        sage: P = K.ideal(923478923).factor()[0][0] 
    397         sage: k =K.residue_field(P) 
     472        sage: k = K.residue_field(P) 
    398473        sage: k.degree() 
    399474        2 
     
    438513        """ 
    439514        try: 
    440             return self.coerce_map_from(self.f.domain())(self.f.domain()(x)) 
    441         except (AttributeError, TypeError): 
    442515            return FiniteField_ext_pari.__call__(self, x) 
     516        except TypeError: 
     517            return self._structure[0](x) 
     518        #try: 
     519        #    return self.coerce_map_from(self.f.domain())(self.f.domain()(x)) 
     520        #except (AttributeError, TypeError): 
     521        #    return FiniteField_ext_pari.__call__(self, x) 
    443522 
    444523class ResidueFiniteField_givaro(ResidueField_generic, FiniteField_givaro): 
     
    474553            sage: K.<a> = NumberField(x^4+3*x^2-17) 
    475554            sage: P = K.ideal(61).factor()[0][0] 
    476             sage: k =K.residue_field(P) 
     555            sage: k = K.residue_field(P) 
    477556        """ 
    478557        FiniteField_givaro.__init__(self, q, name, g) 
     
    494573        """ 
    495574        try: 
    496             return self.coerce_map_from(self.f.domain())(self.f.domain()(x)) 
    497         except (AttributeError, TypeError): 
    498575            return FiniteField_givaro.__call__(self, x) 
    499  
     576        except TypeError: 
     577            try: 
     578                return self._structure[0](x) 
     579            except: 
     580                raise TypeError 
     581 
     582        #try: 
     583        #    return self.coerce_map_from(self.f.domain())(self.f.domain()(x)) 
     584        #except (AttributeError, TypeError): 
     585        #    return FiniteField_givaro.__call__(self, x) 
     586 
     587 
  • setup.py

    r7678 r7727  
    10991099if not sdist and do_cython: 
    11001100    cython(ext_modules) 
     1101    pass 
    11011102 
    11021103code = setup(name        = 'sage', 
Note: See TracChangeset for help on using the changeset viewer.