Ticket #1183: trac-1183-supportforquo-step1and2.patch

File trac-1183-supportforquo-step1and2.patch, 15.6 KB (added by was, 15 years ago)
  • sage/rings/number_field/number_field_ideal.py

    # HG changeset patch
    # User William Stein <wstein@gmail.com>
    # Date 1196588793 28800
    # Node ID 54cdaf20dc6ff93f16ba63be50a62efe38ea2476
    # Parent  cc5379f06ce41f65bc84f5121fb91ee73caf8b10
    Trac #1183 -- added support for computing O_K / I.
    
    diff -r cc5379f06ce4 -r 54cdaf20dc6f sage/rings/number_field/number_field_ideal.py
    a b import sage.rings.integer as integer 
    4141import sage.rings.integer as integer
    4242import sage.rings.arith as arith
    4343import sage.misc.misc as misc
     44from sage.rings.finite_field import FiniteField
    4445
    4546import number_field
    4647import number_field_element
    from sage.misc.misc import prod 
    5051from sage.misc.misc import prod
    5152from sage.structure.element import generic_power
    5253from sage.structure.factorization import Factorization
     54from sage.structure.sequence import Sequence
    5355
    5456QQ = rational_field.RationalField()
    5557ZZ = integer_ring.IntegerRing()
    class NumberFieldIdeal(Ideal_fractional) 
    199201            sage: K.<a> = NumberField(x^3 + 389); K
    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]
    205207            sage: I._NumberFieldIdeal__elements_from_hnf(hnf)
    class NumberFieldIdeal(Ideal_fractional) 
    326328            for ideal in hnflist:
    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):
    331435        """
    class NumberFieldIdeal(Ideal_fractional) 
    699803            return ZZ(self._pari_prime.getattr('e'))
    700804        raise ValueError, "the ideal (= %s) is not prime"%self
    701805
     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)
     854
    702855    def residue_field(self, names=None):
    703856        """
    704857        Return the residue class field of this ideal, which must
    def is_pari_zero_vector(z): 
    8481001        if a:
    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

    diff -r cc5379f06ce4 -r 54cdaf20dc6f sage/rings/number_field/number_field_ideal_rel.py
    a b AUTHOR: 
    2222#*****************************************************************************
    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):
    2730    """
    class NumberFieldIdeal_rel(NumberFieldId 
    98101    def __invert__(self):
    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():
    103114            raise ZeroDivisionError
  • sage/rings/number_field/order.py

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