Ticket #11304: trac_11304_S_class_groups.patch

File trac_11304_S_class_groups.patch, 16.7 KB (added by fwclarke, 8 years ago)

apply after patches from #11234

  • sage/rings/number_field/class_group.py

    # HG changeset patch
    # User Francis Clarke <francis.w.clarke@gmail.com>
    # Date 1307086682 -3600
    # Node ID 68cda424de91aced12647ee718a10e23e13b31c4
    # Parent  55754e50e2e3d075c26d5070c78ab09a57378ceb
    Trac 11304: S-class groups
    
    diff -r 55754e50e2e3 -r 68cda424de91 sage/rings/number_field/class_group.py
    a b  
    436436            (2, 1/2*w - 1/2)
    437437        """
    438438        return self.ideal().gens()
    439        
     439
     440
    440441class SClassGroup(ClassGroup):
    441442    r"""
    442443    The S-class group of a number field.
    443444    """
    444     def __init__(self, invariants, names, number_field, gens, S):
     445
     446    def __init__(self, invariants, names, number_field, gens, S, proof=True):
    445447        r"""
    446448        Create an S-class group.
    447449
     
    450452            sage: K.<a> = QuadraticField(-14)
    451453            sage: I = K.ideal(2,a)                 
    452454            sage: S = (I,)
    453             sage: CS = K.S_class_group(S);CS
    454             Class group of order 2 with structure C2 of Number Field in a with defining polynomial x^2 + 14
     455            sage: K.S_class_group(S)
     456            S-class group of order 2 with structure C2 of Number Field in a with defining polynomial x^2 + 14
     457            sage: K.<a> = QuadraticField(-105)
     458            sage: K.S_class_group([K.ideal(13, a + 8)])
     459            S-class group of order 4 with structure C2 x C2 of Number Field in a with defining polynomial x^2 + 105
    455460        """
    456         ClassGroup.__init__(self, invariants, names, number_field, gens)
     461        AbelianGroup_class.__init__(self, len(invariants), invariants, names)
     462        self._proof_flag = proof
     463        self.__number_field = number_field
    457464        self.__S = S
     465        self.__gens = Sequence([SFractionalIdealClass(self, x) for x in gens], immutable=True,
     466                               universe=self, check=False)
     467
    458468    def S(self):
    459469        r"""
    460470        Return the set (or rather tuple) of primes used to define this class group.
     
    465475            sage: I = K.ideal(2,a)                 
    466476            sage: S = (I,)
    467477            sage: CS = K.S_class_group(S);CS
    468             Class group of order 2 with structure C2 of Number Field in a with defining polynomial x^2 + 14
     478            S-class group of order 2 with structure C2 of Number Field in a with defining polynomial x^2 + 14
    469479            sage: T = tuple([])
    470480            sage: CT = K.S_class_group(T);CT
    471             Class group of order 4 with structure C4 of Number Field in a with defining polynomial x^2 + 14
     481            S-class group of order 4 with structure C4 of Number Field in a with defining polynomial x^2 + 14
    472482            sage: CS.S()
    473483            (Fractional ideal (2, a),)
    474484            sage: CT.S()
    475485            ()
    476486        """
    477487        return self.__S
     488
    478489    def __call__(self, *args, **kwds):
    479490        r"""
    480491        Call method.
     
    488499            sage: J = K.ideal(7,a)
    489500            sage: G = K.ideal(3,a+1)
    490501            sage: CS(I)
    491             Class of the Fractional ideal (2, a) in the S-class group of Number Field in a with defining polynomial x^2 + 14
     502            Trivial S-ideal class
    492503            sage: CS(J)
    493             Class of the Fractional ideal (7, a) in the S-class group of Number Field in a with defining polynomial x^2 + 14
     504            Trivial S-ideal class
    494505            sage: CS(G)
    495             Class of the Fractional ideal (3, a + 1) in the S-class group of Number Field in a with defining polynomial x^2 + 14
    496 
     506            Fractional S-ideal class (3, a + 1)
    497507        """
    498508        return Group.__call__(self, *args, **kwds)
     509
    499510    def _element_constructor_(self, *args, **kwds):
    500511        r"""
    501512        Create an element of this class group from the given data.
     
    509520            sage: J = K.ideal(7,a)
    510521            sage: G = K.ideal(3,a+1)
    511522            sage: CS(I)
    512             Class of the Fractional ideal (2, a) in the S-class group of Number Field in a with defining polynomial x^2 + 14
     523            Trivial S-ideal class
    513524            sage: CS(J)
    514             Class of the Fractional ideal (7, a) in the S-class group of Number Field in a with defining polynomial x^2 + 14
     525            Trivial S-ideal class
    515526            sage: CS(G)
    516             Class of the Fractional ideal (3, a + 1) in the S-class group of Number Field in a with defining polynomial x^2 + 14
    517 
     527            Fractional S-ideal class (3, a + 1)
    518528        """
    519529        if isinstance(args[0], FractionalIdealClass):
    520530            return SFractionalIdealClass(self, args[0].ideal())
     
    523533            if I.is_zero(): raise TypeError, "The zero ideal is not a fractional ideal"
    524534            return SFractionalIdealClass(self, I)
    525535
    526 class SFractionalIdealClass(AbelianGroupElement):
     536    def gens(self):
     537        r"""
     538        Return generators for the S-class group.
     539
     540        EXAMPLES::
     541
     542            sage: K.<a> = QuadraticField(-14)
     543            sage: S = K.primes_above(2)
     544            sage: K.S_class_group(S).gens()   # random gens (platform dependent)
     545            [Fractional S-ideal class (3, a + 2)]
     546        """
     547        return self.__gens
     548
     549    def gen(self, i=0):
     550        r"""
     551        Return the i-th generator for this class group.
     552
     553        EXAMPLES::
     554
     555            sage: K.<a> = QuadraticField(-974)
     556            sage: CS = K.S_class_group(K.primes_above(2)); CS
     557            S-class group of order 18 with structure C6 x C3 of Number Field in a with defining polynomial x^2 + 974
     558            sage: CS.gen(0) # random
     559            Fractional S-ideal class (3, a + 2)
     560            sage: CS.gen(1) # random
     561            Fractional S-ideal class (31, a + 24)
     562        """
     563        if i < 0 or i >= len(self.__gens):
     564            raise IndexError
     565        return self.__gens[i]
     566
     567    def _repr_(self):
     568        r"""
     569        Return string representation of this S-class group.
     570
     571        EXAMPLES::
     572
     573            sage: K.<a> = QuadraticField(-14)
     574            sage: CS = K.S_class_group(K.primes_above(2))
     575            sage: CS._repr_()
     576            'S-class group of order 2 with structure C2 of Number Field in a with defining polynomial x^2 + 14'
     577        """
     578        s = 'S-class group of order %s ' % self.order()
     579        if self.order() > 1:
     580            s += 'with structure %s ' % self._group_notation(self.invariants())
     581        s += 'of %s' % self.number_field()
     582        return s
     583
     584    def number_field(self):
     585        r"""
     586        Return the number field that this S-class group is attached to.
     587       
     588        EXAMPLES::
     589
     590            sage: K.<a> = QuadraticField(-14)
     591            sage: CS = K.S_class_group(K.primes_above(2))
     592            sage: CS.number_field()
     593            Number Field in a with defining polynomial x^2 + 14
     594        """
     595        return self.__number_field
     596
     597
     598class SFractionalIdealClass(FractionalIdealClass):
    527599    r"""
    528600    An S-fractional ideal class in a number field for a tuple of primes S.
    529601    """
    530     def __init__(self, parent, idl, element=None):
     602
     603    def __init__(self, parent, ideal, element=None):
    531604        r"""
    532605        Returns the S-ideal class of this fractional ideal.
    533606
     
    540613            sage: J = K.ideal(7,a)
    541614            sage: G = K.ideal(3,a+1)
    542615            sage: CS(I)
    543             Class of the Fractional ideal (2, a) in the S-class group of Number Field in a with defining polynomial x^2 + 14
     616            Trivial S-ideal class
    544617            sage: CS(J)
    545             Class of the Fractional ideal (7, a) in the S-class group of Number Field in a with defining polynomial x^2 + 14
     618            Trivial S-ideal class
    546619            sage: CS(G)
    547             Class of the Fractional ideal (3, a + 1) in the S-class group of Number Field in a with defining polynomial x^2 + 14
     620            Fractional S-ideal class (3, a + 1)
     621        """
     622        self.__ideal = ideal
     623        if element is None:
     624            element = ideal._S_ideal_class_log(parent.S())
     625        AbelianGroupElement.__init__(self, parent, element)
    548626
    549         """
    550         self.__idl = idl
    551         if element is None:
    552             element = idl._S_ideal_class_log(parent.S())
    553         AbelianGroupElement.__init__(self, parent, element)
    554627    def _repr_(self):
    555628        r"""
    556629        Returns a string representation of the S-ideal class of this fractional ideal.
     
    559632       
    560633            sage: K.<a> = QuadraticField(-14)
    561634            sage: I = K.ideal(2,a)                 
     635            sage: J = K.ideal(3, a + 2)
    562636            sage: S = (I,)
    563637            sage: CS = K.S_class_group(S)
    564             sage: CS(I)
    565             Class of the Fractional ideal (2, a) in the S-class group of Number Field in a with defining polynomial x^2 + 14
     638            sage: CS(J)
     639            Fractional S-ideal class (3, a + 2)
     640            sage: CS(J^2)
     641            Trivial S-ideal class
    566642        """
    567         return 'Class of the %s in the S-class group of %s'%( self.ideal(), self.parent().number_field())
     643        if not any(self.list()):
     644            return 'Trivial S-ideal class'
     645        return 'Fractional S-ideal class %s' % self.__ideal._repr_short()
     646
    568647    def ideal(self):
    569648        r"""
    570649        Returns a representative ideal for this S-ideal class.
     
    583662            Fractional ideal (7, a)
    584663            sage: CS(G).ideal()
    585664            Fractional ideal (3, a + 1)
     665        """
     666        return self.__ideal
    586667
    587         """
    588         return self.__idl
    589668    def order(self):
    590669        r"""
    591670        Finds the order of the given S-ideal class.
     
    606685            2
    607686        """
    608687        return LCM([e.additive_order() for e in self.list()])
     688
    609689    def _mul_(self, other):
    610690        r"""
    611691        Multiplies together two S-ideal classes.
     
    618698            sage: CS = K.S_class_group(S)
    619699            sage: G = K.ideal(3,a+1)
    620700            sage: CS(G)*CS(G)
    621             Class of the Fractional ideal (2, a) in the S-class group of Number Field in a with defining polynomial x^2 + 14
    622 
     701            Trivial S-ideal class
    623702        """
    624703
    625704        m = AbelianGroupElement._mul_(self, other)
    626705        return SFractionalIdealClass(self.parent(), (self.ideal() * other.ideal()).reduce_equiv(), m.list())
     706
    627707    def inverse(self):
    628708        r"""
    629709        Finds the inverse of the given S-ideal class.
     
    636716            sage: CS = K.S_class_group(S)
    637717            sage: G = K.ideal(3,a+1)
    638718            sage: CS(G).inverse()
    639             Class of the Fractional ideal class (3, a + 2) in the S-class group of Number Field in a with defining polynomial x^2 + 14
    640 
     719            Fractional S-ideal class (3, a + 2)
    641720        """
    642721        m = AbelianGroupElement.inverse(self)
    643         return SFractionalIdealClass(self.parent(), self.parent().number_field().class_group()(self.ideal()).inverse() , m.list())
    644 
    645 
    646 
     722        inv_ideal = self.parent().number_field().class_group()(self.ideal()).inverse().ideal()
     723        return SFractionalIdealClass(self.parent(), inv_ideal , m.list())
  • sage/rings/number_field/number_field.py

    diff -r 55754e50e2e3 -r 68cda424de91 sage/rings/number_field/number_field.py
    a b  
    28922892       
    28932893            sage: K.<a> = QuadraticField(-5)
    28942894            sage: K.S_class_group([])
    2895             Class group of order 2 with structure C2 of Number Field in a with defining polynomial x^2 + 5
     2895            S-class group of order 2 with structure C2 of Number Field in a with defining polynomial x^2 + 5
    28962896       
    28972897        When we include the prime `(2, a+1)`, the S-class group becomes
    28982898        trivial::
    28992899       
    29002900            sage: K.S_class_group([K.ideal(2,a+1)])
    2901             Class group of order 1 of Number Field in a with defining polynomial x^2 + 5
     2901            S-class group of order 1 of Number Field in a with defining polynomial x^2 + 5
    29022902
    29032903        TESTS::
    29042904
     
    29062906            sage: I = K.ideal(2,a)                 
    29072907            sage: S = (I,)
    29082908            sage: CS = K.S_class_group(S);CS
    2909             Class group of order 2 with structure C2 of Number Field in a with defining polynomial x^2 + 14
     2909            S-class group of order 2 with structure C2 of Number Field in a with defining polynomial x^2 + 14
    29102910            sage: T = tuple([])
    29112911            sage: CT = K.S_class_group(T);CT
    2912             Class group of order 4 with structure C4 of Number Field in a with defining polynomial x^2 + 14
     2912            S-class group of order 4 with structure C4 of Number Field in a with defining polynomial x^2 + 14
    29132913            sage: K.class_group()
    29142914            Class group of order 4 with structure C4 of Number Field in a with defining polynomial x^2 + 14
    2915 
    2916         """
    2917         proof = proof_flag(proof) 
    2918         Slist = self._S_class_group_and_units(tuple(S), proof = proof)[1]
    2919         return SClassGroup([s[1] for s in Slist],names,self,[s[0] for s in Slist],S)
     2915        """
     2916        proof = proof_flag(proof)
     2917        if all(P.is_principal() for P in S):
     2918            C = self.class_group(proof=proof)
     2919            Slist = zip([g.ideal() for g in C.gens()], C.invariants())
     2920        else:
     2921            Slist = self._S_class_group_and_units(tuple(S), proof=proof)[1]
     2922        return SClassGroup([s[1] for s in Slist], names, self, [s[0] for s in Slist], S)
    29202923
    29212924    def S_units(self, S, proof=True):
    29222925        """
     
    29942997        pari_cyc = result[4][1]
    29952998        pari_gens = result[4][2]
    29962999        clgp_gens = []
    2997         for k in range(0,len(pari_cyc)):
     3000        for k in range(len(pari_cyc)):
    29983001            order = ZZ(pari_cyc[k])
    29993002            if order > 1: # since some generators are given "of order 1"
    30003003                I = self.ideal(pari_gens[k])
     
    30203023            sage: K._S_class_group_quotient_matrix(())
    30213024            [1 0]
    30223025            [0 1]
     3026            sage: K.<a> = QuadraticField(-105)
     3027            sage: K._S_class_group_quotient_matrix((K.ideal(11, a + 4),))
     3028            [0 0]
     3029            [1 0]
     3030            [0 1]
    30233031        """
    30243032        from sage.matrix.constructor import matrix
    3025         clgp_gens = self._S_class_group_and_units(S)[1]
    3026         C = self.class_group()
    3027         a = len(clgp_gens)
    3028         c = C.ngens()
    3029         M = matrix(ZZ, [C(x).list() for x in ([u[0] for u in clgp_gens] + list(S))])
    3030         return (M.hermite_form(transformation=True)[1][:a,:c]).transpose()
     3033        S_clgp_gens = self._S_class_group_and_units(S)[1]
     3034        a = len(S_clgp_gens)
     3035        c = self.class_group().ngens()
     3036        M = [u[0]._ideal_class_log() for u in S_clgp_gens]
     3037        M += [x._ideal_class_log() for x in S]
     3038        M = matrix(ZZ, M)
     3039        A, Q = M.hermite_form(transformation=True)
     3040        assert A[:c] == 1 and A[c:] == 0
     3041        return Q[:c, :a]
    30313042       
    30323043    def selmer_group(self, S, m, proof=True):
    30333044        r"""
  • sage/rings/number_field/number_field_ideal.py

    diff -r 55754e50e2e3 -r 68cda424de91 sage/rings/number_field/number_field_ideal.py
    a b  
    10661066            return self._ideal_class_log(proof)
    10671067        except KeyError:
    10681068            bnf = self.number_field().pari_bnf(proof)
    1069             v = bnf.bnfisprincipal(self.pari_hnf())
    1070             self.__ideal_class_log[proof] = list(v[0])
     1069            v = bnf.bnfisprincipal(self.pari_hnf(), flag=0)
     1070            self.__ideal_class_log[proof] = list(v)
    10711071            return self.__ideal_class_log[proof]
    10721072
    10731073    def _S_ideal_class_log(self, S):
     
    10781078
    10791079            sage: K.<a> = QuadraticField(-14)
    10801080            sage: S = K.primes_above(2)
    1081             sage: I = K.ideal(3, a-1)
     1081            sage: I = K.ideal(3, a + 1)
    10821082            sage: I._S_ideal_class_log(S)
    10831083            [1]
    10841084            sage: I._S_ideal_class_log([])
    1085             [1]
    1086             sage: I._ideal_class_log()
    1087             [1]
     1085            [3]
     1086            sage: K.<a> = QuadraticField(-974)
     1087            sage: S = K.primes_above(2)
     1088            sage: [P._S_ideal_class_log(S) for P in K.primes_above(11)]
     1089            [[5, 2], [1, 1]]
    10881090        """
    10891091        from sage.modules.free_module_element import vector
    10901092        from sage.rings.finite_rings.integer_mod_ring import Zmod
    10911093        v = vector(ZZ, self._ideal_class_log())
    1092         D = self.number_field()._S_class_group_and_units(tuple(S))
    1093         M = self.number_field()._S_class_group_quotient_matrix(tuple(S))
    1094         L = (v * M).list()
    1095         invs = [x[1] for x in D[1]]
     1094        if all(P.is_principal() for P in S):
     1095            L = v.list()
     1096            invs = self.number_field().class_group().invariants()
     1097        else:
     1098            M = self.number_field()._S_class_group_quotient_matrix(tuple(S))
     1099            L = (v * M).list()
     1100            D = self.number_field()._S_class_group_and_units(tuple(S))[1]
     1101            invs = [x[1] for x in D]
    10961102        return [Zmod(invs[i])(L[i]) for i in xrange(len(L))]
    10971103
    10981104    def is_zero(self):