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]);
|
||||
|
||||
## element of a quasigroup
|
||||
DeclareCategory( "IsQuasigroupElement",
|
||||
IsMultiplicativeElement and
|
||||
IsLeftQuotientElement and IsRightQuotientElement );
|
||||
DeclareSynonym( "IsQuasigroupElement",
|
||||
IsMultiplicativeElement and
|
||||
IsLeftQuotientElement and IsRightQuotientElement );
|
||||
DeclareRepresentation( "IsQuasigroupElmRep",
|
||||
IsPositionalObjectRep and IsMultiplicativeElement, [1] );
|
||||
|
||||
## element of a loop
|
||||
DeclareCategory( "IsLoopElement",
|
||||
DeclareSynonym( "IsLoopElement",
|
||||
IsQuasigroupElement and IsMultiplicativeElementWithInverse );
|
||||
DeclareRepresentation( "IsLoopElmRep",
|
||||
IsPositionalObjectRep and IsMultiplicativeElementWithInverse, [1] );
|
||||
@ -64,17 +64,11 @@ DeclareCategory("IsRightQuasigroup",
|
||||
DeclareCategory("IsLeftQuasigroup",
|
||||
IsMagma and IsLeftQuotientElementCollection);
|
||||
|
||||
|
||||
## latin (auxiliary category for GAP to tell apart IsMagma and IsQuasigroup)
|
||||
DeclareSynonym( "IsLatin",
|
||||
IsRightQuotientElementCollection and
|
||||
IsLeftQuotientElementCollection );
|
||||
|
||||
## quasigroup
|
||||
DeclareCategory( "IsQuasigroup", IsMagma and IsLatin );
|
||||
DeclareSynonym( "IsQuasigroup", IsRightQuasigroup and IsLeftQuasigroup );
|
||||
|
||||
## loop
|
||||
DeclareCategory( "IsLoop", IsQuasigroup and IsMagmaWithOne and
|
||||
DeclareSynonym( "IsLoop", IsQuasigroup and IsMagmaWithOne and
|
||||
IsMultiplicativeElementWithInverseCollection);
|
||||
|
||||
#############################################################################
|
||||
@ -139,6 +133,7 @@ DeclareOperation( "IntoGroup", [ IsMagma ] );
|
||||
## PRODUCTS OF QUASIGROUPS AND LOOPS
|
||||
## --------------------------------------------------------------------------
|
||||
|
||||
DeclareGlobalFuntion("ProductTableOfCanonicalCayleyTables");
|
||||
#DirectProduct already declared for groups.
|
||||
|
||||
#############################################################################
|
||||
|
@ -732,98 +732,104 @@ end);
|
||||
# groups in GAP. The idea is as follows:
|
||||
# We want to calculate direct product of quasigroups, loops and groups.
|
||||
# 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,
|
||||
# we must take care of it.
|
||||
# of it. If there are also some quasigroups or loops on the list (but nothing
|
||||
# that is not a quasigroup), we must take care of it.
|
||||
# However, we do not know if such a list will be processed with
|
||||
# DirectProductOp( <IsList>, <IsGroup> ), or
|
||||
# DirectProductOp( <IsList>, <IsQuasigroup> ),
|
||||
# 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],
|
||||
function( list, first )
|
||||
local L, p;
|
||||
|
||||
# Check the arguments.
|
||||
if IsEmpty( list ) then Error( "LOOPS: <1> must be nonempty." ); fi;
|
||||
if not ForAny( list, IsQuasigroup ) then
|
||||
# there are no quasigroups or loops on the list
|
||||
TryNextMethod();
|
||||
if IsEmpty( list ) then
|
||||
Error( "LOOPS: <1> must be nonempty." );
|
||||
elif Length(list) = 1 then
|
||||
return list[1];
|
||||
fi;
|
||||
if ForAny( list, G -> (not IsGroup( G )) and (not IsQuasigroup( G ) ) ) then
|
||||
# there are other objects beside groups, loops and quasigroups on the list
|
||||
TryNextMethod();
|
||||
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;
|
||||
for p in [1..Length(list)] do
|
||||
if not IsGroup(list[p]) then
|
||||
return DirectProductOp(Permuted(list, (1,p)), list[p]);
|
||||
fi;
|
||||
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);
|
||||
|
||||
InstallOtherMethod( DirectProductOp, "for DirectProduct( <IsList>, <IsQuasigroup> )",
|
||||
[ IsList, IsQuasigroup ],
|
||||
function( list, dummy )
|
||||
|
||||
local group_list, quasigroup_list, group_product, are_all_loops,
|
||||
n, i, nL, nM, TL, TM, T, j, k, s;
|
||||
local group_list, quasigroup_list, group_product, are_all_loops, n, i, T;
|
||||
|
||||
# check the arguments
|
||||
if IsEmpty( list ) then
|
||||
Error( "LOOPS: <1> must be nonempty." );
|
||||
elif ForAny( list, G -> (not IsGroup( G )) and (not IsQuasigroup( G ) ) ) then
|
||||
TryNextMethod();
|
||||
elif Length(list) = 1 then
|
||||
return list(1);
|
||||
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
|
||||
group_list := Filtered( list, G -> IsGroup( G ) );
|
||||
quasigroup_list := Filtered( list, G -> IsQuasigroup( G ) );
|
||||
# only groups, quasigroups and loops are on the list, with at least one
|
||||
# non-group; moreover, we have partitioned the list into groups and
|
||||
# non-groups and checked whether all quasigroups are really loops.
|
||||
if not IsEmpty( group_list ) then # some groups are on the list
|
||||
group_product := DirectProductOp( group_list, group_list[ 1 ] );
|
||||
Add( quasigroup_list, IntoLoop( group_product ) );
|
||||
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 );
|
||||
if n=1 then
|
||||
return quasigroup_list[ 1 ];
|
||||
fi;
|
||||
# at least 2 quasigroups and loops; we will not use recursion
|
||||
# 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;
|
||||
# We willl not use recursion; start by making all Cayley tables canonical
|
||||
Apply(quasigroup_list,
|
||||
Q -> CanonicalCayleyTableOfLeftQuasigroupTable( CayleyTable( Q ) ) );
|
||||
T := ProductTableOfCanonicalCayleyTables( quasigroup_list );
|
||||
|
||||
if are_all_loops then
|
||||
return LoopByCayleyTable( quasigroup_list[1] );
|
||||
return LoopByCayleyTable( T );
|
||||
fi;
|
||||
return QuasigroupByCayleyTable( quasigroup_list[1] );
|
||||
return QuasigroupByCayleyTable( T );
|
||||
end );
|
||||
|
||||
#############################################################################
|
||||
|
Loading…
Reference in New Issue
Block a user