Add quandles and split out functions based on multiplication tables

This commit is contained in:
Glen Whitney 2017-10-20 11:08:09 +02:00
parent 27c5f78120
commit d304b53fde
5 changed files with 401 additions and 249 deletions

31
gap/bytable.gd Normal file
View File

@ -0,0 +1,31 @@
## bytable.gd RAQ Quasigroups, racks, and quandles by multiplication tables.
## Self-distributivity
# Predicates on tables:
DeclareProperty( "IsLeftSelfDistributiveTable", IsMatrix );
DeclareProperty( "IsRightSelfDistributiveTable", IsMatrix );
DeclareProperty( "IsElementwiseIdempotentTable", IsMatrix );
## Attributes (typically used on the families of elements created from a
## multiplication table) to store sections and division tables
DeclareAttribute("LeftPerms", HasMultiplicationTable);
DeclareAttribute("RightPerms", HasMultiplicationTable);
DeclareAttribute("LeftDivisionTable", HasMultiplicationTable);
DeclareAttribute("RightDivisionTable", HasMultiplicationTable);
## Create Quasigroups and racks from multiplication tables
DeclareGlobalFunction("LeftQuasigroupByMultiplicationTable");
DeclareGlobalFunction("LeftQuasigroupByMultiplicationTableNC");
DeclareGlobalFunction("LeftRackByMultiplicationTable");
DeclareGlobalFunction("LeftRackByMultiplicationTableNC");
DeclareGlobalFunction("LeftQuandleByMultiplicationTable");
DeclareGlobalFunction("LeftQuandleByMultiplicationTableNC");
DeclareGlobalFunction("RightQuasigroupByMultiplicationTable");
DeclareGlobalFunction("RightQuasigroupByMultiplicationTableNC");
DeclareGlobalFunction("RightRackByMultiplicationTable");
DeclareGlobalFunction("RightRackByMultiplicationTableNC");
DeclareGlobalFunction("RightQuandleByMultiplicationTable");
DeclareGlobalFunction("RightQuandleByMultiplicationTableNC");
## Property of a collection that its elements know their multiplication table
DeclareProperty("IsBuiltFromMultiplicationTable", IsCollection);

271
gap/bytable.gi Normal file
View File

