10
10
- David Roe (2019): initial version
11
11
"""
12
12
13
- from sage .groups .perm_gps .permgroup import PermutationGroup , PermutationGroup_generic , PermutationGroup_subgroup
14
13
from sage .groups .abelian_gps .abelian_group import AbelianGroup_class , AbelianGroup_subgroup
15
- from sage .sets .finite_enumerated_set import FiniteEnumeratedSet
16
- from sage .misc .lazy_attribute import lazy_attribute
17
14
from sage .misc .abstract_method import abstract_method
18
15
from sage .misc .cachefunc import cached_method
19
- from sage .structure .category_object import normalize_names
16
+ from sage .misc .lazy_attribute import lazy_attribute
17
+ from sage .misc .lazy_import import lazy_import
20
18
from sage .rings .integer_ring import ZZ
21
19
20
+ lazy_import ('sage.groups.galois_group_perm' , 'GaloisGroup_perm' )
21
+ lazy_import ('sage.groups.perm_gps.permgroup' , 'PermutationGroup' )
22
+
23
+
22
24
def _alg_key (self , algorithm = None , recompute = False ):
23
25
r"""
24
26
Return a key for use in cached_method calls.
@@ -40,6 +42,7 @@ def _alg_key(self, algorithm=None, recompute=False):
40
42
algorithm = self ._get_algorithm (algorithm )
41
43
return algorithm
42
44
45
+
43
46
class _GMixin :
44
47
r"""
45
48
This class provides some methods for Galois groups to be used for both permutation groups
@@ -151,6 +154,7 @@ def _gc_map(self):
151
154
"""
152
155
return self ._gcdata [1 ]
153
156
157
+
154
158
class _GaloisMixin (_GMixin ):
155
159
"""
156
160
This class provides methods for Galois groups, allowing concrete instances
@@ -275,6 +279,7 @@ def is_galois(self):
275
279
"""
276
280
return self .order () == self ._field_degree
277
281
282
+
278
283
class _SubGaloisMixin (_GMixin ):
279
284
"""
280
285
This class provides methods for subgroups of Galois groups, allowing concrete instances
@@ -339,164 +344,6 @@ def _gcdata(self):
339
344
"""
340
345
return self ._ambient_group ._gcdata
341
346
342
- class GaloisGroup_perm (_GaloisMixin , PermutationGroup_generic ):
343
- r"""
344
- The group of automorphisms of a Galois closure of a given field.
345
-
346
- INPUT:
347
-
348
- - ``field`` -- a field, separable over its base
349
-
350
- - ``names`` -- a string or tuple of length 1, giving a variable name for the splitting field
351
-
352
- - ``gc_numbering`` -- boolean, whether to express permutations in terms of the
353
- roots of the defining polynomial of the splitting field (versus the defining polynomial
354
- of the original extension). The default value may vary based on the type of field.
355
- """
356
- @abstract_method
357
- def transitive_number (self , algorithm = None , recompute = False ):
358
- """
359
- The transitive number (as in the GAP and Magma databases of transitive groups)
360
- for the action on the roots of the defining polynomial of the top field.
361
-
362
- EXAMPLES::
363
-
364
- sage: R.<x> = ZZ[]
365
- sage: K.<a> = NumberField(x^3 + 2*x + 2) # needs sage.rings.number_field
366
- sage: G = K.galois_group() # needs sage.rings.number_field
367
- sage: G.transitive_number() # needs sage.rings.number_field
368
- 2
369
- """
370
-
371
- @lazy_attribute
372
- def _gens (self ):
373
- """
374
- The generators of this Galois group as permutations of the roots. It's important that this
375
- be computed lazily, since it's often possible to compute other attributes (such as the order
376
- or transitive number) more cheaply.
377
-
378
- EXAMPLES::
379
-
380
- sage: R.<x> = ZZ[]
381
- sage: K.<a> = NumberField(x^5 - 2) # needs sage.rings.number_field
382
- sage: G = K.galois_group(gc_numbering=False) # needs sage.rings.number_field
383
- sage: G._gens # needs sage.rings.number_field
384
- [(1,2,3,5), (1,4,3,2,5)]
385
- """
386
- return NotImplemented
387
-
388
- def __init__ (self , field , algorithm = None , names = None , gc_numbering = False ):
389
- r"""
390
- EXAMPLES::
391
-
392
- sage: R.<x> = ZZ[]
393
- sage: K.<a> = NumberField(x^3 + 2*x + 2) # needs sage.rings.number_field
394
- sage: G = K.galois_group() # needs sage.rings.number_field
395
- sage: TestSuite(G).run() # needs sage.rings.number_field
396
- """
397
- self ._field = field
398
- self ._default_algorithm = algorithm
399
- self ._base = field .base_field ()
400
- self ._gc_numbering = gc_numbering
401
- if names is None :
402
- # add a c for Galois closure
403
- names = field .variable_name () + 'c'
404
- self ._gc_names = normalize_names (1 , names )
405
- # We do only the parts of the initialization of PermutationGroup_generic
406
- # that don't depend on _gens
407
- from sage .categories .permutation_groups import PermutationGroups
408
- category = PermutationGroups ().FinitelyGenerated ().Finite ()
409
- # Note that we DON'T call the __init__ method for PermutationGroup_generic
410
- # Instead, the relevant attributes are computed lazily
411
- super (PermutationGroup_generic , self ).__init__ (category = category )
412
-
413
- @lazy_attribute
414
- def _deg (self ):
415
- r"""
416
- The number of moved points in the permutation representation.
417
-
418
- This will be the degree of the original number field if `_gc_numbering``
419
- is ``False``, or the degree of the Galois closure otherwise.
420
-
421
- EXAMPLES::
422
-
423
- sage: # needs sage.rings.number_field
424
- sage: R.<x> = ZZ[]
425
- sage: K.<a> = NumberField(x^5 - 2)
426
- sage: G = K.galois_group(gc_numbering=False); G
427
- Galois group 5T3 (5:4) with order 20 of x^5 - 2
428
- sage: G._deg
429
- 5
430
- sage: G = K.galois_group(gc_numbering=True); G._deg
431
- 20
432
- """
433
- if self ._gc_numbering :
434
- return self .order ()
435
- else :
436
- try :
437
- return self ._field .degree ()
438
- except NotImplementedError : # relative number fields don't support degree
439
- return self ._field .relative_degree ()
440
-
441
- @lazy_attribute
442
- def _domain (self ):
443
- r"""
444
- The integers labeling the roots on which this Galois group acts.
445
-
446
- EXAMPLES::
447
-
448
- sage: # needs sage.rings.number_field
449
- sage: R.<x> = ZZ[]
450
- sage: K.<a> = NumberField(x^5 - 2)
451
- sage: G = K.galois_group(gc_numbering=False); G
452
- Galois group 5T3 (5:4) with order 20 of x^5 - 2
453
- sage: G._domain
454
- {1, 2, 3, 4, 5}
455
- sage: G = K.galois_group(gc_numbering=True); G._domain
456
- {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20}
457
- """
458
- return FiniteEnumeratedSet (range (1 , self ._deg + 1 ))
459
-
460
- @lazy_attribute
461
- def _domain_to_gap (self ):
462
- r"""
463
- Dictionary implementing the identity (used by PermutationGroup_generic).
464
-
465
- EXAMPLES::
466
-
467
- sage: R.<x> = ZZ[]
468
- sage: K.<a> = NumberField(x^5 - 2) # needs sage.rings.number_field
469
- sage: G = K.galois_group(gc_numbering=False) # needs sage.rings.number_field
470
- sage: G._domain_to_gap[5] # needs sage.rings.number_field
471
- 5
472
- """
473
- return {key : i + 1 for i , key in enumerate (self ._domain )}
474
-
475
- @lazy_attribute
476
- def _domain_from_gap (self ):
477
- r"""
478
- Dictionary implementing the identity (used by PermutationGroup_generic).
479
-
480
- EXAMPLES::
481
-
482
- sage: R.<x> = ZZ[]
483
- sage: K.<a> = NumberField(x^5 - 2) # needs sage.rings.number_field
484
- sage: G = K.galois_group(gc_numbering=True) # needs sage.rings.number_field
485
- sage: G._domain_from_gap[20] # needs sage.rings.number_field
486
- 20
487
- """
488
- return {i + 1 : key for i , key in enumerate (self ._domain )}
489
-
490
- def ngens (self ):
491
- r"""
492
- Number of generators of this Galois group
493
-
494
- EXAMPLES::
495
-
496
- sage: QuadraticField(-23, 'a').galois_group().ngens() # needs sage.rings.number_field
497
- 1
498
- """
499
- return len (self ._gens )
500
347
501
348
class GaloisGroup_ab (_GaloisMixin , AbelianGroup_class ):
502
349
r"""
@@ -573,6 +420,7 @@ def transitive_number(self, algorithm=None, recompute=False):
573
420
"""
574
421
return ZZ (self .permutation_group ()._gap_ ().TransitiveIdentification ())
575
422
423
+
576
424
class GaloisGroup_cyc (GaloisGroup_ab ):
577
425
r"""
578
426
Cyclic Galois groups
@@ -614,17 +462,6 @@ def signature(self):
614
462
"""
615
463
return ZZ (1 ) if (self ._field .degree () % 2 ) else ZZ (- 1 )
616
464
617
- class GaloisSubgroup_perm (PermutationGroup_subgroup , _SubGaloisMixin ):
618
- """
619
- Subgroups of Galois groups (implemented as permutation groups), specified
620
- by giving a list of generators.
621
-
622
- Unlike ambient Galois groups, where we use a lazy ``_gens`` attribute in order
623
- to enable creation without determining a list of generators,
624
- we require that generators for a subgroup be specified during initialization,
625
- as specified in the ``__init__`` method of permutation subgroups.
626
- """
627
- pass
628
465
629
466
class GaloisSubgroup_ab (AbelianGroup_subgroup , _SubGaloisMixin ):
630
467
"""
@@ -633,5 +470,4 @@ class GaloisSubgroup_ab(AbelianGroup_subgroup, _SubGaloisMixin):
633
470
pass
634
471
635
472
636
- GaloisGroup_perm .Subgroup = GaloisSubgroup_perm
637
473
GaloisGroup_ab .Subgroup = GaloisSubgroup_ab
0 commit comments