Finite Permutation Groups¶
- class sage.categories.finite_permutation_groups.FinitePermutationGroups(base_category)[source]¶
Bases:
CategoryWithAxiom
The category of finite permutation groups, i.e. groups concretely represented as groups of permutations acting on a finite set.
It is currently assumed that any finite permutation group comes endowed with a distinguished finite set of generators (method
group_generators
); this is the case for all the existing implementations in Sage.EXAMPLES:
sage: C = PermutationGroups().Finite(); C Category of finite enumerated permutation groups sage: C.super_categories() [Category of permutation groups, Category of finite groups, Category of finite finitely generated semigroups] sage: C.example() Dihedral group of order 6 as a permutation group
>>> from sage.all import * >>> C = PermutationGroups().Finite(); C Category of finite enumerated permutation groups >>> C.super_categories() [Category of permutation groups, Category of finite groups, Category of finite finitely generated semigroups] >>> C.example() Dihedral group of order 6 as a permutation group
- class ParentMethods[source]¶
Bases:
object
- cycle_index(parent=None)[source]¶
Return the cycle index of
self
.INPUT:
self
– a permutation group \(G\)parent
– a free module with basis indexed by partitions, or behave as such, with aterm
andsum
method (default: the symmetric functions over the rational field in the \(p\) basis)
The cycle index of a permutation group \(G\) (Wikipedia article Cycle_index) is a gadget counting the elements of \(G\) by cycle type, averaged over the group:
\[P = \frac{1}{|G|} \sum_{g\in G} p_{ \operatorname{cycle\ type}(g) }\]EXAMPLES:
Among the permutations of the symmetric group \(S_4\), there is the identity, 6 cycles of length 2, 3 products of two cycles of length 2, 8 cycles of length 3, and 6 cycles of length 4:
sage: S4 = SymmetricGroup(4) sage: P = S4.cycle_index() # needs sage.combinat sage: 24 * P # needs sage.combinat p[1, 1, 1, 1] + 6*p[2, 1, 1] + 3*p[2, 2] + 8*p[3, 1] + 6*p[4]
>>> from sage.all import * >>> S4 = SymmetricGroup(Integer(4)) >>> P = S4.cycle_index() # needs sage.combinat >>> Integer(24) * P # needs sage.combinat p[1, 1, 1, 1] + 6*p[2, 1, 1] + 3*p[2, 2] + 8*p[3, 1] + 6*p[4]
If \(l = (l_1,\dots,l_k)\) is a partition,
|G| P[l]
is the number of elements of \(G\) with cycles of length \((p_1,\dots,p_k)\):sage: 24 * P[ Partition([3,1]) ] # needs sage.combinat 8
>>> from sage.all import * >>> Integer(24) * P[ Partition([Integer(3),Integer(1)]) ] # needs sage.combinat 8
The cycle index plays an important role in the enumeration of objects modulo the action of a group (Pólya enumeration), via the use of symmetric functions and plethysms. It is therefore encoded as a symmetric function, expressed in the powersum basis:
sage: P.parent() # needs sage.combinat Symmetric Functions over Rational Field in the powersum basis
>>> from sage.all import * >>> P.parent() # needs sage.combinat Symmetric Functions over Rational Field in the powersum basis
This symmetric function can have some nice properties; for example, for the symmetric group \(S_n\), we get the complete symmetric function \(h_n\):
sage: S = SymmetricFunctions(QQ); h = S.h() sage: h( P ) # needs sage.combinat h[4]
>>> from sage.all import * >>> S = SymmetricFunctions(QQ); h = S.h() >>> h( P ) # needs sage.combinat h[4]
Todo
Add some simple examples of Pólya enumeration, once it will be easy to expand symmetric functions on any alphabet.
Here are the cycle indices of some permutation groups:
sage: 6 * CyclicPermutationGroup(6).cycle_index() # needs sage.combinat p[1, 1, 1, 1, 1, 1] + p[2, 2, 2] + 2*p[3, 3] + 2*p[6] sage: 60 * AlternatingGroup(5).cycle_index() # needs sage.combinat p[1, 1, 1, 1, 1] + 15*p[2, 2, 1] + 20*p[3, 1, 1] + 24*p[5] sage: for G in TransitiveGroups(5): # long time ....: G.cardinality() * G.cycle_index() p[1, 1, 1, 1, 1] + 4*p[5] p[1, 1, 1, 1, 1] + 5*p[2, 2, 1] + 4*p[5] p[1, 1, 1, 1, 1] + 5*p[2, 2, 1] + 10*p[4, 1] + 4*p[5] p[1, 1, 1, 1, 1] + 15*p[2, 2, 1] + 20*p[3, 1, 1] + 24*p[5] p[1, 1, 1, 1, 1] + 10*p[2, 1, 1, 1] + 15*p[2, 2, 1] + 20*p[3, 1, 1] + 20*p[3, 2] + 30*p[4, 1] + 24*p[5]
>>> from sage.all import * >>> Integer(6) * CyclicPermutationGroup(Integer(6)).cycle_index() # needs sage.combinat p[1, 1, 1, 1, 1, 1] + p[2, 2, 2] + 2*p[3, 3] + 2*p[6] >>> Integer(60) * AlternatingGroup(Integer(5)).cycle_index() # needs sage.combinat p[1, 1, 1, 1, 1] + 15*p[2, 2, 1] + 20*p[3, 1, 1] + 24*p[5] >>> for G in TransitiveGroups(Integer(5)): # long time ... G.cardinality() * G.cycle_index() p[1, 1, 1, 1, 1] + 4*p[5] p[1, 1, 1, 1, 1] + 5*p[2, 2, 1] + 4*p[5] p[1, 1, 1, 1, 1] + 5*p[2, 2, 1] + 10*p[4, 1] + 4*p[5] p[1, 1, 1, 1, 1] + 15*p[2, 2, 1] + 20*p[3, 1, 1] + 24*p[5] p[1, 1, 1, 1, 1] + 10*p[2, 1, 1, 1] + 15*p[2, 2, 1] + 20*p[3, 1, 1] + 20*p[3, 2] + 30*p[4, 1] + 24*p[5]
Permutation groups with arbitrary domains are supported (see Issue #22765):
sage: G = PermutationGroup([['b','c','a']], domain=['a','b','c']) sage: G.cycle_index() # needs sage.combinat 1/3*p[1, 1, 1] + 2/3*p[3]
>>> from sage.all import * >>> G = PermutationGroup([['b','c','a']], domain=['a','b','c']) >>> G.cycle_index() # needs sage.combinat 1/3*p[1, 1, 1] + 2/3*p[3]
One may specify another parent for the result:
sage: # needs sage.combinat sage: F = CombinatorialFreeModule(QQ, Partitions()) sage: P = CyclicPermutationGroup(6).cycle_index(parent=F) sage: 6 * P B[[1, 1, 1, 1, 1, 1]] + B[[2, 2, 2]] + 2*B[[3, 3]] + 2*B[[6]] sage: P.parent() is F True
>>> from sage.all import * >>> # needs sage.combinat >>> F = CombinatorialFreeModule(QQ, Partitions()) >>> P = CyclicPermutationGroup(Integer(6)).cycle_index(parent=F) >>> Integer(6) * P B[[1, 1, 1, 1, 1, 1]] + B[[2, 2, 2]] + 2*B[[3, 3]] + 2*B[[6]] >>> P.parent() is F True
This parent should be a module with basis indexed by partitions:
sage: CyclicPermutationGroup(6).cycle_index(parent = QQ) Traceback (most recent call last): ... ValueError: `parent` should be a module with basis indexed by partitions
>>> from sage.all import * >>> CyclicPermutationGroup(Integer(6)).cycle_index(parent = QQ) Traceback (most recent call last): ... ValueError: `parent` should be a module with basis indexed by partitions
REFERENCES:
AUTHORS:
Nicolas Borie and Nicolas M. Thiéry
- profile(n, using_polya=True)[source]¶
Return the value in \(n\) of the profile of the group
self
.Optional argument
using_polya
allows to change the default method.INPUT:
n
– nonnegative integerusing_polya
– boolean (default:True
); ifTrue
, the computation uses Pólya enumeration (and all values of the profile are cached, so this should be the method used in case several of them are needed); ifFalse
, uses the GAP interface to compute the orbit.
OUTPUT:
A nonnegative integer that is the number of orbits of \(n\)-subsets under the action induced by
self
on the subsets of its domain (i.e. the value of the profile ofself
in \(n\))
See also
EXAMPLES:
sage: C6 = CyclicPermutationGroup(6) sage: C6.profile(2) # needs sage.combinat 3 sage: C6.profile(3) # needs sage.combinat 4 sage: D8 = DihedralGroup(8) sage: D8.profile(4, using_polya=False) 8
>>> from sage.all import * >>> C6 = CyclicPermutationGroup(Integer(6)) >>> C6.profile(Integer(2)) # needs sage.combinat 3 >>> C6.profile(Integer(3)) # needs sage.combinat 4 >>> D8 = DihedralGroup(Integer(8)) >>> D8.profile(Integer(4), using_polya=False) 8
- profile_polynomial(variable='z')[source]¶
Return the (finite) generating series of the (finite) profile of the group.
The profile of a permutation group G is the counting function that maps each nonnegative integer n onto the number of orbits of the action induced by G on the n-subsets of its domain. If f is the profile of G, f(n) is thus the number of orbits of n-subsets of G.
INPUT:
variable
– a variable, or variable name as a string (default: \('z'\))
OUTPUT:
A polynomial in
variable
with nonnegative integer coefficients. By default, a polynomial in z over ZZ.
See also
EXAMPLES:
sage: # needs sage.combinat sage: C8 = CyclicPermutationGroup(8) sage: C8.profile_series() z^8 + z^7 + 4*z^6 + 7*z^5 + 10*z^4 + 7*z^3 + 4*z^2 + z + 1 sage: D8 = DihedralGroup(8) sage: poly_D8 = D8.profile_series() sage: poly_D8 z^8 + z^7 + 4*z^6 + 5*z^5 + 8*z^4 + 5*z^3 + 4*z^2 + z + 1 sage: poly_D8.parent() Univariate Polynomial Ring in z over Rational Field sage: D8.profile_series(variable='y') y^8 + y^7 + 4*y^6 + 5*y^5 + 8*y^4 + 5*y^3 + 4*y^2 + y + 1 sage: u = var('u') sage: D8.profile_series(u).parent() Symbolic Ring
>>> from sage.all import * >>> # needs sage.combinat >>> C8 = CyclicPermutationGroup(Integer(8)) >>> C8.profile_series() z^8 + z^7 + 4*z^6 + 7*z^5 + 10*z^4 + 7*z^3 + 4*z^2 + z + 1 >>> D8 = DihedralGroup(Integer(8)) >>> poly_D8 = D8.profile_series() >>> poly_D8 z^8 + z^7 + 4*z^6 + 5*z^5 + 8*z^4 + 5*z^3 + 4*z^2 + z + 1 >>> poly_D8.parent() Univariate Polynomial Ring in z over Rational Field >>> D8.profile_series(variable='y') y^8 + y^7 + 4*y^6 + 5*y^5 + 8*y^4 + 5*y^3 + 4*y^2 + y + 1 >>> u = var('u') >>> D8.profile_series(u).parent() Symbolic Ring
- profile_series(variable='z')[source]¶
Return the (finite) generating series of the (finite) profile of the group.
The profile of a permutation group G is the counting function that maps each nonnegative integer n onto the number of orbits of the action induced by G on the n-subsets of its domain. If f is the profile of G, f(n) is thus the number of orbits of n-subsets of G.
INPUT:
variable
– a variable, or variable name as a string (default: \('z'\))
OUTPUT:
A polynomial in
variable
with nonnegative integer coefficients. By default, a polynomial in z over ZZ.
See also
EXAMPLES:
sage: # needs sage.combinat sage: C8 = CyclicPermutationGroup(8) sage: C8.profile_series() z^8 + z^7 + 4*z^6 + 7*z^5 + 10*z^4 + 7*z^3 + 4*z^2 + z + 1 sage: D8 = DihedralGroup(8) sage: poly_D8 = D8.profile_series() sage: poly_D8 z^8 + z^7 + 4*z^6 + 5*z^5 + 8*z^4 + 5*z^3 + 4*z^2 + z + 1 sage: poly_D8.parent() Univariate Polynomial Ring in z over Rational Field sage: D8.profile_series(variable='y') y^8 + y^7 + 4*y^6 + 5*y^5 + 8*y^4 + 5*y^3 + 4*y^2 + y + 1 sage: u = var('u') sage: D8.profile_series(u).parent() Symbolic Ring
>>> from sage.all import * >>> # needs sage.combinat >>> C8 = CyclicPermutationGroup(Integer(8)) >>> C8.profile_series() z^8 + z^7 + 4*z^6 + 7*z^5 + 10*z^4 + 7*z^3 + 4*z^2 + z + 1 >>> D8 = DihedralGroup(Integer(8)) >>> poly_D8 = D8.profile_series() >>> poly_D8 z^8 + z^7 + 4*z^6 + 5*z^5 + 8*z^4 + 5*z^3 + 4*z^2 + z + 1 >>> poly_D8.parent() Univariate Polynomial Ring in z over Rational Field >>> D8.profile_series(variable='y') y^8 + y^7 + 4*y^6 + 5*y^5 + 8*y^4 + 5*y^3 + 4*y^2 + y + 1 >>> u = var('u') >>> D8.profile_series(u).parent() Symbolic Ring
- example()[source]¶
Return an example of finite permutation group, as per
Category.example()
.EXAMPLES:
sage: G = FinitePermutationGroups().example(); G Dihedral group of order 6 as a permutation group
>>> from sage.all import * >>> G = FinitePermutationGroups().example(); G Dihedral group of order 6 as a permutation group