@ -0,0 +1,271 @@
## bytable.gi RAQ Implementation of racks etc. by multiplication tables.
## Predicates to check tables for distributivity
InstallMethod(IsRightSelfDistributiveTable, "for matrix",
[ IsMatrix ],
T -> IsLeftSelfDistributiveTable(TransposedMat(T))
);
InstallMethod(IsLeftSelfDistributiveTable, "for matrix",
[ IsMatrix ],
function(T)
# Everybody else does it by checking all of the cases, so why not me, too?
# Is there a better way?
local n,i,j,k;
n := Length(T);
for i in [1..n] do for j in [1..n] do for k in [1..n] do
if T[i, T[j,k]] <> T[T[i,j], T[i,k]] then return false; fi;
od; od; od;
return true;
end);
InstallMethod(IsElementwiseIdempotentTable, "for matrix",
[ IsMatrix ],
T -> ForAll([1..Length(T)], i->(T[i,i]=i))
);
## And now create them from multiplication tables
InstallGlobalFunction(LeftQuasigroupByMultiplicationTable,
function(T)
if not IsLeftQuasigroupTable(T) then
Error("Multiplication table <T> must have each row a permutation of ",
"the same entries.");
fi;
return LeftQuasigroupByMultiplicationTableNC(
CanonicalCayleyTableOfLeftQuasigroupTable(T));
end);
InstallGlobalFunction(LeftQuasigroupByMultiplicationTableNC,
T -> MagmaByMultiplicationTableCreatorNC(T, LeftQuasigroup,
IsLeftQuotientElement and IsMagmaByMultiplicationTableObj)
);
InstallGlobalFunction(RightQuasigroupByMultiplicationTable,
function(T)
if not IsRightQuasigroupTable(T) then
Error("Multiplication table <T> must have each row a permutation of ",
"the same entries.");
fi;
return RightQuasigroupByMultiplicationTableNC(CanonicalCayleyTable(T));
end);
InstallGlobalFunction(RightQuasigroupByMultiplicationTableNC,
T -> MagmaByMultiplicationTableCreatorNC(T, RightQuasigroup,
IsRightQuotientElement and IsMagmaByMultiplicationTableObj)
);
InstallGlobalFunction(LeftRackByMultiplicationTable,
function(T)
if not IsLeftQuasigroupTable(T) then
Error("Multiplication table <T> must have each row a permutation of ",
"the same entries.");
fi;
T := CanonicalCayleyTableOfLeftQuasigroupTable(T);
if not IsLeftSelfDistributiveTable(T) then
Error("Multiplication table <T> must be left self distributive.");
fi;
return LeftRackByMultiplicationTableNC(T);
end);
InstallGlobalFunction(LeftRackByMultiplicationTableNC,
T -> MagmaByMultiplicationTableCreatorNC(T, LeftRack,
IsLeftQuotientElement and IsLSelfDistElement and
IsMagmaByMultiplicationTableObj
)
);
InstallGlobalFunction(LeftQuandleByMultiplicationTable,
function(T)
if not IsLeftQuasigroupTable(T) then
Error("Multiplication table <T> must have each row a permutation of ",
"the same entries.");
fi;
T := CanonicalCayleyTableOfLeftQuasigroupTable(T);
if not (IsLeftSelfDistributiveTable(T) and
IsElementwiseIdempotentTable(T)) then
Error("Multiplication table <T> must be left self-dist and idempotent.");
fi;
return LeftQuandleByMultiplicationTableNC(T);
end);
InstallGlobalFunction(LeftQuandleByMultiplicationTableNC,
T -> MagmaByMultiplicationTableCreatorNC(T, LeftQuandle,
IsLeftQuotientElement and IsLSelfDistElement and IsIdempotent and
IsMagmaByMultiplicationTableObj
)
);
InstallGlobalFunction(RightRackByMultiplicationTable,
function(T)
if not IsRightQuasigroupTable(T) then
Error("Multiplication table <T> must have each column a permutation of ",
"the same entries.");
fi;
T := CanonicalCayleyTable(T);
if not IsRightSelfDistributiveTable(T) then
Error("Multiplication table <T> must be right self distributive.");
fi;
return RightRackByMultiplicationTableNC(T);
end);
InstallGlobalFunction(RightRackByMultiplicationTableNC,
T -> MagmaByMultiplicationTableCreatorNC(T, RightRack,
IsRightQuotientElement and IsRSelfDistElement and
IsMagmaByMultiplicationTableObj
)
);
InstallGlobalFunction(RightQuandleByMultiplicationTable,
function(T)
if not IsRightQuasigroupTable(T) then
Error("Multiplication table <T> must have each column a permutation of ",
"the same entries.");
fi;
T := CanonicalCayleyTable(T);
if not (IsRightSelfDistributiveTable(T) and
IsElementwiseIdempotentTable(T)) then
Error("Multiplication table <T> must be right self-dist and idempotent.");
fi;
return RightQuandleByMultiplicationTableNC(T);
end);
InstallGlobalFunction(RightQuandleByMultiplicationTableNC,
T -> MagmaByMultiplicationTableCreatorNC(T, RightQuandle,
IsRightQuotientElement and IsRSelfDistElement and IsIdempotent and
IsMagmaByMultiplicationTableObj
)
);
## And define the operations
InstallOtherMethod(LeftQuotient,
"for two elts in magma by mult table, when left has left quotients",
IsIdenticalObj,
[IsLeftQuotientElement, IsMagmaByMultiplicationTableObj],
function (l,r)
local fam, ix;
fam := FamilyObj(l);
ix := LeftDivisionTable(fam)[l![1],r![1]];
return fam!.set[ix];
end);
InstallOtherMethod(\/,
"for two elts in magma by mult table, when right has right quotients",
IsIdenticalObj,
[IsMagmaByMultiplicationTableObj, IsRightQuotientElement],
function (l,r)
local fam, ix;
fam := FamilyObj(r);
ix := RightDivisionTable(fam)[l![1],r![1]];
return fam!.set[ix];
end);
## Create division tables as needed
InstallMethod(LeftDivisionTable,
"for an object with a multiplication table",
[HasMultiplicationTable],
function(fam)
local LS, n;
LS := LeftPerms(fam);
n := Size(LS);
return List(LS, x->ListPerm(Inverse(x), n));
end);
InstallMethod(RightDivisionTable,
"for an object with a multiplication table",
[HasMultiplicationTable],
function (obj)
local RS, n;
RS := RightPerms(obj);
n := Size(RS);
return TransposedMat(List(RS, x->ListPerm(Inverse(x), n)));
end);
## Create perm lists as needed
InstallMethod(LeftPerms,
"for an object with a multiplication table",
[HasMultiplicationTable],
function(fam)
return List(MultiplicationTable(fam), x->PermList(x));
end);
InstallMethod(RightPerms,
"for an object with a muliplication table",
[HasMultiplicationTable],
function(fam)
return List(TransposedMat(MultiplicationTable(fam)), x->PermList(x));
end);
## Distributivity/idempotence checkers for when need be
InstallMethod(IsLSelfDistributive, "for magma",
[IsMagma and IsFinite],
M -> IsLeftSelfDistributiveTable(MultiplicationTable(M))
);
InstallMethod(IsRSelfDistributive, "for magma",
[IsMagma and IsFinite],
M -> IsRightSelfDistributiveTable(MultiplicationTable(M))
);
InstallMethod(IsElementwiseIdempotent, "for magma",
[IsMagma and IsFinite],
M -> ForAll(Elements(M), m->IsIdempotent(m))
);
## Patch View/Print/Display for magma by mult objects
InstallMethod(String, "for an element of magma by multiplication table",
[IsMagmaByMultiplicationTableObj],
function(obj)
local fam;
fam := FamilyObj(obj);
if IsBound(fam!.elmNamePrefix) then
return Concatenation(fam!.elmNamePrefix, String(obj![1]));
fi;
return Concatenation("m", String(obj![1]));
end);
InstallMethod(ViewString, "for an element of magma by multiplication table",
[IsMagmaByMultiplicationTableObj],
obj -> String(obj));
InstallMethod(DisplayString, "for an element of magma by multiplication table",
[IsMagmaByMultiplicationTableObj],
obj -> String(obj));
InstallMethod(PrintObj, "for an element of magma by multiplication table",
[IsMagmaByMultiplicationTableObj],
function(obj) Print(String(obj)); end);
## Property of a collection that its elements know their multiplication table
InstallMethod(IsBuiltFromMultiplicationTable, "for a collection",
[IsCollection],
C -> HasMultiplicationTable(ElementsFamily(FamilyObj(C)))
);
## Special case the Opposite function from LOOPS package, since the opposite
## of a left quasigroup is a right quasigroup and vice versa
# Is there a way to do this just once for each direction?
InstallMethod(Opposite, "for left quasigroup",
[ IsLeftQuasigroup and IsBuiltFromMultiplicationTable],
L -> RightQuasigroupByMultiplicationTable(
TransposedMat(MultiplicationTable(L))
)
);
InstallMethod(Opposite, "for left rack",
[ IsLeftRack and IsBuiltFromMultiplicationTable],
L -> RightRackByMultiplicationTableNC(TransposedMat(MultiplicationTable(L)))
);
InstallMethod(Opposite, "for right quasigroup",
[ IsRightQuasigroup and IsBuiltFromMultiplicationTable],
L -> LeftQuasigroupByMultiplicationTable(
TransposedMat(MultiplicationTable(L))
)
);
InstallMethod(Opposite, "for right rack",
[ IsRightRack and IsBuiltFromMultiplicationTable],
L -> LeftRackByMultiplicationTableNC(TransposedMat(MultiplicationTable(L)))
);

