Changeset 7725:d38173145837


Ignore:
Timestamp:
12/02/07 01:46:33 (5 years ago)
Author:
William Stein <wstein@…>
Branch:
default
Message:

Trac #1183 -- added support for computing O_K / I.

Location:
sage/rings/number_field
Files:
3 edited

Legend:

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

    r7479 r7725  
    4242import sage.rings.arith as arith 
    4343import sage.misc.misc as misc 
     44from sage.rings.finite_field import FiniteField 
    4445 
    4546import number_field 
     
    5152from sage.structure.element import generic_power 
    5253from sage.structure.factorization import Factorization 
     54from sage.structure.sequence import Sequence 
    5355 
    5456QQ = rational_field.RationalField() 
     
    200202            Number Field in a with defining polynomial x^3 + 389 
    201203            sage: I = K.factor_integer(17)[0][0]; I 
    202             Fractional ideal (-100*a^2 + 730*a - 5329) 
     204            Fractional ideal (100*a^2 - 730*a + 5329) 
    203205            sage: hnf = I.pari_hnf(); hnf 
    204206            [17, 0, 13; 0, 17, 8; 0, 0, 1] 
     
    327329                self.__pari_hnf = nf.idealadd(self.__pari_hnf, ideal) 
    328330            return self.__pari_hnf 
     331 
     332    def basis(self): 
     333        """ 
     334        Return an immutable sequence of elements of this ideal (note: 
     335        their parent is the number field) that form a basis for this 
     336        ideal viewed as a ZZ-module. 
     337 
     338        OUTPUT: 
     339            basis -- an immutable sequence. 
     340 
     341        EXAMPLES: 
     342            sage: K.<z> = CyclotomicField(7) 
     343            sage: I = K.factor_integer(11)[0][0] 
     344            sage: I.basis() 
     345            [11, 11*z, 11*z^2, z^3 + 5*z^2 + 4*z + 10, z^4 + z^2 + z + 5, z^5 + z^4 + z^3 + 2*z^2 + 6*z + 5] 
     346 
     347        An example of a non-integral ideal. 
     348            sage: J = 1/I; J 
     349            Fractional ideal (2/11*z^5 + 2/11*z^4 + 3/11*z^3 + 2/11) 
     350            sage: J.basis() 
     351            [1, z, z^2, 1/11*z^3 + 7/11*z^2 + 6/11*z + 10/11, 1/11*z^4 + 1/11*z^2 + 1/11*z + 7/11, 1/11*z^5 + 1/11*z^4 + 1/11*z^3 + 2/11*z^2 + 8/11*z + 7/11] 
     352        """ 
     353        try: 
     354            return self.__basis 
     355        except AttributeError: 
     356            pass 
     357        hnf = self.pari_hnf() 
     358        v = self.__elements_from_hnf(hnf) 
     359        O = self.number_field().maximal_order() 
     360        self.__basis = Sequence(v, immutable=True) 
     361        return self.__basis 
     362 
     363    def free_module(self): 
     364        """ 
     365        Return the free ZZ-module contained in the vector space 
     366        associated to the ambient number field, that corresponds 
     367        to this ideal. 
     368 
     369        EXAMPLES: 
     370            sage: K.<z> = CyclotomicField(7) 
     371            sage: I = K.factor_integer(11)[0][0]; I 
     372            Fractional ideal (-2*z^4 - 2*z^2 - 2*z + 1) 
     373            sage: A = I.free_module(); A 
     374            Free module of degree 6 and rank 6 over Integer Ring 
     375            User basis matrix: 
     376            [11  0  0  0  0  0] 
     377            [ 0 11  0  0  0  0] 
     378            [ 0  0 11  0  0  0] 
     379            [10  4  5  1  0  0] 
     380            [ 5  1  1  0  1  0] 
     381            [ 5  6  2  1  1  1] 
     382 
     383        The ideal doesn't have to be integral: 
     384            sage: J = I^(-1) 
     385            sage: B = J.free_module(); B 
     386            Free module of degree 6 and rank 6 over Integer Ring 
     387            User basis matrix: 
     388            [    1     0     0     0     0     0] 
     389            [    0     1     0     0     0     0] 
     390            [    0     0     1     0     0     0] 
     391            [10/11  6/11  7/11  1/11     0     0] 
     392            [ 7/11  1/11  1/11     0  1/11     0] 
     393            [ 7/11  8/11  2/11  1/11  1/11  1/11] 
     394 
     395        This also works for relative extensions: 
     396            sage: K.<a,b> = NumberField([x^2 + 1, x^2 + 2]) 
     397            sage: I = K.fractional_ideal(4) 
     398            sage: I.free_module() 
     399            Free module of degree 4 and rank 4 over Integer Ring 
     400            User basis matrix: 
     401            [  4   0   0   0] 
     402            [ -3   7  -1   1] 
     403            [  3   7   1   1] 
     404            [  0 -10   0  -2] 
     405            sage: J = I^(-1); J.free_module() 
     406            Free module of degree 4 and rank 4 over Integer Ring 
     407            User basis matrix: 
     408            [  1/4     0     0     0] 
     409            [-3/16  7/16 -1/16  1/16] 
     410            [ 3/16  7/16  1/16  1/16] 
     411            [    0  -5/8     0  -1/8] 
     412 
     413        An example of intersecting ideals by intersecting free modules. 
     414            sage: K.<a> = NumberField(x^3 + x^2 - 2*x + 8) 
     415            sage: I = K.factor_integer(2) 
     416            sage: p1 = I[0][0]; p2 = I[1][0] 
     417            sage: N = p1.free_module().intersection(p2.free_module()); N 
     418            Free module of degree 3 and rank 3 over Integer Ring 
     419            Echelon basis matrix: 
     420            [  1 1/2 1/2] 
     421            [  0   1   1] 
     422            [  0   0   2] 
     423            sage: N.index_in(p1.free_module()).abs() 
     424            2 
     425        """ 
     426        try: 
     427            return self.__free_module 
     428        except AttributeError: 
     429            pass 
     430        M = basis_to_module(self.basis(), self.number_field()) 
     431        self.__free_module = M 
     432        return M 
    329433 
    330434    def divides(self, other): 
     
    699803            return ZZ(self._pari_prime.getattr('e')) 
    700804        raise ValueError, "the ideal (= %s) is not prime"%self 
     805 
     806    def _p_quotient(self, p): 
     807        """ 
     808        This is an internal technical function that is used for example for 
     809        computing the quotient of the ring of integers by a prime ideal. 
     810 
     811        INPUT: 
     812            p -- a prime number contained in self. 
     813 
     814        OUTPUT: 
     815            V -- a vector space of characteristic p 
     816            quo -- a partially defined quotient homomorphism from the 
     817                   ambient number field to V 
     818            lift -- a section of quo. 
     819         
     820        EXAMPLES: 
     821            sage: K.<i> = NumberField(x^2 + 1); O = K.maximal_order() 
     822            sage: I = K.factor_integer(3)[0][0] 
     823            sage: Q, quo, lift = I._p_quotient(3); Q 
     824            Vector space quotient V/W of dimension 2 over Finite Field of size 3 where 
     825            V: Vector space of dimension 2 over Finite Field of size 3 
     826            W: Vector space of degree 2 and dimension 0 over Finite Field of size 3 
     827            Basis matrix: 
     828            [] 
     829             
     830        We do an example with a split prime and show byother the quo and lift maps: 
     831            sage: K.<i> = NumberField(x^2 + 1); O = K.maximal_order() 
     832            sage: I = K.factor_integer(5)[0][0] 
     833            sage: Q,quo,lift = I._p_quotient(5) 
     834            sage: lift(quo(i)) 
     835            3 
     836            sage: lift(quo(i)) - i in I 
     837            True 
     838            sage: quo(lift(Q.0)) 
     839            (1) 
     840            sage: Q.0 
     841            (1) 
     842            sage: Q 
     843            Vector space quotient V/W of dimension 1 over Finite Field of size 5 where 
     844            V: Vector space of dimension 2 over Finite Field of size 5 
     845            W: Vector space of degree 2 and dimension 1 over Finite Field of size 5 
     846            Basis matrix: 
     847            [1 3] 
     848            sage: quo 
     849            Partially defined quotient map from Number Field in i with defining polynomial x^2 + 1 to an explicit vector space representation for the quotient of the ring of integers by (p,I) for the ideal I=Fractional ideal (-i - 2). 
     850            sage: lift 
     851            Lifting map to Order in Number Field in i with defining polynomial x^2 + 1 from quotient of integers by Fractional ideal (-i - 2) 
     852        """ 
     853        return quotient_char_p(self, p) 
    701854 
    702855    def residue_field(self, names=None): 
     
    8491002            return False 
    8501003    return True 
     1004 
     1005 
     1006 
     1007def basis_to_module(B, K): 
     1008    """ 
     1009    Given a basis B of elements for a ZZ-submodule of a number field K, return 
     1010    the corresponding ZZ-submodule. 
     1011 
     1012    EXAMPLES: 
     1013        sage: K.<w> = NumberField(x^4 + 1) 
     1014        sage: from sage.rings.number_field.number_field_ideal import basis_to_module 
     1015        sage: basis_to_module([K.0, K.0^2 + 3], K) 
     1016        Free module of degree 4 and rank 2 over Integer Ring 
     1017        User basis matrix: 
     1018        [0 1 0 0] 
     1019        [3 0 1 0] 
     1020    """ 
     1021    V, from_V, to_V = K.absolute_vector_space() 
     1022    M = ZZ**(V.dimension()) 
     1023    C = [to_V(b) for b in B] 
     1024    return M.span_of_basis(C) 
     1025         
     1026 
     1027class QuotientMap: 
     1028    def __init__(self, K, M_OK_change, Q, I): 
     1029        self.__M_OK_change = M_OK_change 
     1030        self.__Q = Q 
     1031        self.__K = K 
     1032        self.__I = I 
     1033        self.__L, self.__from_L, self.__to_L = K.absolute_vector_space() 
     1034 
     1035    def __call__(self, x): 
     1036        v = self.__to_L(x) 
     1037        w = v * self.__M_OK_change 
     1038        return self.__Q( list(w) ) 
     1039 
     1040    def __repr__(self): 
     1041        return "Partially defined quotient map from %s to an explicit vector space representation for the quotient of the ring of integers by (p,I) for the ideal I=%s."%(self.__K, self.__I) 
     1042     
     1043class LiftMap: 
     1044    def __init__(self, OK, M_OK_map, Q, I): 
     1045        self.__I = I 
     1046        self.__OK = OK 
     1047        self.__Q = Q 
     1048        self.__M_OK_map = M_OK_map 
     1049     
     1050    def __call__(self, x): 
     1051        # This lifts to OK tensor F_p 
     1052        v = self.__Q.lift(x) 
     1053        # This lifts to ZZ^n (= OK) 
     1054        w = v.lift() 
     1055        # Write back in terms of K 
     1056        z = w * self.__M_OK_map 
     1057        return self.__OK(z.list()) 
     1058 
     1059    def __repr__(self): 
     1060        return "Lifting map to %s from quotient of integers by %s"%(self.__OK, self.__I) 
     1061 
     1062def quotient_char_p(I, p): 
     1063    """ 
     1064    Given an integral ideal I that contains a prime number p, compute 
     1065    a vector space V = (OK mod p) / (I mod p), along with a 
     1066    homomorphism OK --> V and a section V --> OK. 
     1067 
     1068    EXAMPLES: 
     1069        sage: from sage.rings.number_field.number_field_ideal import quotient_char_p 
     1070        
     1071        sage: K.<i> = NumberField(x^2 + 1); O = K.maximal_order(); I = K.fractional_ideal(15) 
     1072        sage: quotient_char_p(I, 5)[0] 
     1073        Vector space quotient V/W of dimension 2 over Finite Field of size 5 where 
     1074        V: Vector space of dimension 2 over Finite Field of size 5 
     1075        W: Vector space of degree 2 and dimension 0 over Finite Field of size 5 
     1076        Basis matrix: 
     1077        [] 
     1078        sage: quotient_char_p(I, 3)[0] 
     1079        Vector space quotient V/W of dimension 2 over Finite Field of size 3 where 
     1080        V: Vector space of dimension 2 over Finite Field of size 3 
     1081        W: Vector space of degree 2 and dimension 0 over Finite Field of size 3 
     1082        Basis matrix: 
     1083        [] 
     1084 
     1085        sage: I = K.factor_integer(13)[0][0]; I 
     1086        Fractional ideal (-3*i - 2) 
     1087        sage: I.residue_class_degree() 
     1088        1 
     1089        sage: quotient_char_p(I, 13)[0] 
     1090        Vector space quotient V/W of dimension 1 over Finite Field of size 13 where 
     1091        V: Vector space of dimension 2 over Finite Field of size 13 
     1092        W: Vector space of degree 2 and dimension 1 over Finite Field of size 13 
     1093        Basis matrix: 
     1094        [1 8] 
     1095    """ 
     1096    if not I.is_integral(): 
     1097        raise ValueError, "I must be an integral ideal." 
     1098     
     1099    K    = I.number_field() 
     1100    OK   = K.maximal_order(p)  # really only need a p-maximal order. 
     1101    M_OK = OK.free_module() 
     1102    M_I  = I.free_module() 
     1103 
     1104    # Now we have to quite explicitly find a way to compute 
     1105    # with OK / I viewed as a quotient of two F_p vector space, 
     1106    # and itself viewed as an F_p vector space. 
     1107 
     1108    # Step 1. Write each basis vector for I (as a ZZ-module) 
     1109    # in terms of the basis for OK. 
     1110    B_I = M_I.basis() 
     1111    M_OK_mat = M_OK.basis_matrix() 
     1112    M_OK_change = M_OK_mat**(-1) 
     1113    B_I_in_terms_of_M = M_I.basis_matrix() * M_OK_change 
     1114     
     1115    # Step 2. Define "M_OK mod p" to just be (F_p)^n and 
     1116    # "M_I mod p" to be the reduction mod p of the elements 
     1117    # compute in step 1. 
     1118    n = K.degree() 
     1119    k = FiniteField(p) 
     1120    M_OK_modp = k**n 
     1121    B_mod = B_I_in_terms_of_M.change_ring(k) 
     1122    M_I_modp = M_OK_modp.span(B_mod.row_space()) 
     1123     
     1124    # Step 3. Compute the quotient of these two F_p vector space. 
     1125    Q = M_OK_modp.quotient(M_I_modp) 
     1126     
     1127    # Step 4. Now we get the maps we need from the above data. 
     1128    K_to_Q = QuotientMap(K, M_OK_change, Q, I) 
     1129    Q_to_OK = LiftMap(OK, M_OK_mat, Q, I) 
     1130    return Q, K_to_Q, Q_to_OK 
     1131 
     1132     
     1133     
  • sage/rings/number_field/number_field_ideal_rel.py

    r6990 r7725  
    2323 
    2424from number_field_ideal import NumberFieldIdeal, convert_from_zk_basis 
     25 
     26import sage.rings.rational_field as rational_field 
     27QQ = rational_field.RationalField() 
    2528 
    2629class NumberFieldIdeal_rel(NumberFieldIdeal): 
     
    99102        """ 
    100103        Return the multiplicative inverse of self.  Call with ~self. 
     104 
     105        EXAMPLES: 
     106            sage: K.<a,b> = NumberField([x^2 + 1, x^2 + 2]) 
     107            sage: I = K.fractional_ideal(4) 
     108            sage: I^(-1) 
     109            Fractional ideal (1/4) 
     110            sage: I * I^(-1) 
     111            Fractional ideal (1) 
    101112        """ 
    102113        if self.is_zero(): 
  • sage/rings/number_field/order.py

    r7715 r7725  
    364364        """ 
    365365        raise NotImplementedError 
     366 
     367    def free_module(self): 
     368        """ 
     369        Return the free ZZ-module contained in the vector space 
     370        associated to the ambient number field, that corresponds 
     371        to this ideal. 
     372 
     373        EXAMPLES: 
     374            sage: K.<a> = NumberField(x^3 + x^2 - 2*x + 8) 
     375            sage: O = K.maximal_order(); O.basis() 
     376            [1, 1/2*a^2 + 1/2*a, a^2] 
     377            sage: O.free_module() 
     378            Free module of degree 3 and rank 3 over Integer Ring 
     379            User basis matrix: 
     380            [  1   0   0] 
     381            [  0 1/2 1/2] 
     382            [  0   0   1] 
     383 
     384        An example in a relative extension.  Notice that the module is a ZZ-module in the 
     385        absolute_field associated to the relative field: 
     386            sage: K.<a,b> = NumberField([x^2 + 1, x^2 + 2]) 
     387            sage: O = K.maximal_order(); O.basis() 
     388            [(-3/2*b - 5)*a + 7/2*b - 2, (-3)*a + 2*b, (-2*b)*a - 3, (-7)*a + 5*b] 
     389            sage: O.free_module() 
     390            Free module of degree 4 and rank 4 over Integer Ring 
     391            User basis matrix: 
     392            [1/4 1/4 3/4 3/4] 
     393            [  0 1/2   0 1/2] 
     394            [  0   0   1   0] 
     395            [  0   0   0   1] 
     396        """ 
     397        try: 
     398            return self.__free_module 
     399        except AttributeError: 
     400            pass 
     401        from number_field_ideal import basis_to_module 
     402        M = basis_to_module(self.basis(), self.number_field()) 
     403        self.__free_module = M 
     404        return M 
    366405 
    367406    def ring_generators(self): 
Note: See TracChangeset for help on using the changeset viewer.