From bc8c89289834006e6c74850eb4332e3dbaf27c47 Mon Sep 17 00:00:00 2001 From: Glen Whitney Date: Wed, 18 Oct 2017 21:37:48 +0200 Subject: [PATCH] Add constructors for the other one-sided quasigroups and racks. --- gap/structure.gd | 14 +++-- gap/structure.gi | 132 +++++++++++++++++++++++++++++++++++++++++------ 2 files changed, 127 insertions(+), 19 deletions(-) diff --git a/gap/structure.gd b/gap/structure.gd index eb13bdc..5f06f56 100644 --- a/gap/structure.gd +++ b/gap/structure.gd @@ -20,6 +20,10 @@ 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, @@ -71,13 +75,15 @@ InstallImmediateMethod(GeneratorsOfMagma, ## And now, build them from multiplication tables # Need attributes on the families to store the sections and division tables -DeclareAttribute("LeftSectionList", IsFamily and HasMultiplicationTable); -DeclareAttribute("RightSectionList", IsFamily and HasMultiplicationTable); -DeclareAttribute("LeftDivisionTable", IsFamily and HasMultiplicationTable); -DeclareAttribute("RightDivisionTable", IsFamily and HasMultiplicationTable); +DeclareAttribute("LeftPerms", HasMultiplicationTable); +DeclareAttribute("RightPerms", HasMultiplicationTable); +DeclareAttribute("LeftDivisionTable", HasMultiplicationTable); +DeclareAttribute("RightDivisionTable", HasMultiplicationTable); # And the builders DeclareGlobalFunction("LeftQuasigroupByMultiplicationTable"); DeclareGlobalFunction("LeftRackByMultiplicationTable"); +DeclareGlobalFunction("LeftRackByMultiplicationTableNC"); DeclareGlobalFunction("RightQuasigroupByMultiplicationTable"); DeclareGlobalFunction("RightRackByMultiplicationTable"); +DeclareGlobalFunction("RightRackByMultiplicationTableNC"); diff --git a/gap/structure.gi b/gap/structure.gi index 193ba75..bc72f0c 100644 --- a/gap/structure.gi +++ b/gap/structure.gi @@ -2,13 +2,14 @@ ## Create structures with generators InstallGlobalFunction(CloneOfTypeByGenerators, - function(cat, fam, gens, genAttrib) + function(cat, fam, gens, genAttrib, tableCstr), local M; if not(IsEmpty(gens) or IsIdenticalObj(FamilyObj(gens), fam)) then Error(" and family of do not match"); fi; M := Objectify(NewType( fam, cat and IsAttributeStoringRep), rec()); Setter(genAttrib)(M, AsList(gens)); + SetConstructorFromTable(M, tableCstr); return M; end); @@ -28,7 +29,8 @@ InstallGlobalFunction(LeftQuasigroup, function(arg) fam := FamilyObj(arg[1]); fi; return CloneOfTypeByGenerators(IsLeftQuasigroup, fam, arg, - GeneratorsOfLeftQuasigroup); + GeneratorsOfLeftQuasigroup, + LeftQuasigroupByMultiplicationTable); end); InstallGlobalFunction(LeftRack, function(arg) @@ -46,7 +48,8 @@ InstallGlobalFunction(LeftRack, function(arg) fam := FamilyObj(arg[1]); fi; return CloneOfTypeByGenerators(IsLeftRack, fam, arg, - GeneratorsOfLeftQuasigroup); + GeneratorsOfLeftQuasigroup, + LeftRackByMultiplicationTableNC); end); InstallGlobalFunction(RightQuasigroup, function(arg) @@ -64,7 +67,8 @@ InstallGlobalFunction(RightQuasigroup, function(arg) fam := FamilyObj(arg[1]); fi; return CloneOfTypeByGenerators(IsRightQuasigroup, fam, arg, - GeneratorsOfRightQuasigroup); + GeneratorsOfRightQuasigroup, + RightQuasigroupByMultiplicationTable); end); InstallGlobalFunction(RightRack, function(arg) @@ -82,9 +86,29 @@ InstallGlobalFunction(RightRack, function(arg) fam := FamilyObj(arg[1]); fi; return CloneOfTypeByGenerators(IsRightRack, fam, arg, - GeneratorsOfRightQuasigroup); + 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) @@ -99,7 +123,60 @@ InstallGlobalFunction(LeftQuasigroupByMultiplicationTable, ); end); -## And define the operation +InstallGlobalFunction(RightQuasigroupByMultiplicationTable, + function(T) + if not IsRightQuasigroupTable(T) then + Error("Multiplication table must have each column a permutation of ", + "the same entries."); + fi; + return MagmaByMultiplicationTableCreatorNC( + CanonicalCayleyTable(T), + RightQuasigroup, + IsRightQuotientElement and IsMagmaByMultiplicationTableObj + ); +end); + +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 LeftRackByMulitplicationTableNC(T); + end); + +InstallGlobalFunction(LeftRackByMulitplicationTableNC, + T -> MagmaByMultiplicationTableCreatorNC(T, LeftRack, + IsLeftQuotientElement and IsLSelfDistributiveElement 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 IsRSelfDistributiveElement and + IsMagmaByMultiplicationTableObj + ); +); + +## And define the operations InstallOtherMethod(LeftQuotient, "for two elts in magma by mult table, when left has left quotients", @@ -112,24 +189,49 @@ InstallOtherMethod(LeftQuotient, 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 a family with a multiplication table", - [IsFamily and HasMultiplicationTable], + "for an object with a multiplication table", + [HasMultiplicationTable], function(fam) local LS, n; - LS := LeftSectionList(fam); + LS := LeftPerms(fam); n := Size(LS); return List(LS, x->ListPerm(Inverse(x), n)); end); -## Create section lists as needed -InstallMethod(LeftSectionList, - "for a family with a multiplication table", - [IsFamily and HasMultiplicationTable], +InstallMethod(RightDivisionTable, + "for an object with a multiplication table", + [HasMultiplicationTable], + function (obj) + local RS, n; + RS := RightPerms(fam); + 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);