factor out parts of direct product computation that can be reused for racks
This commit is contained in:
parent
68390c3869
commit
1493a9c480
@ -44,14 +44,14 @@ InstallTrueMethod(IsLeftQuotientElement, IsMultiplicativeElementWithInverse);
|
|||||||
## DeclareOperation("LeftQuotient", [IsLeftQuotientElement,IsExtLElement]);
|
## DeclareOperation("LeftQuotient", [IsLeftQuotientElement,IsExtLElement]);
|
||||||
|
|
||||||
## element of a quasigroup
|
## element of a quasigroup
|
||||||
DeclareCategory( "IsQuasigroupElement",
|
DeclareSynonym( "IsQuasigroupElement",
|
||||||
IsMultiplicativeElement and
|
IsMultiplicativeElement and
|
||||||
IsLeftQuotientElement and IsRightQuotientElement );
|
IsLeftQuotientElement and IsRightQuotientElement );
|
||||||
DeclareRepresentation( "IsQuasigroupElmRep",
|
DeclareRepresentation( "IsQuasigroupElmRep",
|
||||||
IsPositionalObjectRep and IsMultiplicativeElement, [1] );
|
IsPositionalObjectRep and IsMultiplicativeElement, [1] );
|
||||||
|
|
||||||
## element of a loop
|
## element of a loop
|
||||||
DeclareCategory( "IsLoopElement",
|
DeclareSynonym( "IsLoopElement",
|
||||||
IsQuasigroupElement and IsMultiplicativeElementWithInverse );
|
IsQuasigroupElement and IsMultiplicativeElementWithInverse );
|
||||||
DeclareRepresentation( "IsLoopElmRep",
|
DeclareRepresentation( "IsLoopElmRep",
|
||||||
IsPositionalObjectRep and IsMultiplicativeElementWithInverse, [1] );
|
IsPositionalObjectRep and IsMultiplicativeElementWithInverse, [1] );
|
||||||
@ -64,17 +64,11 @@ DeclareCategory("IsRightQuasigroup",
|
|||||||
DeclareCategory("IsLeftQuasigroup",
|
DeclareCategory("IsLeftQuasigroup",
|
||||||
IsMagma and IsLeftQuotientElementCollection);
|
IsMagma and IsLeftQuotientElementCollection);
|
||||||
|
|
||||||
|
|
||||||
## latin (auxiliary category for GAP to tell apart IsMagma and IsQuasigroup)
|
|
||||||
DeclareSynonym( "IsLatin",
|
|
||||||
IsRightQuotientElementCollection and
|
|
||||||
IsLeftQuotientElementCollection );
|
|
||||||
|
|
||||||
## quasigroup
|
## quasigroup
|
||||||
DeclareCategory( "IsQuasigroup", IsMagma and IsLatin );
|
DeclareSynonym( "IsQuasigroup", IsRightQuasigroup and IsLeftQuasigroup );
|
||||||
|
|
||||||
## loop
|
## loop
|
||||||
DeclareCategory( "IsLoop", IsQuasigroup and IsMagmaWithOne and
|
DeclareSynonym( "IsLoop", IsQuasigroup and IsMagmaWithOne and
|
||||||
IsMultiplicativeElementWithInverseCollection);
|
IsMultiplicativeElementWithInverseCollection);
|
||||||
|
|
||||||
#############################################################################
|
#############################################################################
|
||||||
@ -139,6 +133,7 @@ DeclareOperation( "IntoGroup", [ IsMagma ] );
|
|||||||
## PRODUCTS OF QUASIGROUPS AND LOOPS
|
## PRODUCTS OF QUASIGROUPS AND LOOPS
|
||||||
## --------------------------------------------------------------------------
|
## --------------------------------------------------------------------------
|
||||||
|
|
||||||
|
DeclareGlobalFuntion("ProductTableOfCanonicalCayleyTables");
|
||||||
#DirectProduct already declared for groups.
|
#DirectProduct already declared for groups.
|
||||||
|
|
||||||
#############################################################################
|
#############################################################################
|
||||||
|
@ -732,98 +732,104 @@ end);
|
|||||||
# groups in GAP. The idea is as follows:
|
# groups in GAP. The idea is as follows:
|
||||||
# We want to calculate direct product of quasigroups, loops and groups.
|
# We want to calculate direct product of quasigroups, loops and groups.
|
||||||
# If only groups are on the list, standard GAP DirectProduct will take care
|
# If only groups are on the list, standard GAP DirectProduct will take care
|
||||||
# of it. If there are also some quasigroups or loops on the list,
|
# of it. If there are also some quasigroups or loops on the list (but nothing
|
||||||
# we must take care of it.
|
# that is not a quasigroup), we must take care of it.
|
||||||
# However, we do not know if such a list will be processed with
|
# However, we do not know if such a list will be processed with
|
||||||
# DirectProductOp( <IsList>, <IsGroup> ), or
|
# DirectProductOp( <IsList>, <IsGroup> ), or
|
||||||
# DirectProductOp( <IsList>, <IsQuasigroup> ),
|
# DirectProductOp( <IsList>, <IsQuasigroup> ),
|
||||||
# since this depends on which algebra is listed first.
|
# since this depends on which algebra is listed first.
|
||||||
# We therefore take care of both situations.
|
# Call the item in the second argument of DirectProductOp the "distinguished"
|
||||||
|
# item. To produce the correct result whichever of the two above cases for
|
||||||
|
# DirectProductOp ends up being called, we add a method in the first case
|
||||||
|
# which repeats the product call with the first non-group it encounters (if
|
||||||
|
# any) as the distinguished item. Further, the method for the
|
||||||
|
# latter case must itself repeat the call with a similar reordering if it
|
||||||
|
# finds anyitem that is not a quasigroup.
|
||||||
|
|
||||||
InstallOtherMethod( DirectProductOp, "for DirectProduct( <IsList>, <IsGroup> )",
|
InstallMethod( DirectProductOp, "for DirectProduct( <IsList>, <IsGroup> )",
|
||||||
[ IsList, IsGroup],
|
[ IsList, IsGroup],
|
||||||
function( list, first )
|
function( list, first )
|
||||||
local L, p;
|
local L, p;
|
||||||
|
|
||||||
# Check the arguments.
|
# Check the arguments.
|
||||||
if IsEmpty( list ) then Error( "LOOPS: <1> must be nonempty." ); fi;
|
if IsEmpty( list ) then
|
||||||
if not ForAny( list, IsQuasigroup ) then
|
Error( "LOOPS: <1> must be nonempty." );
|
||||||
# there are no quasigroups or loops on the list
|
elif Length(list) = 1 then
|
||||||
TryNextMethod();
|
return list[1];
|
||||||
fi;
|
fi;
|
||||||
if ForAny( list, G -> (not IsGroup( G )) and (not IsQuasigroup( G ) ) ) then
|
for p in [1..Length(list)] do
|
||||||
# there are other objects beside groups, loops and quasigroups on the list
|
if not IsGroup(list[p]) then
|
||||||
TryNextMethod();
|
return DirectProductOp(Permuted(list, (1,p)), list[p]);
|
||||||
fi;
|
|
||||||
|
|
||||||
# all arguments are groups, quasigroups or loops, and there is at least one loop
|
|
||||||
# making sure that a loop is listed first so that this method is not called again
|
|
||||||
for L in list do
|
|
||||||
if not IsGroup( L ) then
|
|
||||||
p := Position( list, L );
|
|
||||||
list[ 1 ] := L;
|
|
||||||
list[ p ] := first;
|
|
||||||
break;
|
|
||||||
fi;
|
fi;
|
||||||
od;
|
od;
|
||||||
|
# OK, everything is a group, so let the rest of GAP do the work.
|
||||||
|
TryNextMethod();
|
||||||
|
end);
|
||||||
|
|
||||||
return DirectProductOp( list, list[ 1 ] );
|
InstallGlobalFunction(ProductTableOfCanonicalCayleyTables,
|
||||||
|
function(tablist)
|
||||||
|
local n, i, nL, nM, TL, TM, T, j, k, s;
|
||||||
|
TL := tablist[1];
|
||||||
|
for s in [2..n] do
|
||||||
|
TM := tablist[ s ];
|
||||||
|
nL := Length( TL); nM := Length( TM );
|
||||||
|
T := List( [1..nL*nM], j->[] );
|
||||||
|
# not efficient, but it does the job
|
||||||
|
for i in [1..nM] do for j in [1..nM] do for k in [1..nL] do
|
||||||
|
Append( T[ (i-1)*nL + k ], TL[ k ] + nL*(TM[i][j]-1) );
|
||||||
|
od; od; od;
|
||||||
|
TL := T;
|
||||||
|
od;
|
||||||
|
return TL;
|
||||||
end);
|
end);
|
||||||
|
|
||||||
InstallOtherMethod( DirectProductOp, "for DirectProduct( <IsList>, <IsQuasigroup> )",
|
InstallOtherMethod( DirectProductOp, "for DirectProduct( <IsList>, <IsQuasigroup> )",
|
||||||
[ IsList, IsQuasigroup ],
|
[ IsList, IsQuasigroup ],
|
||||||
function( list, dummy )
|
function( list, dummy )
|
||||||
|
|
||||||
local group_list, quasigroup_list, group_product, are_all_loops,
|
local group_list, quasigroup_list, group_product, are_all_loops, n, i, T;
|
||||||
n, i, nL, nM, TL, TM, T, j, k, s;
|
|
||||||
|
|
||||||
# check the arguments
|
# check the arguments
|
||||||
if IsEmpty( list ) then
|
if IsEmpty( list ) then
|
||||||
Error( "LOOPS: <1> must be nonempty." );
|
Error( "LOOPS: <1> must be nonempty." );
|
||||||
elif ForAny( list, G -> (not IsGroup( G )) and (not IsQuasigroup( G ) ) ) then
|
elif Length(list) = 1 then
|
||||||
TryNextMethod();
|
return list(1);
|
||||||
fi;
|
fi;
|
||||||
|
group_list := [];
|
||||||
|
quasigroup_list := list{[1]};
|
||||||
|
are_all_loops := true;
|
||||||
|
for i in [2..Length(list)] do
|
||||||
|
if IsGroup(list[i]) then
|
||||||
|
Add(group_list, list[i]);
|
||||||
|
elif IsQuasigroup(list[i]) then
|
||||||
|
Add(quasigroup_list, list[i]);
|
||||||
|
if are_all_loops and not IsLoop(list[i]) then
|
||||||
|
are_all_loops := false;
|
||||||
|
fi;
|
||||||
|
else # Oops, something that's neither a group or quasigroup
|
||||||
|
return DirectProductOp(Permuted(list,(1.i)), list[i]);
|
||||||
|
fi;
|
||||||
|
od;
|
||||||
|
|
||||||
# only groups, quasigroups and loops are on the list, with at least one non-group
|
# only groups, quasigroups and loops are on the list, with at least one
|
||||||
group_list := Filtered( list, G -> IsGroup( G ) );
|
# non-group; moreover, we have partitioned the list into groups and
|
||||||
quasigroup_list := Filtered( list, G -> IsQuasigroup( G ) );
|
# non-groups and checked whether all quasigroups are really loops.
|
||||||
if not IsEmpty( group_list ) then # some groups are on the list
|
if not IsEmpty( group_list ) then # some groups are on the list
|
||||||
group_product := DirectProductOp( group_list, group_list[ 1 ] );
|
group_product := DirectProductOp( group_list, group_list[ 1 ] );
|
||||||
Add( quasigroup_list, IntoLoop( group_product ) );
|
Add( quasigroup_list, IntoLoop( group_product ) );
|
||||||
fi;
|
fi;
|
||||||
# keeping track of whether all algebras are in fact loops
|
|
||||||
are_all_loops := ForAll( quasigroup_list, IsLoop );
|
|
||||||
|
|
||||||
# now only quasigroups and loops are on the list
|
# now only quasigroups and loops are on the list, with at least 2 of them
|
||||||
n := Length( quasigroup_list );
|
n := Length( quasigroup_list );
|
||||||
if n=1 then
|
# We willl not use recursion; start by making all Cayley tables canonical
|
||||||
return quasigroup_list[ 1 ];
|
Apply(quasigroup_list,
|
||||||
fi;
|
Q -> CanonicalCayleyTableOfLeftQuasigroupTable( CayleyTable( Q ) ) );
|
||||||
# at least 2 quasigroups and loops; we will not use recursion
|
T := ProductTableOfCanonicalCayleyTables( quasigroup_list );
|
||||||
# making all Cayley tables canonical
|
|
||||||
for s in [1..n] do
|
|
||||||
quasigroup_list[ s ] :=
|
|
||||||
CanonicalCayleyTableOfLeftQuasigroupTable(
|
|
||||||
CayleyTable( quasigroup_list[ s ] ) );
|
|
||||||
od;
|
|
||||||
# At this point the entries in quasigroup_list are really just tables
|
|
||||||
for s in [2..n] do
|
|
||||||
nL := Length( quasigroup_list[ 1 ] );
|
|
||||||
nM := Length( quasigroup_list[ s ] );
|
|
||||||
TL := quasigroup_list[ 1 ];
|
|
||||||
TM := quasigroup_list[ s ];
|
|
||||||
T := List( [1..nL*nM], j->[] );
|
|
||||||
|
|
||||||
# not efficient, but it does the job
|
|
||||||
for i in [1..nM] do for j in [1..nM] do for k in [1..nL] do
|
|
||||||
Append( T[ (i-1)*nL + k ], TL[ k ] + nL*(TM[i][j]-1) );
|
|
||||||
od; od; od;
|
|
||||||
quasigroup_list[ 1 ] := T;
|
|
||||||
od;
|
|
||||||
if are_all_loops then
|
if are_all_loops then
|
||||||
return LoopByCayleyTable( quasigroup_list[1] );
|
return LoopByCayleyTable( T );
|
||||||
fi;
|
fi;
|
||||||
return QuasigroupByCayleyTable( quasigroup_list[1] );
|
return QuasigroupByCayleyTable( T );
|
||||||
end );
|
end );
|
||||||
|
|
||||||
#############################################################################
|
#############################################################################
|
||||||
|
Loading…
Reference in New Issue
Block a user