917 lines
29 KiB
Plaintext
917 lines
29 KiB
Plaintext
|
#############################################################################
|
||
|
##
|
||
|
#W classes.gi Testing properties/varieties [loops]
|
||
|
##
|
||
|
#H @(#)$Id: classes.gi, v 3.3.0 2016/10/26 gap Exp $
|
||
|
##
|
||
|
#Y Copyright (C) 2004, G. P. Nagy (University of Szeged, Hungary),
|
||
|
#Y P. Vojtechovsky (University of Denver, USA)
|
||
|
##
|
||
|
|
||
|
#############################################################################
|
||
|
## ASSOCIATIVITY, COMMUTATIVITY AND GENERALIZATIONS
|
||
|
## -------------------------------------------------------------------------
|
||
|
|
||
|
# (PROG) IsAssociative is already implemented for magmas, but we provide
|
||
|
# a new method based on sections. This new method is much faster for groups,
|
||
|
# and a bit slower for nonassociative loops.
|
||
|
|
||
|
InstallOtherMethod( IsAssociative, "for loops",
|
||
|
[ IsLoop ], 0,
|
||
|
function( Q )
|
||
|
local sLS, x, y;
|
||
|
sLS := Set( LeftSection( Q ) );
|
||
|
for x in LeftSection( Q ) do
|
||
|
for y in LeftSection( Q ) do
|
||
|
if not x*y in sLS then return false; fi;
|
||
|
od;
|
||
|
od;
|
||
|
return true;
|
||
|
end);
|
||
|
|
||
|
# implies
|
||
|
InstallTrueMethod( IsExtraLoop, IsAssociative and IsLoop );
|
||
|
|
||
|
#############################################################################
|
||
|
##
|
||
|
#P IsCommutative( Q )
|
||
|
##
|
||
|
## Returns true if <Q> is commutative.
|
||
|
|
||
|
InstallOtherMethod( IsCommutative, "for quasigroup",
|
||
|
[ IsQuasigroup ],
|
||
|
function( Q )
|
||
|
return LeftSection( Q ) = RightSection( Q );
|
||
|
end );
|
||
|
|
||
|
#############################################################################
|
||
|
##
|
||
|
#P IsPowerAssociative( Q )
|
||
|
##
|
||
|
## Returns true if <Q> is a power associative quasigroup.
|
||
|
|
||
|
InstallOtherMethod( IsPowerAssociative, "for quasigroup",
|
||
|
[ IsQuasigroup ],
|
||
|
function( Q )
|
||
|
local checked, x, S;
|
||
|
checked := [];
|
||
|
repeat
|
||
|
x := Difference( Elements(Q), checked );
|
||
|
if IsEmpty( x ) then
|
||
|
return true;
|
||
|
fi;
|
||
|
S := Subquasigroup( Q, [x[1]] );
|
||
|
if not IsAssociative( S ) then
|
||
|
return false;
|
||
|
fi;
|
||
|
checked := Union( checked, Elements( S ) ); # S is a group, so every subquasigroup of S is a group
|
||
|
until 0=1;
|
||
|
end );
|
||
|
|
||
|
# implies
|
||
|
InstallTrueMethod( HasTwosidedInverses, IsPowerAssociative and IsLoop );
|
||
|
|
||
|
#############################################################################
|
||
|
##
|
||
|
#P IsDiassociative( Q )
|
||
|
##
|
||
|
## Returns true if <Q> is a diassociative quasigroup.
|
||
|
|
||
|
InstallOtherMethod( IsDiassociative, "for quasigroup",
|
||
|
[ IsQuasigroup ],
|
||
|
function( Q )
|
||
|
local checked, all_pairs, x, S;
|
||
|
checked := [];
|
||
|
all_pairs := Combinations( PosInParent( Elements( Q ) ), 2 ); # it is faster to work with integers
|
||
|
repeat
|
||
|
x := Difference( all_pairs, checked );
|
||
|
if IsEmpty( x ) then
|
||
|
return true;
|
||
|
fi;
|
||
|
S := Subquasigroup( Q, x[1] );
|
||
|
if not IsAssociative( S ) then
|
||
|
return false;
|
||
|
fi;
|
||
|
checked := Union( checked, Combinations( PosInParent( Elements( S ) ), 2 ) );
|
||
|
until 0=1;
|
||
|
end );
|
||
|
|
||
|
# implies
|
||
|
InstallTrueMethod( IsPowerAlternative, IsDiassociative );
|
||
|
InstallTrueMethod( IsFlexible, IsDiassociative );
|
||
|
|
||
|
#############################################################################
|
||
|
## INVERSE PROPERTIES
|
||
|
## -------------------------------------------------------------------------
|
||
|
|
||
|
#############################################################################
|
||
|
##
|
||
|
#P HasLeftInverseProperty( L )
|
||
|
##
|
||
|
## Returns true if <L> has the left inverse property.
|
||
|
|
||
|
InstallMethod( HasLeftInverseProperty, "for loop",
|
||
|
[ IsLoop ],
|
||
|
function( L )
|
||
|
return ForAll( LeftSection( L ), a -> a^-1 in LeftSection( L ) );
|
||
|
end );
|
||
|
|
||
|
#############################################################################
|
||
|
##
|
||
|
#P HasRightInverseProperty( L )
|
||
|
##
|
||
|
## Returns true if <L> has the right inverse property.
|
||
|
|
||
|
InstallMethod( HasRightInverseProperty, "for loop",
|
||
|
[ IsLoop ],
|
||
|
function( L )
|
||
|
return ForAll( RightSection( L ), a -> a^-1 in RightSection( L ) );
|
||
|
end );
|
||
|
|
||
|
#############################################################################
|
||
|
##
|
||
|
#P HasInverseProperty( L )
|
||
|
##
|
||
|
## Returns true if <L> has the inverse property.
|
||
|
|
||
|
InstallMethod( HasInverseProperty, "for loop",
|
||
|
[ IsLoop ],
|
||
|
function( L )
|
||
|
return HasLeftInverseProperty( L ) and HasRightInverseProperty( L );
|
||
|
end );
|
||
|
|
||
|
#############################################################################
|
||
|
##
|
||
|
#P HasWeakInverseProperty( L )
|
||
|
##
|
||
|
## Returns true if <L> has the weak inverse property.
|
||
|
|
||
|
InstallMethod( HasWeakInverseProperty, "for loop",
|
||
|
[ IsLoop ],
|
||
|
function( L )
|
||
|
return ForAll( L, x -> ForAll( L, y -> LeftInverse(x*y)*x=LeftInverse(y) ));
|
||
|
end );
|
||
|
|
||
|
#############################################################################
|
||
|
##
|
||
|
#P HasTwosidedInverses( L )
|
||
|
##
|
||
|
## Returns true if <L> has two-sided inverses.
|
||
|
|
||
|
InstallMethod( HasTwosidedInverses, "for loop",
|
||
|
[ IsLoop ],
|
||
|
function( L )
|
||
|
return ForAll( L, x -> LeftInverse( x ) = RightInverse( x ) );
|
||
|
end );
|
||
|
|
||
|
#############################################################################
|
||
|
##
|
||
|
#P HasAutomorphicInverseProperty( L )
|
||
|
##
|
||
|
## Returns true if <L> has the automorphic inverse property.
|
||
|
|
||
|
InstallMethod( HasAutomorphicInverseProperty, "for loop",
|
||
|
[ IsLoop ],
|
||
|
function( L )
|
||
|
return ForAll( L, x -> ForAll( L, y ->
|
||
|
LeftInverse( x*y ) = LeftInverse( x )*LeftInverse( y ) ) );
|
||
|
end );
|
||
|
|
||
|
#############################################################################
|
||
|
##
|
||
|
#P HasAntiautomorphicInverseProperty( L )
|
||
|
##
|
||
|
## Returns true if <L> has the antiautomorphic inverse property.
|
||
|
|
||
|
InstallMethod( HasAntiautomorphicInverseProperty, "for loop",
|
||
|
[ IsLoop ],
|
||
|
function( L )
|
||
|
return ForAll( L, x -> ForAll( L, y ->
|
||
|
LeftInverse( x*y ) = LeftInverse( y )*LeftInverse( x ) ) );
|
||
|
end );
|
||
|
|
||
|
# implies and is implied by (for inverse properties)
|
||
|
InstallTrueMethod( HasAntiautomorphicInverseProperty, HasAutomorphicInverseProperty and IsCommutative );
|
||
|
InstallTrueMethod( HasAutomorphicInverseProperty, HasAntiautomorphicInverseProperty and IsCommutative );
|
||
|
InstallTrueMethod( HasLeftInverseProperty, HasInverseProperty );
|
||
|
InstallTrueMethod( HasRightInverseProperty, HasInverseProperty );
|
||
|
InstallTrueMethod( HasWeakInverseProperty, HasInverseProperty );
|
||
|
InstallTrueMethod( HasAntiautomorphicInverseProperty, HasInverseProperty );
|
||
|
InstallTrueMethod( HasTwosidedInverses, HasAntiautomorphicInverseProperty );
|
||
|
InstallTrueMethod( HasInverseProperty, HasLeftInverseProperty and IsCommutative );
|
||
|
InstallTrueMethod( HasInverseProperty, HasRightInverseProperty and IsCommutative );
|
||
|
InstallTrueMethod( HasInverseProperty, HasLeftInverseProperty and HasRightInverseProperty );
|
||
|
InstallTrueMethod( HasInverseProperty, HasLeftInverseProperty and HasWeakInverseProperty );
|
||
|
InstallTrueMethod( HasInverseProperty, HasRightInverseProperty and HasWeakInverseProperty );
|
||
|
InstallTrueMethod( HasInverseProperty, HasLeftInverseProperty and HasAntiautomorphicInverseProperty );
|
||
|
InstallTrueMethod( HasInverseProperty, HasRightInverseProperty and HasAntiautomorphicInverseProperty );
|
||
|
InstallTrueMethod( HasInverseProperty, HasWeakInverseProperty and HasAntiautomorphicInverseProperty );
|
||
|
InstallTrueMethod( HasTwosidedInverses, HasLeftInverseProperty );
|
||
|
InstallTrueMethod( HasTwosidedInverses, HasRightInverseProperty );
|
||
|
InstallTrueMethod( HasTwosidedInverses, IsFlexible and IsLoop );
|
||
|
|
||
|
|
||
|
#############################################################################
|
||
|
## PROPERTIES OF QUASIGROUPS
|
||
|
## -------------------------------------------------------------------------
|
||
|
|
||
|
#############################################################################
|
||
|
##
|
||
|
#P IsSemisymmetric( Q )
|
||
|
##
|
||
|
## Returns true if the quasigroup <Q> is semisymmetric, i.e., (xy)x=y.
|
||
|
|
||
|
InstallMethod( IsSemisymmetric, "for quasigroup",
|
||
|
[ IsQuasigroup ],
|
||
|
function( Q )
|
||
|
return ForAll( Q, x ->
|
||
|
LeftTranslation( Q, x ) * RightTranslation( Q, x ) = () );
|
||
|
end );
|
||
|
|
||
|
#############################################################################
|
||
|
##
|
||
|
#P IsTotallySymmetric( Q )
|
||
|
##
|
||
|
## Returns true if the quasigroup <Q> is totally symmetric, i.e,
|
||
|
## commutative and semisymmetric.
|
||
|
|
||
|
InstallMethod( IsTotallySymmetric, "for quasigroup",
|
||
|
[ IsQuasigroup ],
|
||
|
function( Q )
|
||
|
return IsCommutative( Q ) and IsSemisymmetric( Q );
|
||
|
end );
|
||
|
|
||
|
#############################################################################
|
||
|
##
|
||
|
#P IsIdempotent( Q )
|
||
|
##
|
||
|
## Returns true if the quasigroup <Q> is idempotent, i.e., x*x=x.
|
||
|
|
||
|
InstallMethod( IsIdempotent, "for quasigroup",
|
||
|
[ IsQuasigroup ],
|
||
|
function( Q )
|
||
|
return ForAll( Q, x -> x*x = x );
|
||
|
end );
|
||
|
|
||
|
#############################################################################
|
||
|
##
|
||
|
#P IsSteinerQuasigroup( Q )
|
||
|
##
|
||
|
## Returns true if the quasigroup <Q> is a Steiner quasigroup, i.e.,
|
||
|
## idempotent and totally symmetric.
|
||
|
|
||
|
InstallMethod( IsSteinerQuasigroup, "for quasigroup",
|
||
|
[ IsQuasigroup ],
|
||
|
function( Q )
|
||
|
return IsIdempotent( Q ) and IsTotallySymmetric( Q );
|
||
|
end );
|
||
|
|
||
|
#############################################################################
|
||
|
##
|
||
|
#P IsUnipotent( Q )
|
||
|
##
|
||
|
## Returns true if the quasigroup <Q> is unipotent, i.e., x*x=y*y.
|
||
|
|
||
|
InstallMethod( IsUnipotent, "for quasigroup",
|
||
|
[ IsQuasigroup ],
|
||
|
function( Q )
|
||
|
local square;
|
||
|
if IsLoop( Q ) then return IsIdempotent( Q ); fi;
|
||
|
square := Elements( Q )[ 1 ]^2;
|
||
|
return ForAll( Q, y -> y^2 = square );
|
||
|
end );
|
||
|
|
||
|
#############################################################################
|
||
|
##
|
||
|
#P IsLDistributive( Q )
|
||
|
##
|
||
|
## Returns true if the quasigroup <Q> is left distributive.
|
||
|
|
||
|
InstallOtherMethod( IsLDistributive, "for Quasigroup",
|
||
|
[ IsQuasigroup ],
|
||
|
function( Q )
|
||
|
# BETTER ALGORITHM LATER?
|
||
|
local x, y, z;
|
||
|
for x in Q do for y in Q do for z in Q do
|
||
|
if not x*(y*z) = (x*y)*(x*z) then return false; fi;
|
||
|
od; od; od;
|
||
|
return true;
|
||
|
end );
|
||
|
|
||
|
#############################################################################
|
||
|
##
|
||
|
#P IsRDistributive( Q )
|
||
|
##
|
||
|
## Returns true if the quasigroup <Q> is right distributive.
|
||
|
|
||
|
InstallOtherMethod( IsRDistributive, "for Quasigroup",
|
||
|
[ IsQuasigroup ],
|
||
|
function( Q )
|
||
|
# BETTER ALGORITHM LATER?
|
||
|
local x, y, z;
|
||
|
for x in Q do for y in Q do for z in Q do
|
||
|
if not (x*y)*z = (x*z)*(y*z) then return false; fi;
|
||
|
od; od; od;
|
||
|
return true;
|
||
|
end );
|
||
|
|
||
|
#############################################################################
|
||
|
##
|
||
|
#P IsEntropic( Q )
|
||
|
##
|
||
|
## Returns true if the quasigroup <Q> is entropic.
|
||
|
|
||
|
InstallMethod( IsEntropic, "for quasigroup",
|
||
|
[ IsQuasigroup ],
|
||
|
function( Q )
|
||
|
# BETTER ALGORITHM LATER?
|
||
|
local x, y, z, w;
|
||
|
for x in Q do for y in Q do for z in Q do for w in Q do
|
||
|
if not (x*y)*(z*w) = (x*z)*(y*w) then return false; fi;
|
||
|
od; od; od; od;
|
||
|
return true;
|
||
|
end );
|
||
|
|
||
|
#############################################################################
|
||
|
## LOOPS OF BOL-MOUFANG
|
||
|
## -------------------------------------------------------------------------
|
||
|
|
||
|
#############################################################################
|
||
|
##
|
||
|
#P IsExtraLoop( L )
|
||
|
##
|
||
|
## Returns true if <L> is an extra loop.
|
||
|
|
||
|
InstallMethod( IsExtraLoop, "for loop",
|
||
|
[ IsLoop ],
|
||
|
function( L )
|
||
|
return IsMoufangLoop( L ) and IsNuclearSquareLoop( L );
|
||
|
end );
|
||
|
|
||
|
# implies
|
||
|
InstallTrueMethod( IsMoufangLoop, IsExtraLoop );
|
||
|
InstallTrueMethod( IsCLoop, IsExtraLoop );
|
||
|
|
||
|
# is implied by
|
||
|
InstallTrueMethod( IsExtraLoop, IsMoufangLoop and IsLeftNuclearSquareLoop );
|
||
|
InstallTrueMethod( IsExtraLoop, IsMoufangLoop and IsMiddleNuclearSquareLoop );
|
||
|
InstallTrueMethod( IsExtraLoop, IsMoufangLoop and IsRightNuclearSquareLoop );
|
||
|
|
||
|
#############################################################################
|
||
|
##
|
||
|
#P IsMoufangLoop( L )
|
||
|
##
|
||
|
## Returns true if <L> is a Moufang loop.
|
||
|
|
||
|
InstallMethod( IsMoufangLoop, "for loop",
|
||
|
[ IsLoop ],
|
||
|
function( L )
|
||
|
return IsLeftBolLoop( L ) and HasRightInverseProperty( L );
|
||
|
end );
|
||
|
|
||
|
# implies
|
||
|
InstallTrueMethod( IsLeftBolLoop, IsMoufangLoop );
|
||
|
InstallTrueMethod( IsRightBolLoop, IsMoufangLoop );
|
||
|
InstallTrueMethod( IsDiassociative, IsMoufangLoop );
|
||
|
|
||
|
# is implied by
|
||
|
InstallTrueMethod( IsMoufangLoop, IsLeftBolLoop and IsRightBolLoop );
|
||
|
|
||
|
#############################################################################
|
||
|
##
|
||
|
#P IsCLoop( L )
|
||
|
##
|
||
|
## Returns true if <L> is a C-loop.
|
||
|
|
||
|
InstallMethod( IsCLoop, "for loop",
|
||
|
[ IsLoop ],
|
||
|
function( L )
|
||
|
return IsLCLoop( L ) and IsRCLoop( L );
|
||
|
end );
|
||
|
|
||
|
# implies
|
||
|
InstallTrueMethod( IsLCLoop, IsCLoop );
|
||
|
InstallTrueMethod( IsRCLoop, IsCLoop );
|
||
|
InstallTrueMethod( IsDiassociative, IsCLoop and IsFlexible);
|
||
|
|
||
|
# is implied by
|
||
|
InstallTrueMethod( IsCLoop, IsLCLoop and IsRCLoop );
|
||
|
|
||
|
#############################################################################
|
||
|
##
|
||
|
#P IsLeftBolLoop( L )
|
||
|
##
|
||
|
## Returns true if <L> is a left Bol loop.
|
||
|
|
||
|
InstallMethod( IsLeftBolLoop, "for loop",
|
||
|
[ IsLoop ],
|
||
|
function( L )
|
||
|
return ForAll( LeftSection( L ), a ->
|
||
|
ForAll( LeftSection( L ), b -> a*b*a in LeftSection( L ) ) );
|
||
|
end );
|
||
|
|
||
|
# implies
|
||
|
InstallTrueMethod( IsRightBolLoop, IsLeftBolLoop and IsCommutative );
|
||
|
InstallTrueMethod( IsLeftPowerAlternative, IsLeftBolLoop );
|
||
|
|
||
|
#############################################################################
|
||
|
##
|
||
|
#P IsRightBolLoop( L )
|
||
|
##
|
||
|
## Returns true if <L> is a right Bol loop.
|
||
|
|
||
|
InstallMethod( IsRightBolLoop, "for loop",
|
||
|
[ IsLoop ],
|
||
|
function( L )
|
||
|
return ForAll( RightSection( L ), a ->
|
||
|
ForAll( RightSection( L ), b -> a*b*a in RightSection( L ) ) );
|
||
|
end );
|
||
|
|
||
|
# implies
|
||
|
InstallTrueMethod( IsLeftBolLoop, IsRightBolLoop and IsCommutative );
|
||
|
InstallTrueMethod( IsRightPowerAlternative, IsRightBolLoop );
|
||
|
|
||
|
#############################################################################
|
||
|
##
|
||
|
#P IsLCLoop( L )
|
||
|
##
|
||
|
## Returns true if <L> is an LC-loop.
|
||
|
|
||
|
InstallMethod( IsLCLoop, "for loop",
|
||
|
[ IsLoop ],
|
||
|
function( L )
|
||
|
return ForAll( LeftSection( L ), a ->
|
||
|
ForAll( RightSection( L ), b -> b^(-1)*a*a*b in LeftSection( L ) ) );
|
||
|
end );
|
||
|
|
||
|
# implies
|
||
|
InstallTrueMethod( IsLeftPowerAlternative, IsLCLoop );
|
||
|
InstallTrueMethod( IsLeftNuclearSquareLoop, IsLCLoop );
|
||
|
InstallTrueMethod( IsMiddleNuclearSquareLoop, IsLCLoop );
|
||
|
InstallTrueMethod( IsRCLoop, IsLCLoop and IsCommutative );
|
||
|
|
||
|
#############################################################################
|
||
|
##
|
||
|
#P IsRCLoop( L )
|
||
|
##
|
||
|
## Returns true if <L> is an RC-loop.
|
||
|
|
||
|
InstallMethod( IsRCLoop, "for loop",
|
||
|
[ IsLoop ],
|
||
|
function( L )
|
||
|
return ForAll( LeftSection( L ), a ->
|
||
|
ForAll( RightSection( L ), b -> a^(-1)*b*b*a in RightSection( L ) ) );
|
||
|
end );
|
||
|
|
||
|
# implies
|
||
|
InstallTrueMethod( IsRightPowerAlternative, IsRCLoop );
|
||
|
InstallTrueMethod( IsRightNuclearSquareLoop, IsRCLoop );
|
||
|
InstallTrueMethod( IsMiddleNuclearSquareLoop, IsRCLoop );
|
||
|
InstallTrueMethod( IsLCLoop, IsRCLoop and IsCommutative );
|
||
|
|
||
|
#############################################################################
|
||
|
##
|
||
|
#P IsLeftNuclearSquareLoop( L )
|
||
|
##
|
||
|
## Returns true if <L> is a left nuclear square loop.
|
||
|
|
||
|
InstallMethod( IsLeftNuclearSquareLoop, "for loop",
|
||
|
[ IsLoop ],
|
||
|
function( L )
|
||
|
return ForAll( L, x -> x^2 in LeftNucleus( L ) );
|
||
|
end );
|
||
|
|
||
|
#implies
|
||
|
InstallTrueMethod( IsRightNuclearSquareLoop, IsLeftNuclearSquareLoop and IsCommutative );
|
||
|
|
||
|
#############################################################################
|
||
|
##
|
||
|
#P IsMiddleNuclearSquareLoop( L )
|
||
|
##
|
||
|
## Returns true if <L> is a middle nuclear square loop.
|
||
|
|
||
|
InstallMethod( IsMiddleNuclearSquareLoop, "for loop",
|
||
|
[ IsLoop ],
|
||
|
function( L )
|
||
|
return ForAll( L, x -> x^2 in MiddleNucleus( L ) );
|
||
|
end );
|
||
|
|
||
|
#############################################################################
|
||
|
##
|
||
|
#P IsRightNuclearSquareLoop( L )
|
||
|
##
|
||
|
## Returns true if <L> is a right nuclear square loop.
|
||
|
|
||
|
InstallMethod( IsRightNuclearSquareLoop, "for loop",
|
||
|
[ IsLoop ],
|
||
|
function( L )
|
||
|
return ForAll( L, x -> x^2 in RightNucleus( L ) );
|
||
|
end );
|
||
|
|
||
|
# implies
|
||
|
InstallTrueMethod( IsLeftNuclearSquareLoop, IsRightNuclearSquareLoop and IsCommutative );
|
||
|
|
||
|
#############################################################################
|
||
|
##
|
||
|
#P IsNuclearSquareLoop( L )
|
||
|
##
|
||
|
## Returns true if <L> is a nuclear square loop.
|
||
|
|
||
|
InstallMethod( IsNuclearSquareLoop, "for loop",
|
||
|
[ IsLoop ],
|
||
|
function( L )
|
||
|
return IsLeftNuclearSquareLoop( L ) and IsRightNuclearSquareLoop( L )
|
||
|
and IsMiddleNuclearSquareLoop( L );
|
||
|
end );
|
||
|
|
||
|
# implies
|
||
|
InstallTrueMethod( IsLeftNuclearSquareLoop, IsNuclearSquareLoop );
|
||
|
InstallTrueMethod( IsRightNuclearSquareLoop, IsNuclearSquareLoop );
|
||
|
InstallTrueMethod( IsMiddleNuclearSquareLoop, IsNuclearSquareLoop );
|
||
|
|
||
|
# is implied by
|
||
|
InstallTrueMethod( IsNuclearSquareLoop, IsLeftNuclearSquareLoop
|
||
|
and IsRightNuclearSquareLoop and IsMiddleNuclearSquareLoop );
|
||
|
|
||
|
#############################################################################
|
||
|
##
|
||
|
#P IsFlexible( Q )
|
||
|
##
|
||
|
## Returns true if <Q> is a flexible quasigroup.
|
||
|
|
||
|
InstallMethod( IsFlexible, "for quasigroup",
|
||
|
[ IsQuasigroup ],
|
||
|
function( Q )
|
||
|
local LS, RS;
|
||
|
LS := LeftSection( Q );
|
||
|
RS := RightSection( Q );
|
||
|
return ForAll( [1..Size( Q )], i -> LS[ i ] * RS[ i ] = RS[ i ] * LS[ i ] );
|
||
|
end );
|
||
|
|
||
|
# is implied by
|
||
|
InstallTrueMethod( IsFlexible, IsCommutative );
|
||
|
|
||
|
#############################################################################
|
||
|
##
|
||
|
#P IsLeftAlternative( Q )
|
||
|
##
|
||
|
## Returns true if <Q> is a left alternative quasigroup.
|
||
|
|
||
|
InstallMethod( IsLeftAlternative, "for quasigroup",
|
||
|
[ IsQuasigroup],
|
||
|
function( Q )
|
||
|
if IsLoop( Q ) then
|
||
|
return ForAll( LeftSection( Q ), a -> a*a in LeftSection( Q ) );
|
||
|
fi;
|
||
|
return ForAll( Q, x -> ForAll( Q, y -> x*(x*y) = (x*x)*y ) );
|
||
|
end );
|
||
|
|
||
|
# implies
|
||
|
InstallTrueMethod( IsRightAlternative, IsLeftAlternative and IsCommutative );
|
||
|
|
||
|
#############################################################################
|
||
|
##
|
||
|
#P IsRightAlternative( Q )
|
||
|
##
|
||
|
## Returns true if <Q> is a right alternative quasigroup.
|
||
|
|
||
|
InstallMethod( IsRightAlternative, "for quasigroup",
|
||
|
[ IsQuasigroup ],
|
||
|
function( Q )
|
||
|
if IsLoop( Q ) then
|
||
|
return ForAll( RightSection( Q ), a -> a*a in RightSection( Q ) );
|
||
|
fi;
|
||
|
return ForAll( Q, x -> ForAll( Q, y -> (x*y)*y = x*(y*y) ) );
|
||
|
end );
|
||
|
|
||
|
# implies
|
||
|
InstallTrueMethod( IsLeftAlternative, IsRightAlternative and IsCommutative );
|
||
|
|
||
|
#############################################################################
|
||
|
##
|
||
|
#P IsAlternative( Q )
|
||
|
##
|
||
|
## Returns true if <Q> is an alternative quasigroup.
|
||
|
|
||
|
InstallMethod( IsAlternative, "for quasigroup",
|
||
|
[ IsQuasigroup ],
|
||
|
function( Q )
|
||
|
return IsLeftAlternative( Q ) and IsRightAlternative( Q );
|
||
|
end );
|
||
|
|
||
|
# implies
|
||
|
InstallTrueMethod( IsLeftAlternative, IsAlternative );
|
||
|
InstallTrueMethod( IsRightAlternative, IsAlternative );
|
||
|
|
||
|
# is implied by
|
||
|
InstallTrueMethod( IsAlternative, IsLeftAlternative and IsRightAlternative );
|
||
|
|
||
|
#############################################################################
|
||
|
## POWER ALTERNATIVE LOOPS
|
||
|
## -------------------------------------------------------------------------
|
||
|
|
||
|
#############################################################################
|
||
|
##
|
||
|
#P IsLeftPowerAlternative( L )
|
||
|
##
|
||
|
## Returns true if <L> is a left power alternative loop.
|
||
|
|
||
|
InstallMethod( IsLeftPowerAlternative, "for loop",
|
||
|
[ IsLoop ],
|
||
|
function( L )
|
||
|
local i, M;
|
||
|
if Size( L ) = 1 then return true; fi;
|
||
|
for i in [ 2..Size( L )] do
|
||
|
M := Subloop( L, [ Elements( L )[ i ] ]);
|
||
|
if not Size( RelativeLeftMultiplicationGroup( L, M ) ) = Size( M ) then
|
||
|
return false;
|
||
|
fi;
|
||
|
od;
|
||
|
return true;
|
||
|
end );
|
||
|
|
||
|
# implies
|
||
|
InstallTrueMethod( IsLeftAlternative, IsLeftPowerAlternative );
|
||
|
InstallTrueMethod( HasLeftInverseProperty, IsLeftPowerAlternative );
|
||
|
InstallTrueMethod( IsPowerAssociative, IsLeftPowerAlternative );
|
||
|
|
||
|
#############################################################################
|
||
|
##
|
||
|
#P IsRightPowerAlternative( L )
|
||
|
##
|
||
|
## Returns true if <L> is a right power alternative loop.
|
||
|
|
||
|
InstallMethod( IsRightPowerAlternative, "for loop",
|
||
|
[ IsLoop ],
|
||
|
function( L )
|
||
|
local i, M;
|
||
|
if Size( L ) = 1 then return true; fi;
|
||
|
for i in [ 2..Size( L ) ] do
|
||
|
M := Subloop( L, [ Elements( L )[ i ] ] );
|
||
|
if not Size( RelativeRightMultiplicationGroup( L, M ) ) = Size( M ) then
|
||
|
return false;
|
||
|
fi;
|
||
|
od;
|
||
|
return true;
|
||
|
end );
|
||
|
|
||
|
# implies
|
||
|
InstallTrueMethod( IsRightAlternative, IsRightPowerAlternative );
|
||
|
InstallTrueMethod( HasRightInverseProperty, IsRightPowerAlternative );
|
||
|
InstallTrueMethod( IsPowerAssociative, IsRightPowerAlternative );
|
||
|
|
||
|
#############################################################################
|
||
|
##
|
||
|
#P IsPowerAlternative( L )
|
||
|
##
|
||
|
## Returns true if <L> is a power alternative loop.
|
||
|
|
||
|
InstallMethod( IsPowerAlternative, "for loop",
|
||
|
[ IsLoop ],
|
||
|
function( L )
|
||
|
return ( IsLeftPowerAlternative( L ) and IsRightPowerAlternative( L ) );
|
||
|
end );
|
||
|
|
||
|
# implies
|
||
|
InstallTrueMethod( IsLeftPowerAlternative, IsPowerAlternative );
|
||
|
InstallTrueMethod( IsRightPowerAlternative, IsPowerAlternative );
|
||
|
|
||
|
#############################################################################
|
||
|
## CC-LOOPS AND RELATED PROPERTIES
|
||
|
## -------------------------------------------------------------------------
|
||
|
|
||
|
#############################################################################
|
||
|
##
|
||
|
#P IsLCCLoop( L )
|
||
|
##
|
||
|
## Returns true if <L> is a left conjugacy closed loop.
|
||
|
|
||
|
InstallMethod( IsLCCLoop, "for loop",
|
||
|
[ IsLoop ],
|
||
|
function( L )
|
||
|
return ForAll( LeftSection( L ), a ->
|
||
|
ForAll( LeftSection( L ), b -> b*a*b^(-1) in LeftSection( L ) ) );
|
||
|
end );
|
||
|
|
||
|
# implies
|
||
|
InstallTrueMethod( IsAssociative, IsLCCLoop and IsCommutative );
|
||
|
InstallTrueMethod( IsExtraLoop, IsLCCLoop and IsMoufangLoop );
|
||
|
|
||
|
#############################################################################
|
||
|
##
|
||
|
#P IsRCCLoop( L )
|
||
|
##
|
||
|
## Returns true if <L> is a right conjugacy closed loop.
|
||
|
|
||
|
InstallMethod( IsRCCLoop, "for loop",
|
||
|
[ IsLoop ],
|
||
|
function( L )
|
||
|
return ForAll( RightSection( L ), a ->
|
||
|
ForAll( RightSection( L ), b -> b*a*b^(-1) in RightSection( L ) ) );
|
||
|
end );
|
||
|
|
||
|
# implies
|
||
|
InstallTrueMethod( IsAssociative, IsRCCLoop and IsCommutative );
|
||
|
InstallTrueMethod( IsExtraLoop, IsRCCLoop and IsMoufangLoop );
|
||
|
|
||
|
#############################################################################
|
||
|
##
|
||
|
#P IsCCLoop( L )
|
||
|
##
|
||
|
## Returns true if <L> is a conjugacy closed loop.
|
||
|
|
||
|
InstallMethod( IsCCLoop, "for loop",
|
||
|
[ IsLoop ],
|
||
|
function( L )
|
||
|
return IsLCCLoop( L ) and IsRCCLoop( L );
|
||
|
end );
|
||
|
|
||
|
# implies
|
||
|
InstallTrueMethod( IsLCCLoop, IsCCLoop );
|
||
|
InstallTrueMethod( IsRCCLoop, IsCCLoop );
|
||
|
|
||
|
# is implied by
|
||
|
InstallTrueMethod( IsCCLoop, IsLCCLoop and IsRCCLoop );
|
||
|
|
||
|
#############################################################################
|
||
|
##
|
||
|
#P IsOsbornLoop( L )
|
||
|
##
|
||
|
## Returns true if <L> is an Osborn loop.
|
||
|
|
||
|
InstallMethod( IsOsbornLoop, "for loop",
|
||
|
[ IsLoop ],
|
||
|
function( L )
|
||
|
# MIGHT REDO LATER
|
||
|
return ForAll(L, x-> ForAll(L, y->
|
||
|
ForAll(L, z-> x*((y*z)*x) = LeftDivision(LeftInverse(x),y)*(z*x))
|
||
|
));
|
||
|
end );
|
||
|
|
||
|
# is implied by
|
||
|
InstallTrueMethod( IsOsbornLoop, IsMoufangLoop );
|
||
|
InstallTrueMethod( IsOsbornLoop, IsCCLoop );
|
||
|
|
||
|
#############################################################################
|
||
|
## ADDITIONAL VARIETIES OF LOOPS
|
||
|
## -------------------------------------------------------------------------
|
||
|
|
||
|
#############################################################################
|
||
|
##
|
||
|
#P IsCodeLoop( L )
|
||
|
##
|
||
|
## Returns true if <L> is an even code loop.
|
||
|
|
||
|
InstallMethod( IsCodeLoop, "for loop",
|
||
|
[ IsLoop ],
|
||
|
function( L )
|
||
|
# even code loops are precisely Moufang 2-loops with Frattini subloop of order 1, 2
|
||
|
return Set( Factors( Size( L ) ) ) = [ 2 ]
|
||
|
and IsMoufangLoop( L )
|
||
|
and Size( FrattiniSubloop( L ) ) in [1, 2];
|
||
|
end );
|
||
|
|
||
|
# implies
|
||
|
InstallTrueMethod( IsExtraLoop, IsCodeLoop );
|
||
|
InstallTrueMethod( IsCCLoop, IsCodeLoop );
|
||
|
|
||
|
#############################################################################
|
||
|
##
|
||
|
#P IsSteinerLoop( L )
|
||
|
##
|
||
|
## Returns true if <L> is a Steiner loop.
|
||
|
|
||
|
InstallMethod( IsSteinerLoop, "for loop",
|
||
|
[ IsLoop ],
|
||
|
function( L )
|
||
|
# Steiner loops are inverse property loops of exponent at most 2.
|
||
|
return HasInverseProperty( L ) and Exponent( L )<=2;
|
||
|
end );
|
||
|
|
||
|
# implies
|
||
|
InstallTrueMethod( IsCommutative, IsSteinerLoop );
|
||
|
InstallTrueMethod( IsCLoop, IsSteinerLoop );
|
||
|
|
||
|
#############################################################################
|
||
|
##
|
||
|
#P IsLeftBruckLoop( L )
|
||
|
##
|
||
|
## Returns true if <L> is a left Bruck loop.
|
||
|
|
||
|
InstallMethod( IsLeftBruckLoop, "for loop",
|
||
|
[ IsLoop ],
|
||
|
function( L )
|
||
|
return IsLeftBolLoop( L ) and HasAutomorphicInverseProperty( L );
|
||
|
end );
|
||
|
|
||
|
# implies
|
||
|
InstallTrueMethod( HasAutomorphicInverseProperty, IsLeftBruckLoop );
|
||
|
InstallTrueMethod( IsLeftBolLoop, IsLeftBruckLoop );
|
||
|
InstallTrueMethod( IsRightBruckLoop, IsLeftBruckLoop and IsCommutative );
|
||
|
|
||
|
# is implied by
|
||
|
InstallTrueMethod( IsLeftBruckLoop, IsLeftBolLoop and HasAutomorphicInverseProperty );
|
||
|
|
||
|
#############################################################################
|
||
|
##
|
||
|
#P IsRightBruckLoop( L )
|
||
|
##
|
||
|
## Returns true if <L> is a right Bruck loop.
|
||
|
|
||
|
InstallMethod( IsRightBruckLoop, "for loop",
|
||
|
[ IsLoop ],
|
||
|
function( L )
|
||
|
return IsRightBolLoop( L ) and HasAutomorphicInverseProperty( L );
|
||
|
end );
|
||
|
|
||
|
# implies
|
||
|
InstallTrueMethod( HasAutomorphicInverseProperty, IsRightBruckLoop );
|
||
|
InstallTrueMethod( IsRightBolLoop, IsRightBruckLoop );
|
||
|
InstallTrueMethod( IsLeftBruckLoop, IsRightBruckLoop and IsCommutative );
|
||
|
|
||
|
# is implied by
|
||
|
InstallTrueMethod( IsRightBruckLoop, IsRightBolLoop and HasAutomorphicInverseProperty );
|
||
|
|
||
|
#############################################################################
|
||
|
##
|
||
|
#P IsLeftALoop( L )
|
||
|
##
|
||
|
## Returns true if <L> is a left A-loop, that is if
|
||
|
## all left inner mappings are automorphisms of <L>.
|
||
|
|
||
|
InstallMethod( IsLeftALoop, "for loop",
|
||
|
[ IsLoop ],
|
||
|
function( L )
|
||
|
local gens;
|
||
|
gens := GeneratorsOfGroup( LeftInnerMappingGroup( L ) );
|
||
|
return ForAll(gens, f -> ForAll(L, x -> ForAll(L, y -> (x * y)^f = x^f * y^f )));
|
||
|
end);
|
||
|
|
||
|
#############################################################################
|
||
|
##
|
||
|
#P IsRightALoop( L )
|
||
|
##
|
||
|
## Returns true if <L> is a right A-loop, that is if
|
||
|
## all right inner mappings are automorphisms of <L>.
|
||
|
|
||
|
InstallMethod( IsRightALoop, "for loop",
|
||
|
[ IsLoop ],
|
||
|
function( L )
|
||
|
local gens;
|
||
|
gens := GeneratorsOfGroup( RightInnerMappingGroup( L ) );
|
||
|
return ForAll(gens, f -> ForAll(L, x -> ForAll(L, y -> (x * y)^f = x^f * y^f )));
|
||
|
end);
|
||
|
|
||
|
#############################################################################
|
||
|
##
|
||
|
#P IsMiddleALoop( L )
|
||
|
##
|
||
|
## Returns true if <L> is a middle A-loop, that is if
|
||
|
## all middle inner mappings (conjugations) are automorphisms of <L>.
|
||
|
|
||
|
InstallMethod( IsMiddleALoop, "for loop",
|
||
|
[ IsLoop ],
|
||
|
function( L )
|
||
|
local gens;
|
||
|
gens := GeneratorsOfGroup( MiddleInnerMappingGroup( L ) );
|
||
|
return ForAll(gens, f -> ForAll(L, x -> ForAll(L, y -> (x * y)^f = x^f * y^f )));
|
||
|
end);
|
||
|
|
||
|
#############################################################################
|
||
|
##
|
||
|
#P IsALoop( L )
|
||
|
##
|
||
|
## Returns true if <L> is an A-loop, that is if
|
||
|
## all inner mappings are automorphisms of <L>.
|
||
|
|
||
|
InstallMethod( IsALoop, "for loop",
|
||
|
[ IsLoop ],
|
||
|
function( Q )
|
||
|
return IsLeftALoop(Q) and IsRightALoop(Q) and IsMiddleALoop(Q);
|
||
|
end);
|
||
|
|
||
|
# implies
|
||
|
InstallTrueMethod( IsLeftALoop, IsALoop );
|
||
|
InstallTrueMethod( IsRightALoop, IsALoop );
|
||
|
InstallTrueMethod( IsMiddleALoop, IsALoop );
|
||
|
InstallTrueMethod( IsMiddleALoop, IsCommutative );
|
||
|
InstallTrueMethod( IsALoop, IsLeftALoop and IsCommutative );
|
||
|
InstallTrueMethod( IsALoop, IsRightALoop and IsCommutative );
|
||
|
InstallTrueMethod( IsLeftALoop, IsRightALoop and HasAntiautomorphicInverseProperty );
|
||
|
InstallTrueMethod( IsRightALoop, IsLeftALoop and HasAntiautomorphicInverseProperty );
|
||
|
InstallTrueMethod( IsFlexible, IsMiddleALoop );
|
||
|
InstallTrueMethod( HasAntiautomorphicInverseProperty, IsFlexible and IsLeftALoop );
|
||
|
InstallTrueMethod( HasAntiautomorphicInverseProperty, IsFlexible and IsRightALoop );
|
||
|
InstallTrueMethod( IsMoufangLoop, IsALoop and IsLeftAlternative );
|
||
|
InstallTrueMethod( IsMoufangLoop, IsALoop and IsRightAlternative );
|
||
|
InstallTrueMethod( IsMoufangLoop, IsALoop and HasLeftInverseProperty );
|
||
|
InstallTrueMethod( IsMoufangLoop, IsALoop and HasRightInverseProperty );
|
||
|
InstallTrueMethod( IsMoufangLoop, IsALoop and HasWeakInverseProperty );
|
||
|
|
||
|
# is implied by
|
||
|
InstallTrueMethod( IsLeftALoop, IsLeftBruckLoop );
|
||
|
InstallTrueMethod( IsLeftALoop, IsLCCLoop );
|
||
|
InstallTrueMethod( IsRightALoop, IsRightBruckLoop );
|
||
|
InstallTrueMethod( IsRightALoop, IsRCCLoop );
|
||
|
InstallTrueMethod( IsALoop, IsCommutative and IsMoufangLoop );
|