View File

@ -1,14 +1,15 @@
## structure.gd RAQ Definitions, representations, and elementary operations.
## structure.gd RAQ Definitions, generation, and elementary ops and props.
## GAP Categories and representations
## Self-distributivity
# Note these are properties that should be defined just at the level of
# MultiplicativeElements and Magmas, hence although the LOOPS package defines
# IsLDistributive and IsRDistributive for quasigroups, they would be ambiguous
# in the case of something like a semiring whose multiplicative structure was
# a quasigroup (cf. https://arxiv.org/abs/0910.4760). Hence, we implement them
# in RAQ with new, non-conflicting terms.
# Note these are properties that can and therefore should be defined just at
# the level of MultiplicativeElements and Magmas, hence although the LOOPS
# package defines IsLDistributive and IsRDistributive for quasigroups, they
# would be ambiguous in the case of something like a semiring whose
# multiplicative structure was a quasigroup
# (cf. https://arxiv.org/abs/0910.4760). Hence, we implement them in RAQ with
# new, non-conflicting terms.
# An element that knows that multiplication in its family is left
# self-distributive:
@ -20,10 +21,6 @@ DeclareCategoryCollections("IsLSelfDistElement");
DeclareCategory("IsRSelfDistElement", IsMultiplicativeElement);
DeclareCategoryCollections("IsRSelfDistElement");
# Predicates on tables:
DeclareProperty( "IsLeftSelfDistributiveTable", IsMatrix );
DeclareProperty( "IsRightSelfDistributiveTable", IsMatrix );
# Left self-distributive magmas:
DeclareProperty("IsLSelfDistributive", IsMagma);
InstallTrueMethod(IsLSelfDistributive,
@ -34,11 +31,24 @@ DeclareProperty("IsRSelfDistributive", IsMagma);
InstallTrueMethod(IsRSelfDistributive,
IsMagma and IsRSelfDistElementCollection);
# Left and right racks
## Idempotence
# There is already a property IsIdempotent on elements, but to definw
# structures which will automatically be quandles we need a corresponding
# collections category:
DeclareCategoryCollections("IsIdempotent");
# Idempotent magmas, i.e. magmas in which every element is idempotent
DeclareProperty("IsElementwiseIdempotent", IsMagma);
InstallTrueMethod(IsElementwiseIdempotent, IsMagma and IsIdempotentCollection);
## Left and right racks and quandles
DeclareSynonym("IsLeftRack", IsLeftQuasigroup and IsLSelfDistributive);
DeclareSynonym("IsRightRack", IsRightQuasigroup and IsRSelfDistributive);
## One-sided quasigroups
DeclareSynonym("IsLeftQuandle", IsLeftRack and IsElementwiseIdempotent);
DeclareSynonym("IsRightQuandle", IsLeftRack and IsElementwiseIdempotent);
## One-sided quasigroups and racks and quandles by generators
# Returns the closure of <gens> under * and LeftQuotient;
# the family of elements of M may be specified, and must be if <gens>
@ -47,6 +57,8 @@ DeclareGlobalFunction("LeftQuasigroup");
DeclareGlobalFunction("RightQuasigroup");
DeclareGlobalFunction("LeftRack");
DeclareGlobalFunction("RightRack");
DeclareGlobalFunction("LeftQuandle");
DeclareGlobalFunction("RightQuandle");
# Underlying operation
DeclareGlobalFunction("CloneOfTypeByGenerators");
@ -72,20 +84,3 @@ InstallImmediateMethod(GeneratorsOfMagma,
2,
q -> GeneratorsOfRightQuasigroup(q)
);
## And now, build them from multiplication tables
# Need attributes on the families to store the sections and division tables
DeclareAttribute("LeftPerms", HasMultiplicationTable);
DeclareAttribute("RightPerms", HasMultiplicationTable);
DeclareAttribute("LeftDivisionTable", HasMultiplicationTable);
DeclareAttribute("RightDivisionTable", HasMultiplicationTable);
# And the builders
DeclareGlobalFunction("LeftQuasigroupByMultiplicationTable");
DeclareGlobalFunction("LeftQuasigroupByMultiplicationTableNC");
DeclareGlobalFunction("LeftRackByMultiplicationTable");
DeclareGlobalFunction("LeftRackByMultiplicationTableNC");
DeclareGlobalFunction("RightQuasigroupByMultiplicationTable");
DeclareGlobalFunction("RightQuasigroupByMultiplicationTableNC");
DeclareGlobalFunction("RightRackByMultiplicationTable");
DeclareGlobalFunction("RightRackByMultiplicationTableNC");

View File

@ -26,7 +26,7 @@ InstallGlobalFunction(LeftQuasigroup, function(arg)
arg := Flat(arg);
else
arg := Flat(arg);
fam := FamilyObj(arg[1]);
fam := FamilyObj(arg);
fi;
return CloneOfTypeByGenerators(IsLeftQuasigroup, fam, arg,
GeneratorsOfLeftQuasigroup,
@ -45,13 +45,32 @@ InstallGlobalFunction(LeftRack, function(arg)
arg := Flat(arg);
else
arg := Flat(arg);
fam := FamilyObj(arg[1]);
fam := FamilyObj(arg);
fi;
return CloneOfTypeByGenerators(IsLeftRack, fam, arg,
GeneratorsOfLeftQuasigroup,
LeftRackByMultiplicationTableNC);
end);
InstallGlobalFunction(LeftQuandle, function(arg)
local fam;
if Length(arg) = 0 then
Error("usage: LeftQuandle([<family>], <gens>)");
fi;
# Extract the family
if IsFamily(arg[1]) then
fam := arg[1];
Remove(arg, 1);
arg := Flat(arg);
else
arg := Flat(arg);
fam := FamilyObj(arg);
fi;
return CloneOfTypeByGenerators(IsLeftQuandle, fam, arg,
GeneratorsOfLeftQuasigroup,
LeftQuandleByMultiplicationTableNC);
end);
InstallGlobalFunction(RightQuasigroup, function(arg)
local fam;
if Length(arg) = 0 then
@ -64,7 +83,7 @@ InstallGlobalFunction(RightQuasigroup, function(arg)
arg := Flat(arg);
else
arg := Flat(arg);
fam := FamilyObj(arg[1]);
fam := FamilyObj(arg);
fi;
return CloneOfTypeByGenerators(IsRightQuasigroup, fam, arg,
GeneratorsOfRightQuasigroup,
@ -83,183 +102,53 @@ InstallGlobalFunction(RightRack, function(arg)
arg := Flat(arg);
else
arg := Flat(arg);
fam := FamilyObj(arg[1]);
fam := FamilyObj(arg);
fi;
return CloneOfTypeByGenerators(IsRightRack, fam, arg,
GeneratorsOfRightQuasigroup,
RightRackByMultiplicationTableNC);
end);
## Predicates to check tables for distributivity
InstallMethod(IsRightSelfDistributiveTable, "for matrix",
[ IsMatrix ],
T -> IsLeftSelfDistributiveTable(TransposedMat(T))
);
InstallMethod(IsLeftSelfDistributiveTable, "for matrix",
[ IsMatrix ],
function(T)
# Everybody else does it by checking all of the cases, so why not me, too?
# Is there a better way?
local n,i,j,k;
n := Length(T);
for i in [1..n] do for j in [1..n] do for k in [1..n] do
if T[i, T[j,k]] <> T[T[i,j], T[i,k]] then return false; fi;
od; od; od;
return true;
end);
## And now create them from multiplication tables
InstallGlobalFunction(LeftQuasigroupByMultiplicationTable,
function(T)
if not IsLeftQuasigroupTable(T) then
Error("Multiplication table <T> must have each row a permutation of ",
"the same entries.");
fi;
return LeftQuasigroupByMultiplicationTableNC(
CanonicalCayleyTableOfLeftQuasigroupTable(T));
InstallGlobalFunction(RightQuandle, function(arg)
local fam;
if Length(arg) = 0 then
Error("usage: RightQuandle([<family>], <gens>)");
fi;
# Extract the family
if IsFamily(arg[1]) then
fam := arg[1];
Remove(arg, 1);
arg := Flat(arg);
else
arg := Flat(arg);
fam := FamilyObj(arg);
fi;
return CloneOfTypeByGenerators(IsRightQuandle, fam, arg,
GeneratorsOfRightQuasigroup,
RightQuandleByMultiplicationTableNC);
end);
InstallGlobalFunction(LeftQuasigroupByMultiplicationTableNC,
T -> MagmaByMultiplicationTableCreatorNC(T, LeftQuasigroup,
IsLeftQuotientElement and IsMagmaByMultiplicationTableObj)
);
InstallGlobalFunction(RightQuasigroupByMultiplicationTable,
function(T)
if not IsRightQuasigroupTable(T) then
Error("Multiplication table <T> must have each row a permutation of ",
"the same entries.");
fi;
return RightQuasigroupByMultiplicationTableNC(CanonicalCayleyTable(T));
end);
InstallGlobalFunction(RightQuasigroupByMultiplicationTableNC,
T -> MagmaByMultiplicationTableCreatorNC(T, RightQuasigroup,
IsRightQuotientElement and IsMagmaByMultiplicationTableObj)
);
InstallGlobalFunction(LeftRackByMultiplicationTable,
function(T)
if not IsLeftQuasigroupTable(T) then
Error("Multiplication table <T> must have each row a permutation of ",
"the same entries.");
fi;
T := CanonicalCayleyTableOfLeftQuasigroupTable(T);
if not IsLeftSelfDistributiveTable(T) then
Error("Multiplication table <T> must be left self distributive.");
fi;
return LeftRackByMultiplicationTableNC(T);
end);
InstallGlobalFunction(LeftRackByMultiplicationTableNC,
T -> MagmaByMultiplicationTableCreatorNC(T, LeftRack,
IsLeftQuotientElement and IsLSelfDistElement and
IsMagmaByMultiplicationTableObj
)
);
InstallGlobalFunction(RightRackByMultiplicationTable,
function(T)
if not IsRightQuasigroupTable(T) then
Error("Multiplication table <T> must have each column a permutation of ",
"the same entries.");
fi;
T := CanonicalCayleyTable(T);
if not IsRightSelfDistributiveTable(T) then
Error("Multiplication table <T> must be right self distributive.");
fi;
return RightRackByMultiplicationTableNC(T);
end);
InstallGlobalFunction(RightRackByMultiplicationTableNC,
T -> MagmaByMultiplicationTableCreatorNC(T, RightRack,
IsRightQuotientElement and IsRSelfDistElement and
IsMagmaByMultiplicationTableObj
)
);
## And define the operations
InstallOtherMethod(LeftQuotient,
"for two elts in magma by mult table, when left has left quotients",
IsIdenticalObj,
[IsLeftQuotientElement, IsMagmaByMultiplicationTableObj],
function (l,r)
local fam, ix;
fam := FamilyObj(l);
ix := LeftDivisionTable(fam)[l![1],r![1]];
return fam!.set[ix];
end);
InstallOtherMethod(\/,
"for two elts in magma by mult table, when right has right quotients",
IsIdenticalObj,
[IsMagmaByMultiplicationTableObj, IsRightQuotientElement],
function (l,r)
local fam, ix;
fam := FamilyObj(r);
ix := RightDivisionTable(fam)[l![1],r![1]];
return fam!.set[ix];
end);
## Create division tables as needed
InstallMethod(LeftDivisionTable,
"for an object with a multiplication table",
[HasMultiplicationTable],
function(fam)
local LS, n;
LS := LeftPerms(fam);
n := Size(LS);
return List(LS, x->ListPerm(Inverse(x), n));
end);
InstallMethod(RightDivisionTable,
"for an object with a multiplication table",
[HasMultiplicationTable],
function (obj)
local RS, n;
RS := RightPerms(obj);
n := Size(RS);
return TransposedMat(List(RS, x->ListPerm(Inverse(x), n)));
end);
## Create perm lists as needed
InstallMethod(LeftPerms,
"for an object with a multiplication table",
[HasMultiplicationTable],
function(fam)
return List(MultiplicationTable(fam), x->PermList(x));
end);
InstallMethod(RightPerms,
"for an object with a muliplication table",
[HasMultiplicationTable],
function(fam)
return List(TransposedMat(MultiplicationTable(fam)), x->PermList(x));
end);
## Distributivity checkers for when need be
InstallMethod(IsLSelfDistributive, "for magma",
[IsMagma],
M -> IsLeftSelfDistributiveTable(MultiplicationTable(M))
);
InstallMethod(IsRSelfDistributive, "for magma",
[IsMagma],
M -> IsRightSelfDistributiveTable(MultiplicationTable(M))
);
## View and print and such
LeftObjString@ := function(Q)
# Don't test distributivity if we haven't already
if HasIsLSelfDistributive(Q) and IsLeftRack(Q) then return "LeftRack"; fi;
if HasIsLSelfDistributive(Q) and IsLeftRack(Q) then
if HasIsElementwiseIdempotent(Q) and IsElementwiseIdempotent(Q) then
return "LeftQuandle";
fi;
return "LeftRack";
fi;
return "LeftQuasigroup";
end;
RightObjString@ := function(Q)
# Don't test distributivity if we haven't already
if HasIsRSelfDistributive(Q) and IsRightRack(Q) then return "RightRack"; fi;
if HasIsRSelfDistributive(Q) and IsRightRack(Q) then
if HasIsElementwiseIdempotent(Q) and IsElementwiseIdempotent(Q) then
return "RightQuandle";
fi;
return "RightRack";
fi;
return "RightQuasigroup";
end;
@ -324,12 +213,22 @@ InstallMethod(Display, "for a right quasigroup with multiplication table",
end);
LeftObjView@ := function(Q)
if HasIsLSelfDistributive(Q) and IsLeftRack(Q) then return "<left rack"; fi;
# Don't test distributivity if we haven't already
if HasIsLSelfDistributive(Q) and IsLeftRack(Q) then
if HasIsElementwiseIdempotent(Q) and IsElementwiseIdempotent(Q) then
return "<left quandle";
fi;
return "<left rack";
fi;
return "<left quasigroup";
end;
RightObjView@ := function(Q)
# Don't test distributivity if we haven't already
if HasIsRSelfDistributive(Q) and IsRightRack(Q) then
if HasIsElementwiseIdempotent(Q) and IsElementwiseIdempotent(Q) then
return "<right quandle";
fi;
return "<right rack";
fi;
return "<right quasigroup";
@ -355,54 +254,3 @@ InstallMethod(ViewString, "for a right quasigroup with generators",
String(Size(GeneratorsOfRightQuasigroup(Q))),
" generators>"));
# Patch View/Print/Display for magma by mult objects
InstallMethod(String, "for an element of magma by multiplication table",
[IsMagmaByMultiplicationTableObj],
function(obj)
local fam;
fam := FamilyObj(obj);
if IsBound(fam!.elmNamePrefix) then
return Concatenation(fam!.elmNamePrefix, String(obj![1]));
fi;
return Concatenation("m", String(obj![1]));
end);
InstallMethod(ViewString, "for an element of magma by multiplication table",
[IsMagmaByMultiplicationTableObj],
obj -> String(obj));
InstallMethod(DisplayString, "for an element of magma by multiplication table",
[IsMagmaByMultiplicationTableObj],
obj -> String(obj));
InstallMethod(PrintObj, "for an element of magma by multiplication table",
[IsMagmaByMultiplicationTableObj],
function(obj) Print(String(obj)); end);
## Special case the Opposite function from LOOPS package, since the opposite
## of a left quasigroup is a right quasigroup and vice versa
# Is there a way to do this just once for each direction?
InstallMethod(Opposite, "for left quasigroup",
[ IsLeftQuasigroup ],
L -> RightQuasigroupByMultiplicationTable(
TransposedMat(MultiplicationTable(L))
)
);
InstallMethod(Opposite, "for left rack",
[ IsLeftRack ],
L -> RightRackByMultiplicationTableNC(TransposedMat(MultiplicationTable(L)))
);
InstallMethod(Opposite, "for right quasigroup",
[ IsRightQuasigroup ],
L -> LeftQuasigroupByMultiplicationTable(
TransposedMat(MultiplicationTable(L))
)
);
InstallMethod(Opposite, "for right rack",
[ IsRightRack ],
L -> LeftRackByMultiplicationTableNC(TransposedMat(MultiplicationTable(L)))
);

11
init.g
View File

@ -1,4 +1,11 @@
## init.g RAQ
## init.g RAQ: Racks and Quandles in GAP
# Definitions, representations, and elementary operations.
# Definitions, generation, and elementary properties and operations.
ReadPackage("raq", "gap/structure.gd");
# Quasigroups, racks, and quandles by multiplication tables
ReadPackage("raq", "gap/bytable.gd");
# Quandles by conjugation
#Readpackage("raq", "gap/byconj.gd");