Merge branch 'Loops3.4.0'
Incorporate the changes from 3.3.0 to 3.4.0 of LOOPS into this development. These were mostly straightforward. The only conflicts were in quasigroups.gd, in which all of the changes from this development were selected, as "IsLatin" had already been removed.
This commit is contained in:
commit
91ba2744c1
63 changed files with 20298 additions and 29245 deletions
|
@ -2,7 +2,7 @@
|
|||
##
|
||||
#A banner.g loops G. P. Nagy / P. Vojtechovsky
|
||||
##
|
||||
#H @(#)$Id: banner.g, v 3.3.0 2016/09/21 gap Exp $
|
||||
#H @(#)$Id: banner.g, v 3.4.0 2017/10/27 gap Exp $
|
||||
##
|
||||
#Y Copyright (C) 2004, G. P. Nagy (University of Szeged, Hungary),
|
||||
#Y P. Vojtechovsky (University of Denver, USA)
|
||||
|
@ -12,7 +12,7 @@ if not QUIET and BANNER then
|
|||
Print(
|
||||
" ______________________________________________________\n",
|
||||
" LOOPS: Computing with quasigroups and loops in GAP \n",
|
||||
" version 3.3.0 \n",
|
||||
" version 3.4.0 \n",
|
||||
" Gabor P. Nagy & Petr Vojtechovsky \n",
|
||||
" nagyg@math.u-szeged.hu petr@math.du.edu \n",
|
||||
" ------------------------------------------------------\n",
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
##
|
||||
#W classes.gi Testing properties/varieties [loops]
|
||||
##
|
||||
#H @(#)$Id: classes.gi, v 3.3.0 2016/10/26 gap Exp $
|
||||
#H @(#)$Id: classes.gi, v 3.4.0 2017/10/26 gap Exp $
|
||||
##
|
||||
#Y Copyright (C) 2004, G. P. Nagy (University of Szeged, Hungary),
|
||||
#Y P. Vojtechovsky (University of Denver, USA)
|
||||
|
@ -887,16 +887,14 @@ end);
|
|||
InstallMethod( IsALoop, "for loop",
|
||||
[ IsLoop ],
|
||||
function( Q )
|
||||
return IsLeftALoop(Q) and IsRightALoop(Q) and IsMiddleALoop(Q);
|
||||
return IsRightALoop(Q) and IsMiddleALoop(Q);
|
||||
# Theorem: rigth A-loop + middle A-loop implies left A-loop
|
||||
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 );
|
||||
|
@ -909,8 +907,12 @@ InstallTrueMethod( IsMoufangLoop, IsALoop and HasRightInverseProperty );
|
|||
InstallTrueMethod( IsMoufangLoop, IsALoop and HasWeakInverseProperty );
|
||||
|
||||
# is implied by
|
||||
InstallTrueMethod( IsMiddleALoop, IsCommutative );
|
||||
InstallTrueMethod( IsLeftALoop, IsLeftBruckLoop );
|
||||
InstallTrueMethod( IsLeftALoop, IsLCCLoop );
|
||||
InstallTrueMethod( IsRightALoop, IsRightBruckLoop );
|
||||
InstallTrueMethod( IsRightALoop, IsRCCLoop );
|
||||
InstallTrueMethod( IsALoop, IsCommutative and IsMoufangLoop );
|
||||
InstallTrueMethod( IsALoop, IsLeftALoop and IsMiddleALoop );
|
||||
InstallTrueMethod( IsALoop, IsRightALoop and IsMiddleALoop );
|
||||
InstallTrueMethod( IsALoop, IsAssociative );
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
##
|
||||
#W examples.gd Examples [loops]
|
||||
##
|
||||
#H @(#)$Id: examples.gd, v 3.1.0 2015/09/23 gap Exp $
|
||||
#H @(#)$Id: examples.gd, v 3.4.0 2015/09/23 gap Exp $
|
||||
##
|
||||
#Y Copyright (C) 2004, G. P. Nagy (University of Szeged, Hungary),
|
||||
#Y P. Vojtechovsky (University of Denver, USA)
|
||||
|
@ -36,6 +36,8 @@ DeclareGlobalFunction( "SmallLoop" );
|
|||
DeclareGlobalFunction( "InterestingLoop" );
|
||||
DeclareGlobalFunction( "NilpotentLoop" );
|
||||
DeclareGlobalFunction( "AutomorphicLoop" );
|
||||
DeclareGlobalFunction( "LeftBruckLoop" );
|
||||
DeclareGlobalFunction( "RightBruckLoop" );
|
||||
|
||||
# up to isotopism
|
||||
|
||||
|
@ -52,3 +54,4 @@ DeclareGlobalFunction( "LOOPS_ActivateRCCLoop" );
|
|||
DeclareGlobalFunction( "LOOPS_ActivateCCLoop" );
|
||||
DeclareGlobalFunction( "LOOPS_ActivateNilpotentLoop" );
|
||||
DeclareGlobalFunction( "LOOPS_ActivateAutomorphicLoop" );
|
||||
DeclareGlobalFunction( "LOOPS_ActivateRightBruckLoop" );
|
||||
|
|
213
gap/examples.gi
213
gap/examples.gi
|
@ -2,7 +2,7 @@
|
|||
##
|
||||
#W examples.gi Examples [loops]
|
||||
##
|
||||
#H @(#)$Id: examples.gi, v 3.3.0 2016/10/19 gap Exp $
|
||||
#H @(#)$Id: examples.gi, v 3.4.0 2017/10/23 gap Exp $
|
||||
##
|
||||
#Y Copyright (C) 2004, G. P. Nagy (University of Szeged, Hungary),
|
||||
#Y P. Vojtechovsky (University of Denver, USA)
|
||||
|
@ -32,6 +32,7 @@ ReadPackage("loops", "data/small.tbl"); # small loops
|
|||
ReadPackage("loops", "data/interesting.tbl"); # interesting loops
|
||||
ReadPackage("loops", "data/nilpotent.tbl"); # nilpotent loops
|
||||
ReadPackage("loops", "data/automorphic.tbl"); # automorphic loops
|
||||
ReadPackage("loops", "data/rightbruck.tbl"); # right Bruck loops
|
||||
|
||||
# up to isotopism
|
||||
ReadPackage("loops", "data/itp_small.tbl"); # small loops up to isotopism
|
||||
|
@ -60,6 +61,7 @@ function( name )
|
|||
elif name = "interesting" then return LOOPS_interesting_data;
|
||||
elif name = "nilpotent" then return LOOPS_nilpotent_data;
|
||||
elif name = "automorphic" then return LOOPS_automorphic_data;
|
||||
elif name = "right Bruck" then return LOOPS_right_bruck_data;
|
||||
#up to isotopism
|
||||
elif name = "itp small" then return LOOPS_itp_small_data;
|
||||
fi;
|
||||
|
@ -74,11 +76,8 @@ end);
|
|||
InstallGlobalFunction( DisplayLibraryInfo, function( name )
|
||||
local s, lib, k;
|
||||
# up to isomorphism
|
||||
if name = "left Bol" then
|
||||
s := "The library contains all nonassociative left Bol loops of order less than 17\nand all nonassociative left Bol loops of order p*q, where p>q>2 are primes.";
|
||||
elif name = "right Bol" then
|
||||
s := "The library contains all nonassociative right Bol loops of order less than 17\nand all nonassociative left Bol loops of order p*q, where p>q>2 are primes.";
|
||||
name := "left Bol"; # using dual data
|
||||
if name = "left Bol" or name = "right Bol" then
|
||||
s := Concatenation( "The library contains all nonassociative ", name, " loops of order less than 17\nand all nonassociative ", name, " loops of order p*q, where p>q>2 are primes." );
|
||||
elif name = "Moufang" then
|
||||
s := "The library contains all nonassociative Moufang loops \nof order less than 65, and all nonassociative Moufang \nloops of order 81 and 243.";
|
||||
elif name = "Paige" then
|
||||
|
@ -88,12 +87,9 @@ InstallGlobalFunction( DisplayLibraryInfo, function( name )
|
|||
elif name = "Steiner" then
|
||||
s := "The library contains all nonassociative Steiner loops \nof order less or equal to 16. It also contains the \nassociative Steiner loops of order 4 and 8.";
|
||||
elif name = "CC" then
|
||||
s := "The library contains all nonassociative CC loops of order less than 28 \nand all nonassociative CC loops of order p^2 and 2*p for any odd prime p.";
|
||||
elif name = "RCC" then
|
||||
s := "The library contains all nonassociative RCC loops of order less than 28.";
|
||||
elif name = "LCC" then
|
||||
s := "The library contains all nonassociative LCC loops of order less than 28.";
|
||||
name := "RCC"; # using dual data
|
||||
s := "The library contains all CC loops of order\n2<=2^k<=64, 3<=3^k<=81, 5<=5^k<=125, 7<=7^k<=343,\nall nonassociative CC loops of order less than 28,\nand all nonassociative CC loops of order p^2 and 2*p for any odd prime p.";
|
||||
elif name = "RCC" or name = "LCC" then
|
||||
s := Concatenation( "The library contains all nonassociative ", name, " loops of order less than 28." );
|
||||
elif name = "small" then
|
||||
s := "The library contains all nonassociative loops of order less than 7.";
|
||||
elif name = "interesting" then
|
||||
|
@ -103,23 +99,27 @@ InstallGlobalFunction( DisplayLibraryInfo, function( name )
|
|||
elif name = "automorphic" then
|
||||
s := "The library contains:\n";
|
||||
s := Concatenation(s," - all nonassociative automorphic loops of order less than 16,\n");
|
||||
s := Concatenation(s," - all commutative automorphic loops of order 3, 9, 27, 81,\n");
|
||||
s := Concatenation(s," - all commutative automorphic loops of order 243 that are central\n");
|
||||
s := Concatenation(s," extensions of Z_3 by F, where F is not the elem. ab. 3-group.\n");
|
||||
s := Concatenation(s,"Note: Abelian groups are included among the commutative loops.");
|
||||
s := Concatenation(s," - all commutative automorphic loops of order 3, 9, 27, 81.");
|
||||
elif name = "left Bruck" or name = "right Bruck" then
|
||||
s := Concatenation( "The library contains all ", name, " loops of orders 3, 9, 27 and 81." );
|
||||
# up to isotopism
|
||||
elif name = "itp small" then
|
||||
s := "The library contains all nonassociative loops of order less than 7 up to isotopism.";
|
||||
else
|
||||
Info( InfoWarning, 1, Concatenation(
|
||||
"The admissible names for loop libraries are: \n",
|
||||
"[ \"left Bol\", \"right Bol\", \"Moufang\", \"Paige\", \"code\", \"Steiner\", \"CC\", \"RCC\", \"LCC\", \"small\", \"itp small\", \"interesting\", \"nilpotent\", \"automorphic\" ]."
|
||||
"\"automorphic\", \"CC\", \"code\", \"interesting\", \"itp small\", \"LCC\", \"left Bol\", \"left Bruck\", \"Moufang\", \"nilpotent\", \"Paige\", \"right Bol\", \"right Bruck\", \"RCC\", \"small\", \"Steiner\"."
|
||||
) );
|
||||
return fail;
|
||||
fi;
|
||||
|
||||
s := Concatenation( s, "\n------\nExtent of the library:" );
|
||||
|
||||
# renaming for data access
|
||||
if name = "right Bol" then name := "left Bol"; fi;
|
||||
if name = "LCC" then name := "RCC"; fi;
|
||||
if name = "left Bruck" then name := "right Bruck"; fi;
|
||||
|
||||
lib := LOOPS_LibraryByName( name );
|
||||
for k in [1..Length( lib[ 1 ] ) ] do
|
||||
if lib[ 2 ][ k ] = 1 then
|
||||
|
@ -128,12 +128,12 @@ InstallGlobalFunction( DisplayLibraryInfo, function( name )
|
|||
s := Concatenation( s, "\n ", String( lib[ 2 ][ k ] ), " loops of order ", String( lib[ 1 ][ k ] ) );
|
||||
fi;
|
||||
od;
|
||||
if name = "left Bol" or name = "right Bol" then
|
||||
if name = "left Bol" then
|
||||
s := Concatenation( s, "\n (p-q)/2 loops of order p*q for primes p>q>2 such that q divides p-1");
|
||||
s := Concatenation( s, "\n (p-q+2)/2 loops of order p*q for primes p>q>2 such that q divides p+1" );
|
||||
fi;
|
||||
if name = "CC" then
|
||||
s := Concatenation( s, "\n 3 loops of order p^2 for every odd prime p,\n 1 loop of order 2*p for every odd prime p" );
|
||||
s := Concatenation( s, "\n 3 loops of order p^2 for every prime p>7,\n 1 loop of order 2*p for every odd prime p" );
|
||||
fi;
|
||||
s := Concatenation( s, "\n" );
|
||||
Print( s );
|
||||
|
@ -436,7 +436,48 @@ end);
|
|||
|
||||
InstallGlobalFunction( LOOPS_ActivateCCLoop,
|
||||
function( n, pos_n, m, case )
|
||||
local T, x, y, k, a, b, p;
|
||||
local powers, p, i, k, F, basis, coords, coc, T, a, b, x, y;
|
||||
powers := [ ,[4,8,16,32,64],[9,27,81],,[25,125],,[49,343]];
|
||||
if n in Union( powers ) then # use cocycles
|
||||
# determine p and position of n in database
|
||||
p := Filtered([2,3,5,7], x -> n in powers[x])[1];
|
||||
pos_n := Position( powers[p], n );
|
||||
if not IsBound( LOOPS_cc_cocycles[p] ) then
|
||||
# data not read yet, activate once
|
||||
ReadPackage( "loops", Concatenation( "data/cc/cc_cocycles_", String(p), ".tbl" ) );
|
||||
# decode cocycles and separate coordinates from a long string
|
||||
for i in [1..Length(powers[p])] do
|
||||
LOOPS_cc_cocycles[ p ][ i ] := List( LOOPS_cc_cocycles[ p ][ i ],
|
||||
c -> LOOPS_DecodeCocycle( [ p^i, c[1], c[2] ], [0..p-1] )
|
||||
);
|
||||
LOOPS_cc_coordinates[ p ][ i ] := List( LOOPS_cc_coordinates[ p ][ i ],
|
||||
c -> SplitString( c, " " )
|
||||
);
|
||||
od;
|
||||
fi;
|
||||
# data is now read
|
||||
# determine position of loop in the database
|
||||
k := 1;
|
||||
while m > Length( LOOPS_cc_coordinates[ p ][ pos_n ][ k ] ) do
|
||||
m := m - Length( LOOPS_cc_coordinates[ p ][ pos_n ][ k ] );
|
||||
k := k + 1;
|
||||
od;
|
||||
# factor loop
|
||||
F := CCLoop( n/p, LOOPS_cc_used_factors[ p ][ pos_n ][ k ] );
|
||||
# basis
|
||||
basis := List( LOOPS_cc_bases[ p ][ pos_n ][ k ],
|
||||
i -> LOOPS_cc_cocycles[ p ][ pos_n ][ i ]
|
||||
);
|
||||
# coordinates
|
||||
coords := LOOPS_cc_coordinates[ p ][ pos_n ][ k ][ m ];
|
||||
coords := LOOPS_ConvertBase( coords, 91, p, Length( basis ) );
|
||||
coords := List( coords, LOOPS_CharToDigit );
|
||||
# cocycle
|
||||
coc := (coords*basis) mod p;
|
||||
coc := List( coc, i -> i+1 );
|
||||
# return extension of Z_p by F using cocycle and trivial action
|
||||
return LoopByExtension( CCLoop(p,1), F, List([1..n/p], i -> () ), coc );
|
||||
fi;
|
||||
|
||||
if case=false then # use library of RCC loops, must recalculate pos_n
|
||||
return LOOPS_ActivateRCCLoop( n, Position(LOOPS_rcc_data[ 1 ], n), LOOPS_cc_data[ 3 ][ pos_n ][ m ] );
|
||||
|
@ -543,39 +584,52 @@ end);
|
|||
|
||||
InstallGlobalFunction( LOOPS_ActivateAutomorphicLoop,
|
||||
function( n, m )
|
||||
local i, pos_n, factor_id, F, dim, coords, basis, coc;
|
||||
if IsEmpty( LOOPS_automorphic_cocycles ) then # only read on demand
|
||||
ReadPackage( "loops", "data/automorphic/automorphic_cocycles.tbl");
|
||||
# decode cocycles
|
||||
for i in [1..3] do
|
||||
LOOPS_automorphic_cocycles[ i ] := List( LOOPS_automorphic_cocycles[ i ],
|
||||
c -> LOOPS_DecodeCocycle( [ 3^(i+2), true, c ], [0,1,2] )
|
||||
);
|
||||
od;
|
||||
# separate coordinates (from a long string )
|
||||
for i in [1..3] do
|
||||
LOOPS_automorphic_coordinates[ i ] := SplitString( LOOPS_automorphic_coordinates[ i ], " " );
|
||||
od;
|
||||
fi;
|
||||
# returns the associated Gamma loop (which here always happens to be automorphic)
|
||||
# improve later
|
||||
local P, L, s, Ls, ct, i, j, pos, f;
|
||||
P := LeftBruckLoop( n, m );
|
||||
L := LeftMultiplicationGroup( P );;
|
||||
s := List(Elements(L), x -> x^2 );;
|
||||
Ls := List([1..n], i -> LeftTranslation( P, Elements(P)[i] ) );;
|
||||
ct := List([1..n],i->0*[1..n]);;
|
||||
for i in [1..n] do for j in [1..n] do
|
||||
pos := Position( s, Ls[i]*Ls[j]*Ls[i]^(-1)*Ls[j]^(-1) );
|
||||
f := Elements(L)[pos];
|
||||
ct[i][j] := 1^(f*Ls[j]*Ls[i]);
|
||||
od; od;
|
||||
return LoopByCayleyTable(ct);
|
||||
end);
|
||||
|
||||
#############################################################################
|
||||
##
|
||||
#F LOOPS_ActivateRightBruckLoop( n, m )
|
||||
##
|
||||
## Activates a right Bruck loop from the library.
|
||||
|
||||
InstallGlobalFunction( LOOPS_ActivateRightBruckLoop,
|
||||
function( n, m )
|
||||
local pos_n, factor_id, F, basis, coords, coc;
|
||||
# factor loop
|
||||
pos_n := Position( [27,81,243], n );
|
||||
factor_id := LOOPS_CharToDigit( LOOPS_automorphic_coordinates[ pos_n ][ m ][ 1 ] );
|
||||
F := AutomorphicLoop( n/3, factor_id );
|
||||
pos_n := Position( [27,81], n );
|
||||
factor_id := LOOPS_CharToDigit( LOOPS_right_bruck_coordinates[ pos_n ][ m ][ 1 ] );
|
||||
F := RightBruckLoop( n/3, factor_id );
|
||||
# basis (only decode cocycles at first usage)
|
||||
if IsString( LOOPS_right_bruck_cocycles[ pos_n ][ 1 ][ 3 ] ) then # not converted yet
|
||||
LOOPS_right_bruck_cocycles[ pos_n ] := List( LOOPS_right_bruck_cocycles[ pos_n ],
|
||||
coc -> LOOPS_DecodeCocycle( coc, [0,1,2] )
|
||||
);
|
||||
fi;
|
||||
basis := LOOPS_right_bruck_cocycles[ pos_n ];
|
||||
# coordinates determining the cocycle
|
||||
dim := Length( LOOPS_automorphic_bases[ pos_n ][ factor_id ] );
|
||||
coords := LOOPS_automorphic_coordinates[ pos_n ][ m ];
|
||||
coords := LOOPS_right_bruck_coordinates[ pos_n ][ m ];
|
||||
coords := coords{[2..Length(coords)]}; # remove the character that determines factor id
|
||||
coords := LOOPS_ConvertBase( coords, 91, 3, dim );
|
||||
coords := LOOPS_ConvertBase( coords, 91, 3, Length( basis ) );
|
||||
coords := List( coords, LOOPS_CharToDigit );
|
||||
# basis
|
||||
basis := List( LOOPS_automorphic_bases[ pos_n ][ factor_id ],
|
||||
i -> LOOPS_automorphic_cocycles[ pos_n ][ i ]
|
||||
);
|
||||
# calculate cocycle
|
||||
coc := (coords*basis) mod 3;
|
||||
coc := List( coc, i -> i+1 );
|
||||
coc := coc + 1;
|
||||
# return extension of Z_3 by F using cocycle and trivial action
|
||||
return LoopByExtension( AutomorphicLoop(3,1), F, List([1..n/3], i -> () ), coc );
|
||||
return LoopByExtension( RightBruckLoop(3,1), F, List([1..n/3], i -> () ), coc );
|
||||
end);
|
||||
|
||||
#############################################################################
|
||||
|
@ -593,13 +647,7 @@ InstallGlobalFunction( LibraryLoop, function( name, n, m )
|
|||
local lib, implemented_orders, NOL, loop, pos_n, p, q, divs, PG, m_inv, root, half, case, g, h;
|
||||
|
||||
# selecting data library
|
||||
if name = "right Bol" then # using dual data
|
||||
lib := LOOPS_LibraryByName( "left Bol" );
|
||||
elif name = "LCC" then # using dual data
|
||||
lib := LOOPS_LibraryByName( "RCC" );
|
||||
else
|
||||
lib := LOOPS_LibraryByName( name );
|
||||
fi;
|
||||
lib := LOOPS_LibraryByName( name );
|
||||
|
||||
# extent of the library
|
||||
implemented_orders := lib[ 1 ];
|
||||
|
@ -614,7 +662,7 @@ InstallGlobalFunction( LibraryLoop, function( name, n, m )
|
|||
# parameters for handling systematic cases, such as CCLoop( p^2, 1 )
|
||||
pos_n := fail;
|
||||
case := false;
|
||||
if name="left Bol" or name="right Bol" then
|
||||
if name="left Bol" then
|
||||
divs := DivisorsInt( n );
|
||||
if Length( divs ) = 4 and not IsInt( divs[3]/divs[2] ) then # case n = p*q
|
||||
q := divs[ 2 ];
|
||||
|
@ -633,13 +681,13 @@ InstallGlobalFunction( LibraryLoop, function( name, n, m )
|
|||
fi;
|
||||
if name="CC" then
|
||||
divs := DivisorsInt( n );
|
||||
if Length( divs ) = 3 then # case p^2
|
||||
if Length( divs ) = 3 and divs[ 2 ] > 7 then # case p^2, p>7
|
||||
p := divs[ 2 ];
|
||||
case := [p,"p^2"];
|
||||
if not m in [1..3] then
|
||||
Error("LOOPS: There are only 3 nonassociative CC-loops of order p^2 for an odd prime p.");
|
||||
fi;
|
||||
elif Length( divs ) = 4 and not IsInt( divs[3]/divs[2] ) then # p*q
|
||||
elif Length( divs ) = 4 and not IsInt( divs[3]/divs[2] ) and not n=21 then # p*q
|
||||
p := divs[ 3 ];
|
||||
case := [p,"2*p"];
|
||||
if not divs[2] = 2 then
|
||||
|
@ -670,9 +718,6 @@ InstallGlobalFunction( LibraryLoop, function( name, n, m )
|
|||
if name = "left Bol" then
|
||||
loop := LOOPS_ActivateLeftBolLoop( pos_n, m, case );
|
||||
SetIsLeftBolLoop( loop, true );
|
||||
elif name = "right Bol" then
|
||||
loop := OppositeLoop( LOOPS_ActivateLeftBolLoop( pos_n, m, case ) );
|
||||
SetIsRightBolLoop( loop, true );
|
||||
elif name = "Moufang" then
|
||||
# renaming loops so that they agree with Goodaire's classification
|
||||
PG := List([1..243], i->());
|
||||
|
@ -701,14 +746,15 @@ InstallGlobalFunction( LibraryLoop, function( name, n, m )
|
|||
loop := LOOPS_ActivateSteinerLoop( n, pos_n, m );
|
||||
SetIsSteinerLoop( loop, true );
|
||||
elif name = "CC" then
|
||||
loop := LOOPS_ActivateCCLoop( n, pos_n, m, case );
|
||||
if n in [2,3,5,7] then # use Cayley table for canonical cyclic group
|
||||
loop := LoopByCayleyTable( LOOPS_DecodeCayleyTable( lib[ 3 ][ pos_n ][ m ] ) );
|
||||
else
|
||||
loop := LOOPS_ActivateCCLoop( n, pos_n, m, case );
|
||||
fi;
|
||||
SetIsCCLoop( loop, true );
|
||||
elif name = "RCC" then
|
||||
loop := LOOPS_ActivateRCCLoop( n, pos_n, m );
|
||||
SetIsRCCLoop( loop, true );
|
||||
elif name = "LCC" then
|
||||
loop := OppositeLoop( LOOPS_ActivateRCCLoop( n, pos_n, m ) );
|
||||
SetIsLCCLoop( loop, true );
|
||||
elif name = "small" then
|
||||
loop := LoopByCayleyTable( LOOPS_DecodeCayleyTable( lib[ 3 ][ pos_n ][ m ] ) );
|
||||
elif name = "interesting" then
|
||||
|
@ -725,12 +771,19 @@ InstallGlobalFunction( LibraryLoop, function( name, n, m )
|
|||
elif name = "nilpotent" then
|
||||
loop := LOOPS_ActivateNilpotentLoop( lib[ 3 ][ pos_n ][ m ] );
|
||||
elif name = "automorphic" then
|
||||
if not n in [27,81,243] then # use Cayley table
|
||||
if not n in [3, 9, 27, 81] then # use Cayley table
|
||||
loop := LoopByCayleyTable( LOOPS_DecodeCayleyTable( lib[ 3 ][ pos_n ][ m ] ) );
|
||||
else # use cocycles
|
||||
loop := LOOPS_ActivateAutomorphicLoop( n, m );
|
||||
else # use associated left Bruck loop
|
||||
loop := LOOPS_ActivateAutomorphicLoop( n, m );
|
||||
fi;
|
||||
SetIsAutomorphicLoop( loop, true );
|
||||
elif name = "right Bruck" then
|
||||
if not n in [27,81] then # use Cayley table
|
||||
loop := LoopByCayleyTable( LOOPS_DecodeCayleyTable( lib[ 3 ][ pos_n ][ m ] ) );
|
||||
else # use cocycles
|
||||
loop := LOOPS_ActivateRightBruckLoop( n, m );
|
||||
fi;
|
||||
SetIsRightBruckLoop( loop, true );
|
||||
# up to isotopism
|
||||
elif name = "itp small" then
|
||||
return LibraryLoop( "small", n, lib[ 3 ][ pos_n ][ m ] );
|
||||
|
@ -762,6 +815,8 @@ end);
|
|||
#F InterestingLoop( n, m )
|
||||
#F NilpotentLoop( n, m )
|
||||
#F AutomorphicLoop( n, m )
|
||||
#F LeftBruckLoop( n, m )
|
||||
#F RightBruckLoop( n, m )
|
||||
#F ItpSmallLoop( n, m )
|
||||
##
|
||||
|
||||
|
@ -770,7 +825,11 @@ InstallGlobalFunction( LeftBolLoop, function( n, m )
|
|||
end);
|
||||
|
||||
InstallGlobalFunction( RightBolLoop, function( n, m )
|
||||
return LibraryLoop( "right Bol", n, m );
|
||||
local loop;
|
||||
loop := Opposite( LeftBolLoop( n, m ) );
|
||||
SetIsRightBolLoop( loop, true );
|
||||
SetName( loop, Concatenation( "<right Bol loop ", String( n ), "/", String( m ), ">" ) );
|
||||
return loop;
|
||||
end);
|
||||
|
||||
InstallGlobalFunction( MoufangLoop, function( n, m )
|
||||
|
@ -808,11 +867,15 @@ InstallGlobalFunction( RightConjugacyClosedLoop, function( n, m )
|
|||
end);
|
||||
|
||||
InstallGlobalFunction( LCCLoop, function( n, m )
|
||||
return LibraryLoop( "LCC", n, m );
|
||||
local loop;
|
||||
loop := Opposite( RCCLoop( n, m ) );
|
||||
SetIsLCCLoop( loop, true );
|
||||
SetName( loop, Concatenation( "<LCC loop ", String( n ), "/", String( m ), ">" ) );
|
||||
return loop;
|
||||
end);
|
||||
|
||||
InstallGlobalFunction( LeftConjugacyClosedLoop, function( n, m )
|
||||
return LibraryLoop( "LCC", n, m );
|
||||
return LCCLoop( n, m );
|
||||
end);
|
||||
|
||||
InstallGlobalFunction( SmallLoop, function( n, m )
|
||||
|
@ -831,6 +894,18 @@ InstallGlobalFunction( AutomorphicLoop, function( n, m )
|
|||
return LibraryLoop( "automorphic", n, m );
|
||||
end);
|
||||
|
||||
InstallGlobalFunction( RightBruckLoop, function( n, m )
|
||||
return LibraryLoop( "right Bruck", n, m );
|
||||
end);
|
||||
|
||||
InstallGlobalFunction( LeftBruckLoop, function( n, m )
|
||||
local loop;
|
||||
loop := Opposite( RightBruckLoop( n, m ) );
|
||||
SetIsLeftBruckLoop( loop, true );
|
||||
SetName( loop, Concatenation( "<left Bruck loop ", String( n ), "/", String( m ), ">" ) );
|
||||
return loop;
|
||||
end);
|
||||
|
||||
InstallGlobalFunction( ItpSmallLoop, function( n, m )
|
||||
return LibraryLoop( "itp small", n, m );
|
||||
end);
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
##
|
||||
#W iso.gd Isomorphisms and isotopisms [loops]
|
||||
##
|
||||
#H @(#)$Id: iso.gd, v 3.2.0 2015/06/12 gap Exp $
|
||||
#H @(#)$Id: iso.gd, v 3.4.0 2016/12/13 gap Exp $
|
||||
##
|
||||
#Y Copyright (C) 2004, G. P. Nagy (University of Szeged, Hungary),
|
||||
#Y P. Vojtechovsky (University of Denver, USA)
|
||||
|
@ -23,6 +23,8 @@ DeclareOperation( "IsomorphismQuasigroups", [ IsQuasigroup, IsQuasigroup ] );
|
|||
DeclareOperation( "IsomorphismLoops", [ IsLoop, IsLoop ] );
|
||||
DeclareOperation( "QuasigroupsUpToIsomorphism", [ IsList ] );
|
||||
DeclareOperation( "LoopsUpToIsomorphism", [ IsList ] );
|
||||
DeclareOperation( "QuasigroupIsomorph", [ IsQuasigroup, IsPerm ] );
|
||||
DeclareOperation( "LoopIsomorph", [ IsLoop, IsPerm ] );
|
||||
DeclareOperation( "IsomorphicCopyByPerm", [ IsQuasigroup, IsPerm ] );
|
||||
DeclareOperation( "IsomorphicCopyByNormalSubloop", [ IsLoop, IsLoop ] );
|
||||
|
||||
|
|
65
gap/iso.gi
65
gap/iso.gi
|
@ -2,7 +2,7 @@
|
|||
##
|
||||
#W iso.gi Isomorphisms and isotopisms [loops]
|
||||
##
|
||||
#H @(#)$Id: iso.gi, v 3.3.0 2016/10/26 gap Exp $
|
||||
#H @(#)$Id: iso.gi, v 3.4.0 2017/08/24 gap Exp $
|
||||
##
|
||||
#Y Copyright (C) 2004, G. P. Nagy (University of Szeged, Hungary),
|
||||
#Y P. Vojtechovsky (University of Denver, USA)
|
||||
|
@ -466,30 +466,54 @@ end);
|
|||
|
||||
#############################################################################
|
||||
##
|
||||
#O IsomorphicCopyByPerm( Q, p )
|
||||
#O QuasigroupIsomorph( Q, p )
|
||||
##
|
||||
## If <Q> is a quasigroup of order n and <p> a permutation of [1..n], returns
|
||||
## the quasigroup (Q,*) such that p(xy) = p(x)*p(y).
|
||||
## If <Q> is a loop, p is first composed with (1,1^p) to make sure
|
||||
## that the neutral element of (Q,*) remains 1.
|
||||
|
||||
InstallMethod( IsomorphicCopyByPerm, "for a quasigroup and permutation",
|
||||
InstallMethod( QuasigroupIsomorph, "for a quasigroup and permutation",
|
||||
[ IsQuasigroup, IsPerm ],
|
||||
function( Q, p )
|
||||
local ctQ, ct, inv_p;
|
||||
ctQ := CanonicalCayleyTable( CayleyTable( Q ) );
|
||||
# if Q is a loop and 1^p > 1, must normalize
|
||||
if (IsLoop( Q ) and (not 1^p = 1)) then
|
||||
p := p * (1, 1^p );
|
||||
fi;
|
||||
inv_p := Inverse( p );
|
||||
ct := List([1..Size(Q)], i-> List([1..Size(Q)], j ->
|
||||
( ctQ[ i^inv_p ][ j^inv_p ] )^p
|
||||
) );
|
||||
if IsLoop( Q ) then return LoopByCayleyTable( ct ); fi;
|
||||
return QuasigroupByCayleyTable( ct );
|
||||
end);
|
||||
|
||||
#############################################################################
|
||||
##
|
||||
#O LoopIsomorph( Q, p )
|
||||
##
|
||||
## If <Q> is a loop of order n and <p> a permutation of [1..n] such that
|
||||
## p(1)=1, returns the loop (Q,*) such that p(xy)=p(x)*p(y).
|
||||
## If p(1)=c<>1, then the quasigroup (Q,*) is converted into loop
|
||||
## via the isomorphism (1,c).
|
||||
|
||||
InstallMethod( LoopIsomorph, "for a loop and permutation",
|
||||
[ IsLoop, IsPerm ],
|
||||
function( Q, p )
|
||||
return IntoLoop( QuasigroupIsomorph( Q, p ) );
|
||||
end);
|
||||
|
||||
#############################################################################
|
||||
##
|
||||
#O IsomorphicCopyByPerm( Q, p )
|
||||
##
|
||||
## Calls LoopIsomorph( Q, p ) if <Q> is a loop,
|
||||
## else QuasigroupIsotope( Q, p ).
|
||||
|
||||
InstallMethod( IsomorphicCopyByPerm, "for a quasigroup and permutation",
|
||||
[ IsQuasigroup, IsPerm ],
|
||||
function( Q, p )
|
||||
if IsLoop( Q ) then
|
||||
return LoopIsomorph( Q, p );
|
||||
fi;
|
||||
return QuasigroupIsomorph( Q, p );
|
||||
end);
|
||||
|
||||
#############################################################################
|
||||
##
|
||||
#O IsomorphicCopyByNormalSubloop( L, S )
|
||||
|
@ -594,15 +618,13 @@ end);
|
|||
##
|
||||
## If L1, L2 are isotopic loops, returns true, else fail.
|
||||
|
||||
# (MATH) First we calculate all principal loop isotopes of L1 of the form
|
||||
# PrincipalLoopIsotope(L1, f, g), where f, g, are elements of L1.
|
||||
# Then we filter these up to isomorphism. If L2 is isotopic to L1, then
|
||||
# L2 is isomorphic to one of these principal isotopes.
|
||||
# (MATH) We check for isomorphism of L2 against all principal
|
||||
# isotopes of L1.
|
||||
|
||||
InstallMethod( IsotopismLoops, "for two loops",
|
||||
[ IsLoop, IsLoop ],
|
||||
function( L1, L2 )
|
||||
local istps, fg, f, g, L, phi, pos, alpha, beta, gamma, p;
|
||||
local f, g, L, phi, alpha, beta, gamma, p;
|
||||
|
||||
# make all loops canonical to be able to calculate isotopisms
|
||||
if not L1 = Parent( L1 ) then L1 := LoopByCayleyTable( CayleyTable( L1 ) ); fi;
|
||||
|
@ -619,20 +641,11 @@ function( L1, L2 )
|
|||
if not Size(InnerMappingGroup(L1)) = Size(InnerMappingGroup(L2)) then return fail; fi;
|
||||
|
||||
# now trying to construct an isotopism
|
||||
istps := [];
|
||||
fg := [];
|
||||
for f in L1 do for g in L1 do
|
||||
Add(istps, PrincipalLoopIsotope( L1, f, g ));
|
||||
Add(fg, [ f, g ] );
|
||||
od; od;
|
||||
for L in LoopsUpToIsomorphism( istps ) do
|
||||
L := PrincipalLoopIsotope( L1, f, g );
|
||||
phi := IsomorphismLoops( L, L2 );
|
||||
if not phi = fail then
|
||||
# must reconstruct the isotopism (alpha, beta, gamma)
|
||||
# first figure out what f and g were
|
||||
pos := Position( istps, L );
|
||||
f := fg[ pos ][ 1 ];
|
||||
g := fg[ pos ][ 2 ];
|
||||
alpha := RightTranslation( L1, g );
|
||||
beta := LeftTranslation( L1, f );
|
||||
# we also applied an isomorphism (1,f*g) inside PrincipalLoopIsotope
|
||||
|
@ -649,7 +662,7 @@ function( L1, L2 )
|
|||
gamma := gamma * phi;
|
||||
return [ alpha, beta, gamma ];
|
||||
fi;
|
||||
od;
|
||||
od; od;
|
||||
return fail;
|
||||
end);
|
||||
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
##
|
||||
#W memory.gi Memory management [loops]
|
||||
##
|
||||
#H @(#)$Id: memory.gi, v 3.3.0 2016/10/20 gap Exp $
|
||||
#H @(#)$Id: memory.gi, v 3.4.0 2016/11/4 gap Exp $
|
||||
##
|
||||
#Y Copyright (C) 2004, G. P. Nagy (University of Szeged, Hungary),
|
||||
#Y P. Vojtechovsky (University of Denver, USA)
|
||||
|
@ -21,9 +21,14 @@ InstallGlobalFunction( LOOPS_FreeMemory, function( )
|
|||
LOOPS_rcc_transitive_groups := [];
|
||||
LOOPS_rcc_sections := List( [1..Length(LOOPS_rcc_data[1])], i-> [] );
|
||||
LOOPS_rcc_conjugacy_classes := [ [], [] ];
|
||||
# automorphic loops
|
||||
LOOPS_automorphic_cocycles := [];
|
||||
LOOPS_automorphic_coordinates := [];
|
||||
# cc loops
|
||||
LOOPS_cc_used_factors := [];
|
||||
LOOPS_cc_cocycles := [];
|
||||
LOOPS_cc_bases := [];
|
||||
LOOPS_cc_coordinates := [];
|
||||
# right Bruck loops
|
||||
LOOPS_right_bruck_cocycles := [];
|
||||
LOOPS_right_bruck_coordinates := [];
|
||||
GASMAN("collect");
|
||||
return GasmanStatistics().full.deadkb;
|
||||
end);
|
||||
|
|
|
@ -1,151 +1,146 @@
|
|||
#############################################################################
|
||||
##
|
||||
#W quasigroups.gd Representing, creating and displaying quasigroups [loops]
|
||||
##
|
||||
#H @(#)$Id: quasigroups.gd, v 3.2.0 2016/05/02 gap Exp $
|
||||
##
|
||||
#Y Copyright (C) 2004, G. P. Nagy (University of Szeged, Hungary),
|
||||
#Y P. Vojtechovsky (University of Denver, USA)
|
||||
##
|
||||
|
||||
#############################################################################
|
||||
## GAP CATEGORIES AND REPRESENTATIONS
|
||||
## -------------------------------------------------------------------------
|
||||
|
||||
## Categories convenient for defining quasigroups
|
||||
|
||||
## element which is an admissible argument for the right argument of /
|
||||
DeclareCategory( "IsRightQuotientElement", IsExtLElement);
|
||||
DeclareCategoryCollections("IsRightQuotientElement");
|
||||
DeclareCategoryCollections("IsRightQuotientElementCollection");
|
||||
|
||||
## Every element with an inverse can form right quotients
|
||||
## (in fact, in some sense it might be enough to have just a left inverse,
|
||||
## but there doesn't seem to be any benefit to delving to that level of
|
||||
## detail at this point.)
|
||||
InstallTrueMethod(IsRightQuotientElement, IsMultiplicativeElementWithInverse);
|
||||
|
||||
## Now what we would like to do is re-declare
|
||||
## DeclareOperation( "/", [IsExtRElement, IsRightQuotientElement] );
|
||||
## but we can't since "/" is in the kernel, so we will have to content
|
||||
## ourselves with InstallOtherMethod() calls on /. (I am not actually sure what
|
||||
## the practical upshot of that is, i.e. if it has any shortcomings as compared
|
||||
## to if we could declare "/" more generally.)
|
||||
|
||||
## Element which is admissible for the left argument of LeftQuotient()
|
||||
DeclareCategory( "IsLeftQuotientElement", IsExtRElement);
|
||||
DeclareCategoryCollections("IsLeftQuotientElement");
|
||||
DeclareCategoryCollections("IsLeftQuotientElementCollection");
|
||||
|
||||
## Every element with an inverse can form left quotients
|
||||
InstallTrueMethod(IsLeftQuotientElement, IsMultiplicativeElementWithInverse);
|
||||
|
||||
## Again, ideally (in some sense) we'd like to redeclare
|
||||
## DeclareOperation("LeftQuotient", [IsLeftQuotientElement,IsExtLElement]);
|
||||
|
||||
## element of a quasigroup
|
||||
DeclareSynonym( "IsQuasigroupElement",
|
||||
IsMultiplicativeElement and
|
||||
IsLeftQuotientElement and IsRightQuotientElement );
|
||||
DeclareRepresentation( "IsQuasigroupElmRep",
|
||||
IsPositionalObjectRep and IsMultiplicativeElement, [1] );
|
||||
|
||||
## element of a loop
|
||||
DeclareSynonym( "IsLoopElement",
|
||||
IsQuasigroupElement and IsMultiplicativeElementWithInverse );
|
||||
DeclareRepresentation( "IsLoopElmRep",
|
||||
IsPositionalObjectRep and IsMultiplicativeElementWithInverse, [1] );
|
||||
|
||||
## Right quasigroup
|
||||
DeclareCategory("IsRightQuasigroup",
|
||||
IsMagma and IsRightQuotientElementCollection);
|
||||
|
||||
## Left quasigroup
|
||||
DeclareCategory("IsLeftQuasigroup",
|
||||
IsMagma and IsLeftQuotientElementCollection);
|
||||
|
||||
## quasigroup
|
||||
DeclareSynonym( "IsQuasigroup", IsRightQuasigroup and IsLeftQuasigroup );
|
||||
|
||||
## loop
|
||||
DeclareSynonym( "IsLoop", IsQuasigroup and IsMagmaWithOne and
|
||||
IsMultiplicativeElementWithInverseCollection);
|
||||
|
||||
#############################################################################
|
||||
## TESTING MULTIPLICATION TABLES
|
||||
## -------------------------------------------------------------------------
|
||||
|
||||
DeclareProperty( "IsLeftQuasigroupTable", IsMatrix );
|
||||
DeclareProperty( "IsRightQuasigroupTable", IsMatrix );
|
||||
DeclareSynonym( "IsQuasigroupTable",
|
||||
IsLeftQuasigroupTable and IsRightQuasigroupTable );
|
||||
DeclareSynonym( "IsQuasigroupCayleyTable", IsQuasigroupTable );
|
||||
DeclareProperty( "IsLoopTable", IsMatrix );
|
||||
DeclareSynonym( "IsLoopCayleyTable", IsLoopTable );
|
||||
DeclareGlobalFunction("CanonicalCayleyTableOfLeftQuasigroupTable");
|
||||
DeclareOperation( "CanonicalCayleyTable", [ IsMatrix ] );
|
||||
DeclareOperation( "NormalizedQuasigroupTable", [ IsMatrix ] );
|
||||
|
||||
#############################################################################
|
||||
## CREATING QUASIGROUPS AND LOOPS MANUALLY
|
||||
## -------------------------------------------------------------------------
|
||||
|
||||
DeclareAttribute( "CayleyTable", IsMagma );
|
||||
DeclareOperation( "QuasigroupByCayleyTable", [ IsMatrix ] );
|
||||
DeclareOperation( "LoopByCayleyTable", [ IsMatrix ] );
|
||||
DeclareOperation( "SpecifyElmNamePrefix", [ IsCollection, IsString ] );
|
||||
DeclareSynonym( "SetQuasigroupElmName", SpecifyElmNamePrefix );
|
||||
DeclareSynonym( "SetLoopElmName", SpecifyElmNamePrefix );
|
||||
DeclareOperation( "BindElmNames", [ IsMagma ] );
|
||||
DeclareAttribute( "ConstructorFromTable", IsMagma );
|
||||
DeclareOperation( "CanonicalCopy", [ IsMagma ] );
|
||||
|
||||
#############################################################################
|
||||
## CREATING QUASIGROUPS AND LOOPS FROM A FILE
|
||||
## -------------------------------------------------------------------------
|
||||
|
||||
DeclareOperation( "QuasigroupFromFile", [ IsString, IsString ] );
|
||||
DeclareOperation( "LoopFromFile", [ IsString, IsString ] );
|
||||
|
||||
#############################################################################
|
||||
## CREATING QUASIGROUPS AND LOOPS BY SECTIONS
|
||||
## -------------------------------------------------------------------------
|
||||
|
||||
DeclareGlobalFunction("CayleyTableByPerms");
|
||||
DeclareOperation( "QuasigroupByLeftSection", [ IsPermCollection ] );
|
||||
DeclareOperation( "LoopByLeftSection", [ IsPermCollection ] );
|
||||
DeclareOperation( "QuasigroupByRightSection", [ IsPermCollection ] );
|
||||
DeclareOperation( "LoopByRightSection", [ IsPermCollection ] );
|
||||
DeclareOperation( "QuasigroupByRightFolder", [ IsGroup, IsGroup, IsMultiplicativeElementCollection ] );
|
||||
DeclareOperation( "LoopByRightFolder", [ IsGroup, IsGroup, IsMultiplicativeElementCollection ] );
|
||||
|
||||
#############################################################################
|
||||
## CONVERSIONS
|
||||
## -------------------------------------------------------------------------
|
||||
|
||||
DeclareOperation( "IntoQuasigroup", [ IsMagma ] );
|
||||
DeclareOperation( "PrincipalLoopIsotope",
|
||||
[ IsQuasigroup, IsQuasigroupElement, IsQuasigroupElement ] );
|
||||
DeclareOperation( "IntoLoop", [ IsMagma ] );
|
||||
DeclareOperation( "IntoGroup", [ IsMagma ] );
|
||||
|
||||
#############################################################################
|
||||
## PRODUCTS OF QUASIGROUPS AND LOOPS
|
||||
## --------------------------------------------------------------------------
|
||||
|
||||
DeclareGlobalFunction("ProductTableOfCanonicalCayleyTables");
|
||||
#DirectProduct already declared for groups.
|
||||
|
||||
#############################################################################
|
||||
## OPPOSITE QUASIGROUPS AND LOOPS
|
||||
## --------------------------------------------------------------------------
|
||||
|
||||
DeclareGlobalFunction( "OppositeQuasigroup");
|
||||
DeclareGlobalFunction( "OppositeLoop");
|
||||
DeclareAttribute( "Opposite", IsMagma );
|
||||
|
||||
#############################################################################
|
||||
## AUXILIARY
|
||||
## --------------------------------------------------------------------------
|
||||
DeclareGlobalFunction( "LOOPS_ReadCayleyTableFromFile" );
|
||||
DeclareGlobalFunction( "LOOPS_CayleyTableByRightFolder" );
|
||||
#############################################################################
|
||||
##
|
||||
#W quasigroups.gd Representing, creating and displaying quasigroups [loops]
|
||||
##
|
||||
#H @(#)$Id: quasigroups.gd, v 3.4.0 2017/10/17 gap Exp $
|
||||
##
|
||||
#Y Copyright (C) 2004, G. P. Nagy (University of Szeged, Hungary),
|
||||
#Y P. Vojtechovsky (University of Denver, USA)
|
||||
##
|
||||
|
||||
#############################################################################
|
||||
## GAP CATEGORIES AND REPRESENTATIONS
|
||||
## -------------------------------------------------------------------------
|
||||
|
||||
## Categories convenient for defining quasigroups
|
||||
|
||||
## element which is an admissible argument for the right argument of /
|
||||
DeclareCategory( "IsRightQuotientElement", IsExtLElement);
|
||||
DeclareCategoryCollections("IsRightQuotientElement");
|
||||
DeclareCategoryCollections("IsRightQuotientElementCollection");
|
||||
|
||||
## Every element with an inverse can form right quotients
|
||||
## (in fact, in some sense it might be enough to have just a left inverse,
|
||||
## but there doesn't seem to be any benefit to delving to that level of
|
||||
## detail at this point.)
|
||||
InstallTrueMethod(IsRightQuotientElement, IsMultiplicativeElementWithInverse);
|
||||
|
||||
## Now what we would like to do is re-declare
|
||||
## DeclareOperation( "/", [IsExtRElement, IsRightQuotientElement] );
|
||||
## but we can't since "/" is in the kernel, so we will have to content
|
||||
## ourselves with InstallOtherMethod() calls on /. (I am not actually sure what
|
||||
## the practical upshot of that is, i.e. if it has any shortcomings as compared
|
||||
## to if we could declare "/" more generally.)
|
||||
|
||||
## Element which is admissible for the left argument of LeftQuotient()
|
||||
DeclareCategory( "IsLeftQuotientElement", IsExtRElement);
|
||||
DeclareCategoryCollections("IsLeftQuotientElement");
|
||||
DeclareCategoryCollections("IsLeftQuotientElementCollection");
|
||||
|
||||
## Every element with an inverse can form left quotients
|
||||
InstallTrueMethod(IsLeftQuotientElement, IsMultiplicativeElementWithInverse);
|
||||
|
||||
## Again, ideally (in some sense) we'd like to redeclare
|
||||
## DeclareOperation("LeftQuotient", [IsLeftQuotientElement,IsExtLElement]);
|
||||
|
||||
## element of a quasigroup
|
||||
DeclareSynonym( "IsQuasigroupElement",
|
||||
IsMultiplicativeElement and
|
||||
IsLeftQuotientElement and IsRightQuotientElement );
|
||||
DeclareRepresentation( "IsQuasigroupElmRep",
|
||||
IsPositionalObjectRep and IsMultiplicativeElement, [1] );
|
||||
|
||||
## element of a loop
|
||||
DeclareSynonym( "IsLoopElement",
|
||||
IsQuasigroupElement and IsMultiplicativeElementWithInverse );
|
||||
DeclareRepresentation( "IsLoopElmRep",
|
||||
IsPositionalObjectRep and IsMultiplicativeElementWithInverse, [1] );
|
||||
|
||||
## latin (auxiliary category for GAP to tell apart IsMagma and IsQuasigroup)
|
||||
DeclareCategory( "IsLatinMagma", IsObject );
|
||||
|
||||
## quasigroup
|
||||
DeclareCategory( "IsQuasigroup", IsMagma and IsLatinMagma );
|
||||
|
||||
## loop
|
||||
DeclareSynonym( "IsLoop", IsQuasigroup and IsMagmaWithOne and
|
||||
IsMultiplicativeElementWithInverseCollection);
|
||||
|
||||
#############################################################################
|
||||
## TESTING MULTIPLICATION TABLES
|
||||
## -------------------------------------------------------------------------
|
||||
|
||||
DeclareProperty( "IsLeftQuasigroupTable", IsMatrix );
|
||||
DeclareProperty( "IsRightQuasigroupTable", IsMatrix );
|
||||
DeclareSynonym( "IsQuasigroupTable",
|
||||
IsLeftQuasigroupTable and IsRightQuasigroupTable );
|
||||
DeclareSynonym( "IsQuasigroupCayleyTable", IsQuasigroupTable );
|
||||
DeclareProperty( "IsLoopTable", IsMatrix );
|
||||
DeclareSynonym( "IsLoopCayleyTable", IsLoopTable );
|
||||
DeclareGlobalFunction("CanonicalCayleyTableOfLeftQuasigroupTable");
|
||||
DeclareOperation( "CanonicalCayleyTable", [ IsMatrix ] );
|
||||
DeclareOperation( "NormalizedQuasigroupTable", [ IsMatrix ] );
|
||||
|
||||
#############################################################################
|
||||
## CREATING QUASIGROUPS AND LOOPS MANUALLY
|
||||
## -------------------------------------------------------------------------
|
||||
|
||||
DeclareAttribute( "CayleyTable", IsMagma );
|
||||
DeclareOperation( "QuasigroupByCayleyTable", [ IsMatrix ] );
|
||||
DeclareOperation( "LoopByCayleyTable", [ IsMatrix ] );
|
||||
DeclareOperation( "SpecifyElmNamePrefix", [ IsCollection, IsString ] );
|
||||
DeclareSynonym( "SetQuasigroupElmName", SpecifyElmNamePrefix );
|
||||
DeclareSynonym( "SetLoopElmName", SpecifyElmNamePrefix );
|
||||
DeclareOperation( "BindElmNames", [ IsMagma ] );
|
||||
DeclareAttribute( "ConstructorFromTable", IsMagma );
|
||||
DeclareOperation( "CanonicalCopy", [ IsMagma ] );
|
||||
|
||||
#############################################################################
|
||||
## CREATING QUASIGROUPS AND LOOPS FROM A FILE
|
||||
## -------------------------------------------------------------------------
|
||||
|
||||
DeclareOperation( "QuasigroupFromFile", [ IsString, IsString ] );
|
||||
DeclareOperation( "LoopFromFile", [ IsString, IsString ] );
|
||||
|
||||
#############################################################################
|
||||
## CREATING QUASIGROUPS AND LOOPS BY SECTIONS
|
||||
## -------------------------------------------------------------------------
|
||||
|
||||
DeclareGlobalFunction("CayleyTableByPerms");
|
||||
DeclareOperation( "QuasigroupByLeftSection", [ IsPermCollection ] );
|
||||
DeclareOperation( "LoopByLeftSection", [ IsPermCollection ] );
|
||||
DeclareOperation( "QuasigroupByRightSection", [ IsPermCollection ] );
|
||||
DeclareOperation( "LoopByRightSection", [ IsPermCollection ] );
|
||||
DeclareOperation( "QuasigroupByRightFolder", [ IsGroup, IsGroup, IsMultiplicativeElementCollection ] );
|
||||
DeclareOperation( "LoopByRightFolder", [ IsGroup, IsGroup, IsMultiplicativeElementCollection ] );
|
||||
|
||||
#############################################################################
|
||||
## CONVERSIONS
|
||||
## -------------------------------------------------------------------------
|
||||
|
||||
DeclareOperation( "IntoQuasigroup", [ IsMagma ] );
|
||||
DeclareOperation( "PrincipalLoopIsotope",
|
||||
[ IsQuasigroup, IsQuasigroupElement, IsQuasigroupElement ] );
|
||||
DeclareOperation( "IntoLoop", [ IsMagma ] );
|
||||
DeclareOperation( "IntoGroup", [ IsMagma ] );
|
||||
|
||||
#############################################################################
|
||||
## PRODUCTS OF QUASIGROUPS AND LOOPS
|
||||
## --------------------------------------------------------------------------
|
||||
|
||||
DeclareGlobalFunction("ProductTableOfCanonicalCayleyTables");
|
||||
#DirectProduct already declared for groups.
|
||||
|
||||
#############################################################################
|
||||
## OPPOSITE QUASIGROUPS AND LOOPS
|
||||
## --------------------------------------------------------------------------
|
||||
|
||||
DeclareGlobalFunction( "OppositeQuasigroup");
|
||||
DeclareGlobalFunction( "OppositeLoop");
|
||||
DeclareAttribute( "Opposite", IsMagma );
|
||||
|
||||
#############################################################################
|
||||
## AUXILIARY
|
||||
## --------------------------------------------------------------------------
|
||||
DeclareGlobalFunction( "LOOPS_ReadCayleyTableFromFile" );
|
||||
DeclareGlobalFunction( "LOOPS_CayleyTableByRightFolder" );
|
||||
|
|
|
@ -893,32 +893,34 @@ end );
|
|||
InstallMethod( ViewObj, "for loop",
|
||||
[ IsLoop ],
|
||||
function( L )
|
||||
if HasIsAssociative( L ) and IsAssociative( L ) then
|
||||
Print( "<associative loop of order ", Size( L ), ">");
|
||||
elif HasIsExtraLoop( L ) and IsExtraLoop( L ) then
|
||||
Print( "<extra loop of order ", Size( L ), ">");
|
||||
elif HasIsMoufangLoop( L ) and IsMoufangLoop( L ) then
|
||||
Print( "<Moufang loop of order ", Size( L ), ">");
|
||||
elif HasIsCLoop( L ) and IsCLoop( L ) then
|
||||
Print( "<C loop of order ", Size( L ), ">");
|
||||
elif HasIsLeftBolLoop( L ) and IsLeftBolLoop( L ) then
|
||||
Print( "<left Bol loop of order ", Size( L ), ">");
|
||||
elif HasIsRightBolLoop( L ) and IsRightBolLoop( L ) then
|
||||
Print( "<right Bol loop of order ", Size( L ), ">");
|
||||
elif HasIsLCLoop( L ) and IsLCLoop( L ) then
|
||||
Print( "<LC loop of order ", Size( L ), ">");
|
||||
elif HasIsRCLoop( L ) and IsRCLoop( L ) then
|
||||
Print( "<RC loop of order ", Size( L ), ">");
|
||||
local PrintMe;
|
||||
|
||||
PrintMe := function( name, L )
|
||||
Print( "<", name, " loop of order ", Size( L ), ">");
|
||||
|
||||
end;
|
||||
if HasIsAssociative( L ) and IsAssociative( L ) then PrintMe( "associative", L );
|
||||
elif HasIsExtraLoop( L ) and IsExtraLoop( L ) then PrintMe( "extra", L );
|
||||
elif HasIsMoufangLoop( L ) and IsMoufangLoop( L ) then PrintMe( "Moufang", L );
|
||||
elif HasIsCLoop( L ) and IsCLoop( L ) then PrintMe( "C", L );
|
||||
elif HasIsLeftBruckLoop( L ) and IsLeftBruckLoop( L ) then PrintMe( "left Bruck", L );
|
||||
elif HasIsRightBruckLoop( L ) and IsRightBruckLoop( L ) then PrintMe( "right Bruck", L );
|
||||
elif HasIsLeftBolLoop( L ) and IsLeftBolLoop( L ) then PrintMe( "left Bol", L );
|
||||
elif HasIsRightBolLoop( L ) and IsRightBolLoop( L ) then PrintMe( "right Bol", L );
|
||||
elif HasIsAutomorphicLoop( L ) and IsAutomorphicLoop( L ) then PrintMe( "automorphic", L );
|
||||
elif HasIsLeftAutomorphicLoop( L ) and IsLeftAutomorphicLoop( L ) then PrintMe( "left automorphic", L );
|
||||
elif HasIsRightAutomorphicLoop( L ) and IsRightAutomorphicLoop( L ) then PrintMe( "right automorphic", L );
|
||||
elif HasIsLCLoop( L ) and IsLCLoop( L ) then PrintMe( "LC", L );
|
||||
elif HasIsRCLoop( L ) and IsRCLoop( L ) then PrintMe( "RC", L );
|
||||
elif HasIsLeftAlternative( L ) and IsLeftAlternative( L ) then
|
||||
if HasIsRightAlternative( L ) and IsRightAlternative( L ) then
|
||||
Print( "<alternative loop of order ", Size( L ), ">");
|
||||
else
|
||||
Print( "<left alternative loop of order ", Size( L ), ">");
|
||||
PrintMe("alternative", L );
|
||||
else
|
||||
PrintMe("left alternative", L );
|
||||
fi;
|
||||
elif HasIsRightAlternative( L ) and IsRightAlternative( L ) then
|
||||
Print( "<right alternative loop of order ", Size( L ), ">");
|
||||
elif HasIsFlexible( L ) and IsFlexible( L ) then
|
||||
Print( "<flexible loop of order ", Size( L ), ">");
|
||||
elif HasIsRightAlternative( L ) and IsRightAlternative( L ) then PrintMe( "right alternative", L );
|
||||
elif HasIsCommutative( L ) and IsCommutative( L ) then PrintMe( "commutative", L );
|
||||
elif HasIsFlexible( L ) and IsFlexible( L ) then PrintMe( "flexible", L);
|
||||
else
|
||||
# MORE ??
|
||||
Print( "<loop of order ", Size( L ), ">" );
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue