Nilpotency and solvability are well-developed for loops but less so for quasigroups and right quasigroups. Many methods described in this chapter therefore apply only to loops.
The right nucleus (resp. middle nucleus, left nucleus) of a right quasigroup Q is the set \mathrm{Nuc}_r(Q) = \{z\in Q:x(yz)=(xy)z for all x,y\in Q\} (resp. \mathrm{Nuc}_m(Q) = \{y\in Q:x(yz)=(xy)z for all x,z\in Q\}, \mathrm{Nuc}_\ell(Q) = \{x\in Q:x(yz)=(xy)z for all y,z\in Q\}). The nucleus \mathrm{Nuc}(Q) of Q is the intesection of the three nuclei.
In the finite case, each of the four nuclei is either an empty set or a subalgebra. For loops, each of the four nuclei is always a subloop.
The commutant of a right quasigroup Q is the possibly empty set \{x\in Q:xy=yx for all y\in Q\}. In the case of loops, the neutral element always belongs to the commutant.
The center of a right quasigroup is the intersection of the nucleus and the commutant. In the case of loops, the center is always a normal subloop.
‣ RightNucleus ( Q ) | ( attribute ) |
‣ MiddleNucleus ( Q ) | ( attribute ) |
‣ LeftNucleus ( Q ) | ( attribute ) |
‣ Nuc ( Q ) | ( attribute ) |
Returns: the (right, middle, left) nucleus of a right quasigroup Q
, either as the empty set or as a subalgebra of Q
.
We also support the synonyms NucleusOfRightQuasigroup
, NucleusOfQuasigroup
and NucleusOfLoop
of Nuc
.
‣ Commutant ( Q ) | ( attribute ) |
Returns: the commutant of the rigt quasigroup Q
, a possibly empty subset of Q
.
‣ Center ( Q ) | ( attribute ) |
Returns: the center of the right quasigroup Q
, a possibly empty subset of Q
.
The nilpotency class of a loop Q is defined inductively by cl(Q)=1 if Q is an abelian group and by cl(Q)=cl(Q/Z(Q))+1, if this process terminates, in which case Q
is nilpotent.
‣ NilpotencyClassOfLoop ( Q ) | ( attribute ) |
Returns: the nilpotency class of a loop Q
. When Q
is not nilpotent, returns fail
.
‣ IsNilpotentLoop ( Q ) | ( operation ) |
Returns: true
if Q
is a nilpotent loop, else returns false
. The non-qualified version IsNilpotent
is also supported, cf. Section 1.10.
‣ UpperCentralSeriesOfLoop ( Q ) | ( operation ) |
Returns: the upper central series of the loop Q
, that is, the series [Z_0(Q), Z_1(Q), Z_2(Q), ...], where Z_0(Q)=1 and Z_{n+1}(Q) is the preimage of Z(Q/Z_n(Q)) under the canonical projection Q\to Q/Z_n(Q). The function returns the longest strictly increasing segment of the upper central series. The non-qualified version UpperCentralSeries
is also supported.
‣ LowerCentralSeriesOfLoop ( Q ) | ( operation ) |
Returns: the lower central series of the loop Q
, that is, the series Q=Q_{(0)}\ge Q_{(1)}\ge Q_{(2)}\ge \dots such that Q_{(i+1)} is the smallest normal subloop of Q such that Q_{(i)}/Q_{(i+1)}\le Z(Q/Q_{(i+1)}). The function returns the longest strictly decreasing segment of the lower central series. The non-qualified version LowerCentralSeries
is also supported.
There are two competing notions of solvability in loop theory and both are supported in RightQuasigroups.
A loop Q is classically solvable if there exists a series Q=Q_0> Q_1>\dots>Q_n=1 such that Q_i\unlhd Q and Q_i/Q_{i+1} is a commutative group. To conform with historical terminology, we call classically solvable loops solvable.
There is a well-established universal-algebraic notion of commutators of congruences in congruence-modular varieties, which includes the variety of loops. We denote by [A,B]_Q this commutator of two normal subloops A, B of a loop Q. A normal subloop A is abelian in Q if [A,A]_Q=1. If a normal subloop A is abelian in Q then A is a commutative group, but not necessarily vice versa.
A loop Q is then congruence solvable if there exists a series Q=Q_0> Q_1>\dots>Q_n=1 such that Q_i\unlhd Q and Q_i/Q_{i+1} is abelian in Q/Q_{i+1}. Universally-algebraically speaking, this is the correct notion of solvablity for loops. Every congruence solvable loop is classically solvable but not necessarily vice versa. A group is congruence solvable iff it is classically solvable.
‣ AssociatorSubloop ( Q ) | ( attribute ) |
Returns: the associator subloop of Q
, that is, the smallest normal subloop of Q
containing all associators.
‣ IsSolvableLoop ( Q ) | ( operation ) |
Returns: true
if Q
is a (classically) solvable loop, else returns false
. The non-qualified version IsSolvable
is also supported.
‣ DerivedSubloop ( Q ) | ( attribute ) |
Returns: the derived subloop of Q
, that is, the smallest normal subloop A
of Q
such that Q/A
is an abelian group. Note that this coincides with the congruence derived subloop [Q,Q]_Q and there is therefore no need for CongruenceDerivedSubloop
.
‣ DerivedSeriesOfLoop ( Q ) | ( operation ) |
Returns: the derived series of Q
. If Q' denotes the derived subloop of Q, then the derived series is the series [Q,Q',Q'',\dots]. The function returns the longest strictly decreasing initial segment of the derived series. The non-qualified version DerivedSeries
is also supported.
‣ DerivedLength ( Q ) | ( attribute ) |
Returns: the number of steps in the derived series of the loop Q
if Q
is solvable, else returns fail
.
The following methods deal with congruence solvability of loops.
‣ CommutatorOfNormalSubloops ( Q, A, B ) | ( operation ) |
Returns: the commutator of normal subloops A
, B
of the loop Q
, that is, [A,B]_Q. For finite loops, [A,B]_Q is the smallest normal subloop of Q contaning the elements R_{b_1,c_1}(a)/R_{b_2,c_2}(a), L_{b_1,c_1}(a)/L_{b_2,c_2}(a), T_{b_1}(a)/T_{b_2}(a), where a\in A, b_1/b_2\in B, c_1/c_2\in B and where R_{x,y}, L_{x,y}, T_x are the standard inner mappings of Q.
‣ IsAbelianNormalSubloop ( Q, A ) | ( operation ) |
Returns: true
if A
is an abelian (in the universal-algebraic sense) normal subloop of the loop Q
, else returns false
. A normal subloop A of Q is abelian in Q if [A,A]_Q=1.
‣ IsCongruenceSolvableLoop ( Q ) | ( operation ) |
Returns: true
if Q
is a congruence solvable loop, else returns false
.
‣ CongruenceDerivedSeriesOfLoop ( Q ) | ( operation ) |
Returns: the congruence derived series of Q
. With Q^{(0)}=Q and Q^{(i+1)} = [Q^{(i)},Q^{(i)}]_Q, this is the series [Q^{(0)},Q^{(1)},Q^{(2)},\dots]. The function returns the longest strictly decreasing initial segment of the congruence derived series.
‣ CongruenceDerivedLength ( Q ) | ( attribute ) |
Returns: the number of steps in the congruence derived series of the loop Q
if Q
is congruence solvable, else returns fail
.
gap> uset := Union( List([0..3], i-> [[i,0],[i,1]] ) ); # the underlying set [ [ 0, 0 ], [ 0, 1 ], [ 1, 0 ], [ 1, 1 ], [ 2, 0 ], [ 2, 1 ], [ 3, 0 ], [ 3, 1 ] ] gap> ct := [[0,1,2,3],[1,3,0,2],[2,0,3,1],[3,2,1,0]];; gap> mult := function( x, y ) > if x[2]=0 or y[2]=0 then > return [ (x[1]+y[1]) mod 4, (x[2]+y[2]) mod 2 ]; > else > return [ ct[x[1]+1,y[1]+1], (x[2]+y[2]) mod 2 ]; > fi; > end; function( x, y ) ... end gap> Q := LoopByFunction( uset, mult ); # Z_4 x Z_2 with one quandrant "replaced" with ct <loop of size 8> gap> DerivedSeries( Q ); [ <loop of size 8>, <loop of size 4>, <trivial group with 1 generator> ] gap> IsSolvable( Q ); true gap> DerivedLength( Q ); 2 gap> C := CommutatorOfNormalSubloops(Q,Q,Q); # congruence derived subloop = derived subloop <loop of size 4> gap> D := CommutatorOfNormalSubloops(Q,C,C); # 2nd congruence derived subloop differs from 2nd derived subloop <loop of size 4> gap> CongruenceDerivedSeriesOfLoop( Q ); [ <loop of size 8>, <loop of size 4> ] gap> IsCongruenceSolvableLoop( Q ); false gap> CongruenceDerivedLength( Q ); fail gap> IsCommutative( C ) and IsAssociative( C ) and IsNormal( Q, C ); # commutative group, normal in Q true gap> IsAbelianNormalSubloop( Q, C ); # but not abelian in Q false
A loop Q is an extension of K by F if K is a normal subloop of Q such that Q/K is isomorphic to F. If K is in the nucleus of Q then the extension is nuclear, while if K is in the center of Q then the enxtension is central.
If K, F are loops then \theta:F\times F\to K is a loop cocycle if \theta(x,1_F)=\theta(1_F,x)=1_K for all x\in F. In RightQuasigroups, a loop cocycle is represented as an |F|\times |F| table with entries in [1..|K|].
Every nuclear extension of K by F with K an abelian group is isomorphic to the loop (K\times F,\circ), where (a,x)\circ(b,y) = (a\phi_x(b)\theta(x,y),xy) for some homomorphism \phi:F\to\mathrm{Aut}(K) and some loop cocycle \theta:F\times F\to K.
Every central extension of K by F is isomorphic to the loop (K\times F,\circ), where (a,x)\circ(b,y) = (ab\theta(x,y),xy) for some loop cocycle \theta:F\times F\to K. This loop will also be denoted by K\times_\theta F.
‣ IsLoopCocycle ( K, F, theta ) | ( operation ) |
Returns: true
if theta is a loop cocycle from F to K, else returns false
. A loop cocycle is an |F|\times |F| table with entries in [1..|K|] such that all entries in the row and in the column corresponding to the neutral element of F are equal to the neutral element of K.
‣ LoopByNuclearExtension ( K, F, phi, theta[, constructorStyle] ) | ( operation ) |
Returns: the nuclear extension of the abelian group K by the loop F via the homomorphism phi and cocycle theta. The arguments must be formatted as follows: K is a commutative and associative loop of size nK
, F is a loop of size nF
, phi is a list of length nF
consisting of permutations of [1..nK]
(each permutation standing for an automorphism of K), theta is an nF
by nF
matrix with entries in [1..nK]
. We also support giving the first four arguments as a list. The loop is returned as index based loop with the underlying set equal to the carthesian product of the underlying sets of K
and F
, and with multiplication [a,x]*[b,y] = [a * b^phi[x] * theta[x,y], x*y ]
.
‣ LoopByCentralExtension ( K, F, theta[, constructorStyle] ) | ( operation ) |
Returns: the central extension of the abelian group K by the loop F via the cocycle theta. The format of arguments and of the resulting loop are the same as in LoopByNuclearExtension
. We also support giving the first three arguments as a list.
gap> K := AsLoop( CyclicGroup( 4 ) );; gap> F := LoopByCayleyTable( [ [ "a", "b" ], [ "b", "a" ] ] );; gap> AutomorphismGroup( K ); Group([ (2,4) ]) gap> phi := [ (), (2,4) ];; # homomorphism from F to Aut( K ) gap> theta := [ [ 1, 1 ], [ 1, 4 ] ];; # loop cocycle from FxF to K gap> IsLoopCocycle( K, F, theta ); true gap> Q := LoopByNuclearExtension( K, F, phi, theta ); <loop of size 8> gap> S := NucleusOfLoop( Q ); <associative loop of size 4> gap> IsNormal( Q, S ); true gap> AsCanonicalPerm( IsomorphismLoops( F, Q/S ) ); () gap> Display( MultiplicationTable( Q ) ); [ [ 1, 2, 3, 4, 5, 6, 7, 8 ], [ 2, 7, 8, 5, 6, 3, 4, 1 ], [ 3, 4, 5, 6, 7, 8, 1, 2 ], [ 4, 1, 2, 7, 8, 5, 6, 3 ], [ 5, 6, 7, 8, 1, 2, 3, 4 ], [ 6, 3, 4, 1, 2, 7, 8, 5 ], [ 7, 8, 1, 2, 3, 4, 5, 6 ], [ 8, 5, 6, 3, 4, 1, 2, 7 ] ] gap> Q.1; # the underlying set of Q is the carthesian product of underlying sets K x F l[ <identity> of ..., "a" ] gap> LoopByCentralExtension( K, F, theta ); <loop of size 8> gap> Center( last ); <associative loop of size 8>
‣ AsSquareTable ( ls ) | ( operation ) |
Returns: If ls is a list of length n^2
for some n
, returns ls as a square table, a list of lists of length n
.
Note: This function is convenient for transforming row vector cocycles obtained by LoopCocyclesInVariety
and by similar functions to square table cocycles required by the LoopByNuclearExtensions
function.
‣ NuclearExtensionByNormalSubloop ( Q, K ) | ( operation ) |
Returns: the parameters [K,F,phi,theta]
for a nuclear extension of K by Q/
K. Here, K must be a commutative normal subloop of the nucleus of the loop Q. The returned loop K
is identical to the argument K and the returned factor loop F
is identical to Q/
K.
‣ CentralExtensionByNormalSubloop ( Q, K ) | ( operation ) |
Returns: the parameters [K,F,theta]
for a central extension of K by Q/
K. Here, K must be a subloop of the center of the loop Q. The returned loop K
is identical to the argument K and the returned factor loop F
is identical to Q/
K.
gap> Q := MoufangLoop(32,3);; gap> Nuc( Q ); # here, the nucleus is commutative and properly contains the center <associative loop of size 4> gap> Center( Q ); <associative loop of size 2> gap> ext := NuclearExtensionByNormalSubloop( Q, Nuc( Q ) ); [ <associative loop of size 4>, <Moufang loop of size 8>, [ (), (), (), (2,4), (), (2,4), (2,4), (2,4) ], [ [ 1, 1, 1, 1, 1, 1, 1, 1 ], [ 1, 1, 1, 1, 1, 1, 3, 3 ], [ 1, 3, 1, 1, 3, 1, 1, 1 ], [ 1, 1, 1, 1, 3, 1, 1, 3 ], [ 1, 3, 1, 1, 3, 1, 3, 3 ], [ 1, 1, 1, 1, 3, 1, 3, 1 ], [ 1, 3, 1, 1, 1, 1, 1, 3 ], [ 1, 3, 1, 1, 1, 1, 3, 1 ] ] ] gap> copyQ := LoopByNuclearExtension( ext[1],ext[2],ext[3],ext[4] );; gap> AsCanonicalPerm( IsomorphismLoops( Q, copyQ ) ); (4,9,11,28,29,24,22,21,20,25,27,12,13,8,6,5)(7,10)(14,30)(15,31)(16,32)(23,26) gap> ext := CentralExtensionByNormalSubloop( Q, Center( Q ) );; gap> copyQ := LoopByCentralExtension( ext );; # extension can also be given as a list gap> AsCanonicalPerm( IsomorphismLoops( Q, copyQ ) ); ()
If a loop Q has a nontrivial center, it is a central extension of an abelian group K of order p by a loop F of order |Q|/p. The following functions construct all central extensions of the cyclic group of order p by a given loop F in a given variety of loops.
Just like all p-groups are centrally nilpotent, all p-loops in certain varieties of loops (e.g., Moufang loops) are centrally nilpotent. The following functions therefore allow us in principle to construct all p-loops of small orders in such varieties.
The enveloping variety is specified as a finite list of loop identities that the built-in parser can understand (see Section 7.1).
Given a variety V, an abelian group K\in V and a loop F\in V, let \mathrm{Coc}_V(F,K) be the vector space of cocycles \theta:F\times F\to K such that the central extension K\times_\theta F is a loop in V.
The vector space of coboundaries \mathrm{Cob}_V(F,K) is generated by the cocycles \theta:F\times F\to (K,+) of the form \theta(x,y) = f(xy)-f(x)-f(y), where f:F\to\mathbb K satisfies f(1)=0.
If \theta,\mu\in\mathrm{Coc}_V(F,K) then the central extensions K\times_\theta F and K\times_\mu F are isomorphic if \theta and \mu differ by a coboundary, that is, \theta-\mu\in\mathrm{Cob}_V(F,K).
Finally, the group G=\mathrm{Aut}(K)\times\mathrm{Aut}(F) acts on the cohomology group \mathrm{Coc}_V(F,K)/\mathrm{Cob}_V(F,K) (details ommitted) and two central extensions are isomorphic if their cocycles lie in the same orbit of G.
In RightQuasigroups, the elements of \mathrm{Coc}_V(F,\mathbb Z_p) are represented as vectors of length |F|^2 with entries in GF(p). (In particular, a cocycle from \mathrm{Coc}_V(F,\mathbb Z_p) must be transformed into a square matrix to be suitable as an argument for LoopByCentralExtension
.)
‣ LoopCocyclesInVariety ( F, p, equationalBasis ) | ( operation ) |
Returns: a basis of the vector space of cocycles \mathrm{Coc}_V(F,\mathbb Z_p), where F is a loop, p is a prime and V is a variety of loops defined by the list of loop identities equationalBasis. It is checked that all identities of equationalBasis hold in the (multiplicative) cyclic group of order p and in the loop F, else en error message is generated.
gap> F := AsLoop( Group( (1,2), (3,4) ) );; # the Klein group gap> coc := LoopCocyclesInVariety( F, 2, [ "x*(y*(x*z)) = (x*(y*x))*z" ] );; # basis of left Bol cocycles gap> Length( coc ); # dimension of the vector space of cocycles 6 gap> theta := coc[3];; Display( theta ); # one cocycle [ 0*Z(2), 0*Z(2), 0*Z(2), 0*Z(2), 0*Z(2), 0*Z(2), 0*Z(2), 0*Z(2), 0*Z(2), Z(2)^0, Z(2)^0, 0*Z(2), 0*Z(2), 0*Z(2), 0*Z(2), 0*Z(2) ] gap> theta := List( theta, x -> IntFFE( x ) + 1 );; Display( theta ); # converting cocycle entries to [1..Size(K)] [ 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 2, 1, 1, 1, 1, 1 ] gap> theta := AsSquareTable( theta );; Display( theta ); # converting cocycle to square table [ [ 1, 1, 1, 1 ], [ 1, 1, 1, 1 ], [ 1, 2, 2, 1 ], [ 1, 1, 1, 1 ] ] gap> Q := LoopByCentralExtension( AsLoop( CyclicGroup(2) ), F, theta ); <loop of size 8> gap> IsLeftBolLoop( Q ); true
‣ LoopCoboundaries ( F, p ) | ( operation ) |
Returns: a basis of the vector space of coboundaries \mathrm{Cob}_V(F,\mathbb Z_p), where F is a loop and p is a prime. Note that V is irrelevant here.
‣ LoopCocyclesModAction ( F, p, coc, cob ) | ( operation ) |
Returns: Given a loop F, prime p, basis coc of the vector space \mathrm{Coc}_V(F,\mathbb Z_p) and a basis cob of the vector space \mathrm{Cob}_V(F,\mathbb Z_p), returns a list of cocycles from \mathrm{Coc}_V(F,\mathbb Z_p), one from each orbit of \mathrm{Aut}(\mathbb Z_p)\times\mathrm{Aut}(F) acting on the cohomology group \mathrm{Coc}_V(F,\mathbb Z_p)/\mathrm{Cob}_V(F,\mathbb Z_p). Once the central extensions corresponding to the cocycles are constructed, they are guaranteed to contain all central extensions of \mathbb Z_p by \mathbb F up to isomorphism (with possible duplications).
‣ AllLoopCocyclesInVariety ( F, p, equationalBasis ) | ( operation ) |
Returns: Given a loop F, prime p and a list of loop identities equationalBasis defining a variety V, returns a list of cocycles from \mathrm{Coc}_V(F,\mathbb Z_p) modulo coboundaries and modulo the action described in LoopCocyclesModAction
.
‣ AllLoopCentralExtensionsInVariety ( F, p, equationalBasis ) | ( operation ) |
Returns: a list of loops constructed as central extensions of the cyclic group of order p by the loop F via the cocycles obtained by AllLoopCocyclesInVariety(
F,
p,
equationalBasis )
. The returned list is guaranteed to contain all central extensions of the cyclic group of order p by the loop F in the variety of loops defined by the identities equationalBasis, but it might contain duplicate loops of the same isomorphism type. (See LoopsUpToIsomorphism
.)
gap> F := AsLoop( Group( (1,2), (3,4 ) ) );; # Klein group gap> coc := LoopCocyclesInVariety( F, 2, [ "x*(y*(x*z)) = (x*(y*x))*z" ] );; Length( coc ); # basis of left Bol cocycles 6 gap> cob := LoopCoboundaries( F, 2 );; Length( cob ); # basis of coboundaries 1 gap> Length( LoopCocyclesModAction( F, 2, coc, cob ) ); # cocycles modulo coboundaries and action of Aut(K)x Aut(F) 11 gap> Length( AllLoopCocyclesInVariety( F, 2, [ "x*(y*(x*z)) = (x*(y*x))*z" ] ) ); # the same in one step #I RQ: Calculating coboundaries #I RQ: Coboundaries have dimension 1 #I RQ: Calculating cocycles #I RQ: Cocycles have dimension 6 11 gap> lps := AllLoopCentralExtensionsInVariety( F, 2, [ "x*(y*(x*z)) = (x*(y*x))*z" ] );; Length( lps ); # all central extensions in one step #I RQ: Calculating coboundaries #I RQ: Coboundaries have dimension 1 #I RQ: Calculating cocycles #I RQ: Cocycles have dimension 6 11 gap> ForAll( lps, IsLeftBolLoop ); true gap> Length( LoopsUpToIsomorphism( lps ) ); # filtering up to isomorphism (no isomorphisms in this example) 10
For a finite algebra Q the Frattini subalgebra \Phi(Q) is the intersection of all maximal subalgebras of Q. It is precisely the set of non-generators of Q, i.e., elements x\in Q such that whenever Q=\langle S,x\rangle then Q=\langle S\rangle.
The Frattini subalgebra might be empty if Q is a quasigroup. If Q is a loop, the \Phi(Q) is a subloop of Q, the Frattini subloop of Q. When Q is a nilpotent loop, then \Phi(Q) is a normal subloop of Q. If Q is a nilpotent p-loop then Q/\Phi(Q) is isomorphic to a vector space over \mathbb Z_p whose dimension is the size of a minimal generating subset of Q.
When Q is a loop with nilpotent multiplication group \mathrm{Mlt}(Q), then \Phi(Q) is the orbit of \Phi(\mathrm{Mlt}(Q)) containing 1.
‣ FrattiniSubrightquasigroup ( Q ) | ( attribute ) |
Returns: the Frattini subrightquasigroup (possibly empty) of the right quasigroup Q
.
‣ FrattiniSubquasigroup ( Q ) | ( attribute ) |
Returns: the Frattini subquasigroup (possibly empty) of the quasigroup Q
.
‣ FrattiniSubloop ( Q ) | ( attribute ) |
Returns: the Frattini subloop of the loop Q
.
gap> Q := MoufangLoop(64,5); MoufangLoop( 64, 5 ) gap> F := FrattiniSubloop(Q); <Moufang loop of size 8> gap> Exponent(Q/F); 2 gap> FrattiniSubrightquasigroup( ProjectionRightQuasigroup([1,2]) ); [ ]
generated by GAPDoc2HTML