## structure.gi RAQ Implementation of definitiions, reps, and elt operations ## Create structures with generators InstallGlobalFunction(CloneOfTypeByGenerators, 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); ## 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[1]); fi; return CloneOfTypeByGenerators(IsLeftQuasigroup, fam, arg, GeneratorsOfLeftQuasigroup, LeftQuasigroupByMultiplicationTable); end); InstallGlobalFunction(LeftRack, function(arg) local fam; if Length(arg) = 0 then Error("usage: LeftRack([], )"); 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[1]); fi; return CloneOfTypeByGenerators(IsLeftRack, fam, arg, GeneratorsOfLeftQuasigroup, LeftRackByMultiplicationTableNC); 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[1]); fi; return CloneOfTypeByGenerators(IsRightQuasigroup, fam, arg, GeneratorsOfRightQuasigroup, RightQuasigroupByMultiplicationTable); end); InstallGlobalFunction(RightRack, function(arg) local fam; if Length(arg) = 0 then Error("usage: RightRack([], )"); 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[1]); 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 MagmaByMultiplicationTableCreatorNC( CanonicalCayleyTableOfLeftQuasigroupTable(T), LeftQuasigroup, IsLeftQuotientElement and IsMagmaByMultiplicationTableObj ); end); 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", 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(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);