diff --git a/gap/bytable.gi b/gap/bytable.gi index e1c1882..81bda85 100644 --- a/gap/bytable.gi +++ b/gap/bytable.gi @@ -36,7 +36,7 @@ InstallGlobalFunction(LeftQuasigroupByMultiplicationTable, end); InstallGlobalFunction(LeftQuasigroupByMultiplicationTableNC, - T -> MagmaByMultiplicationTableCreatorNC(T, LeftQuasigroup, + T -> MagmaByMultiplicationTableCreatorNC(T, LeftQuasigroupNC, IsLeftQuotientElement and IsMagmaByMultiplicationTableObj) ); @@ -50,7 +50,7 @@ InstallGlobalFunction(RightQuasigroupByMultiplicationTable, end); InstallGlobalFunction(RightQuasigroupByMultiplicationTableNC, - T -> MagmaByMultiplicationTableCreatorNC(T, RightQuasigroup, + T -> MagmaByMultiplicationTableCreatorNC(T, RightQuasigroupNC, IsRightQuotientElement and IsMagmaByMultiplicationTableObj) ); @@ -68,7 +68,7 @@ InstallGlobalFunction(LeftRackByMultiplicationTable, end); InstallGlobalFunction(LeftRackByMultiplicationTableNC, - T -> MagmaByMultiplicationTableCreatorNC(T, LeftRack, + T -> MagmaByMultiplicationTableCreatorNC(T, LeftRackNC, IsLeftQuotientElement and IsLSelfDistElement and IsMagmaByMultiplicationTableObj ) @@ -89,7 +89,7 @@ InstallGlobalFunction(LeftQuandleByMultiplicationTable, end); InstallGlobalFunction(LeftQuandleByMultiplicationTableNC, - T -> MagmaByMultiplicationTableCreatorNC(T, LeftQuandle, + T -> MagmaByMultiplicationTableCreatorNC(T, LeftQuandleNC, IsLeftQuotientElement and IsLSelfDistElement and IsIdempotent and IsMagmaByMultiplicationTableObj ) @@ -109,7 +109,7 @@ InstallGlobalFunction(RightRackByMultiplicationTable, end); InstallGlobalFunction(RightRackByMultiplicationTableNC, - T -> MagmaByMultiplicationTableCreatorNC(T, RightRack, + T -> MagmaByMultiplicationTableCreatorNC(T, RightRackNC, IsRightQuotientElement and IsRSelfDistElement and IsMagmaByMultiplicationTableObj ) @@ -130,7 +130,7 @@ InstallGlobalFunction(RightQuandleByMultiplicationTable, end); InstallGlobalFunction(RightQuandleByMultiplicationTableNC, - T -> MagmaByMultiplicationTableCreatorNC(T, RightQuandle, + T -> MagmaByMultiplicationTableCreatorNC(T, RightQuandleNC, IsRightQuotientElement and IsRSelfDistElement and IsIdempotent and IsMagmaByMultiplicationTableObj ) @@ -197,21 +197,16 @@ InstallMethod(RightPerms, end); ## Distributivity/idempotence checkers for when need be -InstallMethod(IsLSelfDistributive, "for magma", - [IsMagma and IsFinite], +InstallMethod(IsLSelfDistributive, "for collections with multiplication tables", + [HasMultiplicationTable], M -> IsLeftSelfDistributiveTable(MultiplicationTable(M)) ); -InstallMethod(IsRSelfDistributive, "for magma", - [IsMagma and IsFinite], +InstallMethod(IsRSelfDistributive, "for collections with multiplication table", + [HasMultiplicationTable], 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], diff --git a/gap/structure.gd b/gap/structure.gd index 8ac3a03..30941f6 100644 --- a/gap/structure.gd +++ b/gap/structure.gd @@ -21,15 +21,13 @@ DeclareCategoryCollections("IsLSelfDistElement"); DeclareCategory("IsRSelfDistElement", IsMultiplicativeElement); DeclareCategoryCollections("IsRSelfDistElement"); -# Left self-distributive magmas: -DeclareProperty("IsLSelfDistributive", IsMagma); -InstallTrueMethod(IsLSelfDistributive, - IsMagma and IsLSelfDistElementCollection); +# Left self-distributive collections of elements: +DeclareProperty("IsLSelfDistributive", IsMultiplicativeElementCollection); +InstallTrueMethod(IsLSelfDistributive, IsLSelfDistElementCollection); -# Right self-distributive magmas: -DeclareProperty("IsRSelfDistributive", IsMagma); -InstallTrueMethod(IsRSelfDistributive, - IsMagma and IsRSelfDistElementCollection); +# Right self-distributive collections of elements: +DeclareProperty("IsRSelfDistributive", IsMultiplicativeElementCollection); +InstallTrueMethod(IsRSelfDistributive, IsRSelfDistElementCollection); ## Idempotence # There is already a property IsIdempotent on elements, but to definw @@ -37,9 +35,9 @@ InstallTrueMethod(IsRSelfDistributive, # collections category: DeclareCategoryCollections("IsIdempotent"); -# Idempotent magmas, i.e. magmas in which every element is idempotent -DeclareProperty("IsElementwiseIdempotent", IsMagma); -InstallTrueMethod(IsElementwiseIdempotent, IsMagma and IsIdempotentCollection); +# Collections in which every element is idempotent +DeclareProperty("IsElementwiseIdempotent", IsMultiplicativeElementCollection); +InstallTrueMethod(IsElementwiseIdempotent, IsIdempotentCollection); ## Left and right racks and quandles DeclareSynonym("IsLeftRack", IsLeftQuasigroup and IsLSelfDistributive); @@ -54,11 +52,17 @@ DeclareSynonym("IsRightQuandle", IsLeftRack and IsElementwiseIdempotent); # the family of elements of M may be specified, and must be if # is empty (in which case M will be empty as well). DeclareGlobalFunction("LeftQuasigroup"); +DeclareGlobalFunction("LeftQuasigroupNC"); DeclareGlobalFunction("RightQuasigroup"); +DeclareGlobalFunction("RightQuasigroupNC"); DeclareGlobalFunction("LeftRack"); +DeclareGlobalFunction("LeftRackNC"); DeclareGlobalFunction("RightRack"); +DeclareGlobalFunction("RightRackNC"); DeclareGlobalFunction("LeftQuandle"); +DeclareGlobalFunction("LeftQuandleNC"); DeclareGlobalFunction("RightQuandle"); +DeclareGlobalFunction("RightQuandleNC"); # Underlying operation DeclareGlobalFunction("CloneOfTypeByGenerators"); diff --git a/gap/structure.gi b/gap/structure.gi index 352468f..e58ad2a 100644 --- a/gap/structure.gi +++ b/gap/structure.gi @@ -1,6 +1,36 @@ ## structure.gi RAQ Implementation of definitiions, reps, and elt operations +## Testing properties of collections the hard way if we have to + +InstallMethod(IsElementwiseIdempotent, "for finite collections", + [IsMultiplicativeElementCollection and IsFinite], + M -> ForAll(Elements(M), m->IsIdempotent(m)) +); + +InstallMethod(IsLSelfDistributive, + "for arbitrary multiplicative collections, the hard way", + [IsMultiplicativeElementCollection], + function (C) + local a,b,d; + for a in C do for b in C do for d in C do + if d*(a*b) <> (d*a)*(d*b) then return false; fi; + od; od; od; + return true; +end); + +InstallMethod(IsRSelfDistributive, + "for arbitrary multiplicative collections, the hard way", + [IsMultiplicativeElementCollection], + function (C) + local a,b,d; + for a in C do for b in C do for d in C do + if (a*b)*d <> (a*d)*(b*d) then return false; fi; + od; od; od; + return true; +end); + ## Create structures with generators + InstallGlobalFunction(CloneOfTypeByGenerators, function(cat, fam, gens, genAttrib, tableCstr) local M; @@ -13,122 +43,131 @@ InstallGlobalFunction(CloneOfTypeByGenerators, return M; end); +## Helpers for the constructors below: + +ArgHelper@ := function(parmlist) + # returns a list of the family and the flat list of elements of parmlist + if Length(parmlist) = 0 then + Error("usage: RAQ constructors take an optional family, followed by gens"); + fi; + if IsFamily(parmlist[1]) then return [Remove(parmlist,1), Flat(parmlist)]; fi; + parmlist := Flat(parmlist); + return [FamilyObj(parmlist), parmlist]; +end; + +CheckLQGprop@ := function(gens) + local g, h; + # Make sure all elements in gens have left quotient property pairwise + for g in gens do for h in gens do + if g*LeftQuotient(g,h) <> h or LeftQuotient(g,g*h) <> h then + Error("left quasigroup property of left quotients violated"); + fi; + od; od; + return; +end; + +CheckRQGprop@ := function(gens) + local g, h; + # Make sure all elements in gens have right quotient property pairwise + for g in gens do for h in gens do + if (h*g)/g <> h or (h/g)*g <> h then + Error("right quasigroup property of / violated"); + fi; + od; od; + return; +end; + ## Functions for each of the magma categories here InstallGlobalFunction(LeftQuasigroup, function(arg) - local fam; - if Length(arg) = 0 then - Error("usage: LeftQuasigroup([], )"); - 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(IsLeftQuasigroup, fam, arg, + arg := ArgHelper@(arg); + CheckLQGprop@(arg[2]); + return LeftQuasigroupNC(arg[1], arg[2]); +end); + +InstallGlobalFunction(LeftQuasigroupNC, function(fam, gens) + return CloneOfTypeByGenerators(IsLeftQuasigroup, fam, gens, GeneratorsOfLeftQuasigroup, LeftQuasigroupByMultiplicationTableNC); end); InstallGlobalFunction(LeftRack, function(arg) - local fam; - if Length(arg) = 0 then - Error("usage: LeftRack([], )"); + arg := ArgHelper@(arg); + CheckLQGprop@(arg[2]); + if not IsLSelfDistributive(arg[2]) then + Error("Left rack must have left distributive generators"); 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(IsLeftRack, fam, arg, + return LeftRackNC(arg[1], arg[2]); +end); + +IntallGlobalFunction(LeftRackNC, function(fam, gens) + return CloneOfTypeByGenerators(IsLeftRack, fam, gens, GeneratorsOfLeftQuasigroup, LeftRackByMultiplicationTableNC); end); InstallGlobalFunction(LeftQuandle, function(arg) - local fam; - if Length(arg) = 0 then - Error("usage: LeftQuandle([], )"); + arg := ArgHelper@(arg); + CheckLQGprop@(arg[2]); + if not IsLSelfDistributive(arg[2]) then + Error("Left quandle must have left distributive generators"); 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); + if not IsElementwiseIdempotent(arg[2]) then + Error("Quandles must contain only idempotent elements"); fi; - return CloneOfTypeByGenerators(IsLeftQuandle, fam, arg, + return LeftQuandleNC(arg[1], arg[2]); +end); + +InstallGlobalFunction(LeftQuandleNC, function(fam, gens) + return CloneOfTypeByGenerators(IsLeftQuandle, fam, gens, GeneratorsOfLeftQuasigroup, LeftQuandleByMultiplicationTableNC); end); InstallGlobalFunction(RightQuasigroup, function(arg) - local fam; - if Length(arg) = 0 then - Error("usage: RightQuasigroup([], )"); - 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(IsRightQuasigroup, fam, arg, - GeneratorsOfRightQuasigroup, + arg := ArgHelper@(arg); + CheckRQGprop@(arg[2]); + return RightQuasigroupNC(arg[1], arg[2]); +end); + +InstallGlobalFunction(RightQuasigroupNC, function(fam, gens) + return CloneOfTypeByGenerators(IsRightQuasigroup, fam, gens, + GeneratorsOfRightQuasigroup, RightQuasigroupByMultiplicationTableNC); end); InstallGlobalFunction(RightRack, function(arg) - local fam; - if Length(arg) = 0 then - Error("usage: RightRack([], )"); + arg := ArgHelper@(arg); + CheckRQGprop@(arg[2]); + if not IsRSelfDistributive(arg[2]) then + Error("Right rack must have right distributive generators"); 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(IsRightRack, fam, arg, + return RightRackNC(arg[1], arg[2]); +end); + +IntallGlobalFunction(RightRackNC, function(fam, gens) + return CloneOfTypeByGenerators(IsRightRack, fam, gens, GeneratorsOfRightQuasigroup, RightRackByMultiplicationTableNC); end); InstallGlobalFunction(RightQuandle, function(arg) - local fam; - if Length(arg) = 0 then - Error("usage: RightQuandle([], )"); + arg := ArgHelper@(arg); + CheckLQGprop@(arg[2]); + if not IsRSelfDistributive(arg[2]) then + Error("Right quandle must have right distributive generators"); 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); + if not IsElementwiseIdempotent(arg[2]) then + Error("Quandles must contain only idempotent elements"); fi; - return CloneOfTypeByGenerators(IsRightQuandle, fam, arg, + return RightQuandleNC(arg[1], arg[2]); +end); + +InstallGlobalFunction(RightQuandleNC, function(fam, gens) + return CloneOfTypeByGenerators(IsRightQuandle, fam, gens, GeneratorsOfRightQuasigroup, RightQuandleByMultiplicationTableNC); end); - ## View and print and such LeftObjString@ := function(Q) # Don't test distributivity if we haven't already