diff --git a/gap/bytable.gd b/gap/bytable.gd new file mode 100644 index 0000000..190ca13 --- /dev/null +++ b/gap/bytable.gd @@ -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); diff --git a/gap/bytable.gi b/gap/bytable.gi new file mode 100644 index 0000000..e1c1882 --- /dev/null +++ b/gap/bytable.gi @@ -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 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 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 must have each row a permutation of ", + "the same entries."); + fi; + T := CanonicalCayleyTableOfLeftQuasigroupTable(T); + if not IsLeftSelfDistributiveTable(T) then + Error("Multiplication table 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 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 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 must have each column a permutation of ", + "the same entries."); + fi; + T := CanonicalCayleyTable(T); + if not IsRightSelfDistributiveTable(T) then + Error("Multiplication table 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 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 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))) +); diff --git a/gap/structure.gd b/gap/structure.gd index aaa49f3..8ac3a03 100644 --- a/gap/structure.gd +++ b/gap/structure.gd @@ -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 under * and LeftQuotient; # the family of elements of M may be specified, and must be if @@ -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"); diff --git a/gap/structure.gi b/gap/structure.gi index 576076c..352468f 100644 --- a/gap/structure.gi +++ b/gap/structure.gi @@ -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([], )"); + 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 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([], )"); + 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 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 must have each row a permutation of ", - "the same entries."); - fi; - T := CanonicalCayleyTableOfLeftQuasigroupTable(T); - if not IsLeftSelfDistributiveTable(T) then - Error("Multiplication table 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 must have each column a permutation of ", - "the same entries."); - fi; - T := CanonicalCayleyTable(T); - if not IsRightSelfDistributiveTable(T) then - Error("Multiplication table 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 "")); -# 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))) -); diff --git a/init.g b/init.g index 751d185..67f3b53 100644 --- a/init.g +++ b/init.g @@ -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"); +