Ticket #9244: trac_9244_ver4.patch
File trac_9244_ver4.patch, 16.0 KB (added by , 13 years ago) |
---|
-
sage/rings/number_field/class_group.py
# HG changeset patch # User David Loeffler <d.loeffler.01@cantab.net> # Date 1277453061 -3600 # Node ID 9d33ffed40c71cf3199bfb91e2ca83ee2523da0f # Parent 8dec8b43ccca5f104b1e280cb33c8f4c2c1b8f85 #9244: technical improvements to number field class groups diff -r 8dec8b43ccca -r 9d33ffed40c7 sage/rings/number_field/class_group.py
a b 1 """1 r""" 2 2 Class Groups of Number Fields 3 3 4 An element of a class group is stored as a pair consisting of both an explicit 5 ideal in that ideal class, and a list of exponents giving that ideal class in 6 terms of the generators of the parent class group. These can be accessed with 7 the ``ideal()`` and ``list()`` methods respectively. 8 4 9 EXAMPLES:: 5 10 6 11 sage: K.<a> = NumberField(x^2 + 23) … … 8 13 Fractional ideal class (2, 1/2*a - 1/2) 9 14 sage: J = I * I; J 10 15 Fractional ideal class (2, 1/2*a + 1/2) 16 sage: J.list() 17 [2] 11 18 sage: O = K.OK(); O 12 19 Maximal Order in Number Field in a with defining polynomial x^2 + 23 13 20 sage: O*(2, 1/2*a + 1/2) … … 19 26 """ 20 27 21 28 from sage.groups.abelian_gps.abelian_group import AbelianGroup_class 22 23 29 from sage.structure.sequence import Sequence 24 25 from sage.structure.element import MultiplicativeGroupElement 30 from sage.structure.element import MonoidElement 31 from sage.groups.abelian_gps.abelian_group_element import AbelianGroupElement 32 from sage.groups.group import Group 26 33 27 34 class ClassGroup(AbelianGroup_class): 28 """35 r""" 29 36 The class group of a number field. 30 37 """ 31 def __init__(self, invariants, names, number_field, gens ):32 """38 def __init__(self, invariants, names, number_field, gens, proof=True): 39 r""" 33 40 Create a class group. 34 41 42 Note that the error in the test suite below is caused by the fact that 43 there is no category of additive abelian groups. 44 35 45 EXAMPLES:: 36 46 37 47 sage: K.<a> = NumberField(x^2 + 23) … … 41 51 sage: G.category() 42 52 Category of groups 43 53 sage: TestSuite(G).run() # see #7945 44 Failure in _test_an_element: 45 ... 46 AssertionError: self.an_element() is not in self 54 Failure in _test_category: 47 55 ... 48 The following tests failed: _test_ an_element, _test_elements, _test_elements_eq, _test_inverse, _test_some_elements56 The following tests failed: _test_elements 49 57 """ 58 AbelianGroup_class.__init__(self, len(invariants), invariants, names) 59 self._proof_flag = proof 50 60 self.__number_field = number_field 51 self.__gens = Sequence([FractionalIdealClass( x, self) for x in gens], immutable=True,61 self.__gens = Sequence([FractionalIdealClass(self, x) for x in gens], immutable=True, 52 62 universe=self, check=False) 53 AbelianGroup_class.__init__(self, len(invariants), invariants, names)54 63 55 64 def __call__(self, *args, **kwds): 65 r""" 66 Call method. This exists *purely* to override the old-fashioned 67 behaviour of the parent AbelianGroup class and ensure that 68 :meth:`element_constructor` gets called. 69 70 EXAMPLE:: 71 72 sage: K.<b> = NumberField(x^2 + 389) 73 sage: C = K.class_group() 74 sage: C(K.ideal(b)) 75 Trivial principal fractional ideal class 56 76 """ 77 return Group.__call__(self, *args, **kwds) 78 79 def _element_constructor_(self, *args, **kwds): 80 r""" 81 Create an element of this class group from the given data. This may be: 82 an ideal class in this number field; an ideal class in a subfield; or 83 anything from which an ideal in this number field can be constructed. 57 84 58 85 EXAMPLES:: 59 86 60 87 sage: K.<b> = NumberField(x^2 + 389) 61 88 sage: C = K.class_group() 62 sage: C(K.ideal(b)) 89 sage: C(K.ideal(b)) # indirect doctest 63 90 Trivial principal fractional ideal class 64 sage: C(K.ideal(59049, b + 35312)) 91 sage: C(K.ideal(59049, b + 35312)) # indirect doctest 65 92 Fractional ideal class (59049, b + 35312) 66 sage: C((59049, b + 35312)) 93 sage: C((59049, b + 35312)) # indirect doctest 67 94 Fractional ideal class (59049, b + 35312) 68 sage: C(59049, b + 35312) 95 sage: C(59049, b + 35312) # indirect doctest 69 96 Fractional ideal class (59049, b + 35312) 97 98 sage: K.<a> = QuadraticField(-23) 99 sage: L.<b> = K.extension(x^2 - 2) 100 sage: CK = K.class_group() 101 sage: CL = L.class_group() 102 sage: [CL(I).list() for I in CK] 103 [[0], [2], [4]] 70 104 """ 71 return FractionalIdealClass(self.__number_field.ideal(*args, **kwds), self) 72 73 def _coerce_impl(self, x): 74 """ 75 Canonical coercion of x into this class group. 76 77 EXAMPLES:: 78 79 80 """ 81 return self(x) 105 if isinstance(args[0], FractionalIdealClass): 106 return FractionalIdealClass(self, self.__number_field.ideal(args[0].ideal())) 107 else: 108 I = self.__number_field.ideal(*args, **kwds) 109 if I.is_zero(): raise TypeError, "The zero ideal is not a fractional ideal" 110 return FractionalIdealClass(self, I) 82 111 83 112 def gens(self): 84 """113 r""" 85 114 Return generators for the class group. 86 115 87 116 EXAMPLES:: … … 93 122 return self.__gens 94 123 95 124 def ngens(self): 96 """125 r""" 97 126 Return the number of generators of the class group. 98 127 99 128 EXAMPLES:: … … 103 132 sage: C.ngens() 104 133 2 105 134 """ 106 return len(self. __gens)135 return len(self.invariants()) 107 136 108 137 def gen(self, i=0): 109 """138 r""" 110 139 Return the i-th generator for this class group. 111 140 112 141 EXAMPLES:: 113 142 114 143 sage: C = NumberField(x^2 + 120071, 'a').class_group(); C 115 144 Class group of order 500 with structure C250 x C2 of Number Field in a with defining polynomial x^2 + 120071 116 sage: C.gen(0) 145 sage: C.gen(0) # random 117 146 Fractional ideal class (130, 1/2*a + 137/2) 118 sage: C.gen(1) 147 sage: C.gen(1) # random 119 148 Fractional ideal class (7, a) 120 149 """ 121 150 if i < 0 or i >= len(self.__gens): … … 139 168 [Trivial principal fractional ideal class, Fractional ideal class (2, 1/2*a^2 + a - 1/2), Fractional ideal class (2, 1/2*a^2 + 1/2)] # 32-bit 140 169 [Trivial principal fractional ideal class, Fractional ideal class (2, 1/2*a^2 - a + 3/2), Fractional ideal class (2, 1/2*a^2 + 1/2)] # 64-bit 141 170 142 TESTS: 171 TESTS:: 172 143 173 sage: K.<a> = NumberField(x^2 + 1) 144 174 sage: G = K.class_group() 145 175 sage: G … … 148 178 [Trivial principal fractional ideal class] 149 179 sage: G.list() 150 180 [Trivial principal fractional ideal class] 151 152 sage: C = NumberField(x^2 + x + 23899, 'a').class_group(); C153 Class group of order 68 with structure C34 x C2 of Number Field in a with defining polynomial x^2 + x + 23899154 sage: len(list(C.__iter__()))155 68156 181 """ 157 182 from sage.misc.mrange import mrange 158 183 invs = self.invariants() … … 167 192 yield self(1) 168 193 169 194 def _repr_(self): 170 """195 r""" 171 196 Return string representation of self. 172 197 173 198 EXAMPLES:: … … 182 207 self.number_field()) 183 208 184 209 def number_field(self): 185 """210 r""" 186 211 Return the number field that this class group is attached to. 187 212 188 213 EXAMPLES:: … … 195 220 return self.__number_field 196 221 197 222 198 class FractionalIdealClass( MultiplicativeGroupElement):199 """223 class FractionalIdealClass(AbelianGroupElement): 224 r""" 200 225 A fractional ideal class in a number field. 201 226 202 227 EXAMPLES:: … … 205 230 Class group of order 3 with structure C3 of Number Field in a with defining polynomial x^2 + 23 206 231 sage: I = G.0; I 207 232 Fractional ideal class (2, 1/2*a - 1/2) 208 sage: I*I209 Fractional ideal class (2, 1/2*a + 1/2)210 sage: I*I*I211 Trivial principal fractional ideal class212 233 """ 213 def __init__(self, ideal, class_group):234 def __init__(self, parent, ideal, element=None): 214 235 """ 215 236 Returns the ideal class of this fractional ideal. 237 238 EXAMPLE:: 239 240 sage: K.<a> = NumberField(x^2 + 23,'a'); G = K.class_group() 241 sage: G(K.ideal(13, a + 4)) 242 Fractional ideal class (13, a + 4) 216 243 """ 217 244 self.__ideal = ideal 218 MultiplicativeGroupElement.__init__(self, class_group) 245 if element is None: 246 element = ideal._ideal_class_log(proof = parent._proof_flag) 247 AbelianGroupElement.__init__(self, parent, element) 219 248 220 249 def _repr_(self): 221 """250 r""" 222 251 Return string representation of this fractional ideal class. 252 253 EXAMPLE:: 254 255 sage: K.<a> = NumberField(x^2 + 23,'a'); G = K.class_group() 256 sage: G(K.ideal(13, a + 4))._repr_() 257 'Fractional ideal class (13, a + 4)' 258 sage: G(K.ideal(59, a+6))._repr_() 259 'Trivial principal fractional ideal class' 223 260 """ 224 261 if self.is_principal(): 225 return 'Trivial principal fractional ideal class' #%self.__ideal.number_field() 226 return 'Fractional ideal class %s'%self.__ideal._repr_short() #, self.__ideal.number_field()) 227 228 def __cmp__(self, other): 229 q = self.__ideal / other.__ideal 230 if q.is_principal(): 231 return 0 232 return cmp(self.__ideal, other.__ideal) 262 return 'Trivial principal fractional ideal class' 263 return 'Fractional ideal class %s'%self.__ideal._repr_short() 233 264 234 265 def _mul_(self, other): 235 return self.parent()((self.__ideal * other.__ideal).reduce_equiv()) 266 r""" 267 Multiplication of two ideal classes. 268 269 EXAMPLE:: 270 271 sage: G = NumberField(x^2 + 23,'a').class_group(); G 272 Class group of order 3 with structure C3 of Number Field in a with defining polynomial x^2 + 23 273 sage: I = G.0; I 274 Fractional ideal class (2, 1/2*a - 1/2) 275 sage: I*I # indirect doctest 276 Fractional ideal class (2, 1/2*a + 1/2) 277 sage: I*I*I # indirect doctest 278 Trivial principal fractional ideal class 279 """ 280 m = AbelianGroupElement._mul_(self, other) 281 return FractionalIdealClass(self.parent(), (self.__ideal * other.__ideal).reduce_equiv(), m.list()) 282 283 def __pow__(self, n): 284 r""" 285 Raise this element to the power n. 286 287 EXAMPLE:: 288 289 sage: K.<a> = NumberField(x^3 - 3*x + 8) 290 sage: C=K.class_group() 291 sage: c = C(2, a) 292 sage: c^2 293 Fractional ideal class (2, a^2 + 2*a - 1) 294 sage: c^3 295 Trivial principal fractional ideal class 296 sage: c^1000 297 Fractional ideal class (2, a) 298 """ 299 # We use MonoidElement's __pow__ routine, since that does 300 # repeated squaring, and hence the ideal gets reduced as 301 # we go along; actually computing self.__ideal ** n would 302 # be disastrous. 303 n = n % self.order() 304 return MonoidElement.__pow__(self, n) 305 306 def inverse(self): 307 r""" 308 Return the multiplicative inverse of this ideal class. 309 310 EXAMPLE:: 311 312 sage: K.<a> = NumberField(x^3 - 3*x + 8); G = K.class_group() 313 sage: G(2, a).inverse() 314 Fractional ideal class (2, a^2 + 2*a - 1) 315 """ 316 m = AbelianGroupElement.inverse(self) 317 return FractionalIdealClass(self.parent(), (~self.__ideal).reduce_equiv(), m.list()) 318 319 def __invert__(self): 320 r""" 321 Return the multiplicative inverse of this ideal class. 322 323 EXAMPLE:: 324 325 sage: K.<a> = NumberField(x^3 - 3*x + 8); G = K.class_group() 326 sage: ~G(2, a) 327 Fractional ideal class (2, a^2 + 2*a - 1) 328 """ 329 return self.inverse() 236 330 237 331 def is_principal(self): 238 """332 r""" 239 333 Returns True iff this ideal class is the trivial (principal) class 240 334 241 335 EXAMPLES:: … … 252 346 sage: (c^3).is_principal() 253 347 True 254 348 """ 255 return self. __ideal.is_principal()349 return self.is_one() 256 350 257 351 def reduce(self): 258 """352 r""" 259 353 Return representative for this ideal class that has been 260 354 reduced using PARI's idealred. 261 355 … … 273 367 return self.parent()(self.__ideal.reduce_equiv()) 274 368 275 369 def order(self): 276 """370 r""" 277 371 Return the order of this ideal class in the class group. 278 372 279 373 EXAMPLE:: … … 295 389 [38, 2] 296 390 297 391 """ 298 try: 299 return self.__multiplicative_order 300 except AttributeError: 301 from sage.groups.generic import order_from_multiple 302 self.__multiplicative_order = order_from_multiple(self,self.parent().order(),operation='*') 303 return self.__multiplicative_order 392 # an old method with a new docstring 393 return AbelianGroupElement.order(self) 304 394 305 multiplicative_order = order 306 395 def multiplicative_order(self): 396 r""" 397 Alias for :meth:`order`. 398 399 EXAMPLE:: 400 401 sage: K.<w>=QuadraticField(-23) 402 sage: K.class_group()(K.primes_above(2)[0]).multiplicative_order() 403 3 404 """ 405 return self.order() 406 307 407 def ideal(self): 308 """408 r""" 309 409 Return a representative ideal in this ideal class. 310 410 311 411 EXAMPLE:: … … 322 422 return self.__ideal 323 423 324 424 def gens(self): 325 """425 r""" 326 426 Return generators for a representative ideal in this 327 427 ideal class. 328 428 -
sage/rings/number_field/number_field.py
diff -r 8dec8b43ccca -r 9d33ffed40c7 sage/rings/number_field/number_field.py
a b 2601 2601 # Next gens is a list of ideals. 2602 2602 gens = [self.ideal([self(convert_from_zk_basis(self, y)) for y in x]) for x in gens] 2603 2603 2604 G = ClassGroup(cycle_structure, names, self, gens )2604 G = ClassGroup(cycle_structure, names, self, gens, proof=proof) 2605 2605 self.__class_group[proof,names] = G 2606 2606 return G 2607 2607 -
sage/rings/number_field/number_field_ideal.py
diff -r 8dec8b43ccca -r 9d33ffed40c7 sage/rings/number_field/number_field_ideal.py
a b 840 840 self.__reduced_generators = tuple([g]) 841 841 return self.__is_principal 842 842 843 def _ideal_class_log(self, proof=None): 844 r""" 845 Return the output of Pari's 'bnfisprincipal' for this ideal, 846 i.e. a vector expressing the class of this ideal in terms of a 847 set of generators for the class group. 848 849 EXAMPLE:: 850 851 sage: K.<a, b> = NumberField([x^3 - x + 1, x^2 + 26]) 852 sage: K.primes_above(7)[0]._ideal_class_log() # random 853 [1, 2] 854 """ 855 proof = get_flag(proof, "number_field") 856 try: 857 return self.__ideal_class_log[proof] 858 except AttributeError: 859 self.__ideal_class_log = {} 860 return self._ideal_class_log(proof) 861 except KeyError: 862 bnf = self.number_field().pari_bnf(proof) 863 v = bnf.bnfisprincipal(self.pari_hnf()) 864 self.__ideal_class_log[proof] = list(v[0]) 865 return self.__ideal_class_log[proof] 866 843 867 def is_zero(self): 844 868 """ 845 869 Return True iff self is the zero ideal