Initial commit: enough to create a left quasigroup from a multiplication table and do left division therein

This commit is contained in:
Glen Whitney 2017-10-18 12:46:13 +02:00
commit 92a7bff629
6 changed files with 320 additions and 0 deletions

82
gap/structure.gd Normal file
View file

@ -0,0 +1,82 @@
## structure.gd RAQ Definitions, representations, and elementary operations.
## 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.
# An element that knows that multiplication in its family is left
# self-distributive:
DeclareCategory("IsLSelfDistElement", IsMultiplicativeElement);
DeclareCategoryCollections("IsLSelfDistElement");
# An element that knows that multiplication in its family is right
# self-distributive:
DeclareCategory("IsRSelfDistElement", IsMultiplicativeElement);
DeclareCategoryCollections("IsRSelfDistElement");
# Left self-distributive magmas:
DeclareProperty("IsLSelfDistributive", IsMagma);
InstallTrueMethod(IsLSelfDistributive,
IsMagma and IsLSelfDistElementCollection);
# Right self-distributive magmas:
DeclareProperty("IsRSelfDistributive", IsMagma);
InstallTrueMethod(IsRSelfDistributive,
IsMagma and IsRSelfDistElementCollection);
# Left and right racks
DeclareSynonym("IsLeftRack", IsLeftQuasigroup and IsLSelfDistributive);
DeclareSynonym("IsRightRack", IsRightQuasigroup and IsRSelfDistributive);
## One-sided quasigroups
# Returns the closure of <gens> under * and LeftQuotient;
# the family of elements of M may be specified, and must be if <gens>
# is empty (in which case M will be empty as well).
DeclareGlobalFunction("LeftQuasigroup");
DeclareGlobalFunction("RightQuasigroup");
DeclareGlobalFunction("LeftRack");
DeclareGlobalFunction("RightRack");
# Underlying operation
DeclareOperation("CloneOfTypeByGenerators",
[IsFilter, IsFamily, IsCollection, IsAttribute]);
# Attributes for the generators
# Generates the structure by \* and LeftQuotient. Note that for finite
# structures, these are the same as the GeneratorsOfMagma but in general more
# elements might be required to generate the structure just under *
DeclareAttribute("GeneratorsOfLeftQuasigroup", IsLeftQuasigroup);
InstallImmediateMethod(GeneratorsOfMagma,
"finite left quasigroups *-generated by left quasigroup generators",
IsLeftQuasigroup and IsFinite,
q -> GeneratorsOfLeftQuasigroup(q)
);
# Generates the structure by \* and \/, same considerations as above
DeclareAttribute("GeneratorsOfRightQuasigroup", IsRightQuasigroup);
InstallImmediateMethod(GeneratorsOfMagma,
"finite right quasigroups *-generated by right quasigroup generators",
IsRightQuasigroup and IsFinite,
q -> GeneratorsOfRightQuasigroup(q)
);
## 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);
# And the builders
DeclareGlobalFunction("LeftQuasigroupByMultiplicationTable");
DeclareGlobalFunction("LeftRackByMultiplicationTable");
DeclareGlobalFunction("RightQuasigroupByMultiplicationTable");
DeclareGlobalFunction("RightRackByMultiplicationTable");

134
gap/structure.gi Normal file
View file

@ -0,0 +1,134 @@
## structure.gi RAQ Implementation of definitiions, reps, and elt operations
## Create structures with generators
InstallMethod(CloneOfTypeByGenerators,
"for generic category of magma, family, collection, gen attrib",
[IsFilter, IsFamily, IsCollection, IsAttribute],
function(cat, fam, gens, genAttrib)
local M;
if not(IsEmpty(gens) or IsIdenticalObj(FamilyObj(gens), fam)) then
Error("<fam> and family of <gens> do not match");
fi;
M := Objectify(NewType( fam, cat and IsAttributeStoringRep), rec());
Setter(genAttrib)(M, AsList(gens));
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([<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[1]);
fi;
return CloneOfTypeByGenerators(IsLeftQuasigroup, fam, arg,
GeneratorsOfLeftQuasigroup);
end);
InstallGlobalFunction(LeftRack, function(arg)
local fam;
if Length(arg) = 0 then
Error("usage: LeftRack([<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[1]);
fi;
return CloneOfTypeByGenerators(IsLeftRack, fam, arg,
GeneratorsOfLeftQuasigroup);
end);
InstallGlobalFunction(RightQuasigroup, function(arg)
local fam;
if Length(arg) = 0 then
Error("usage: RightQuasigroup([<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[1]);
fi;
return CloneOfTypeByGenerators(IsRightQuasigroup, fam, arg,
GeneratorsOfRightQuasigroup);
end);
InstallGlobalFunction(RightRack, function(arg)
local fam;
if Length(arg) = 0 then
Error("usage: RightRack([<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[1]);
fi;
return CloneOfTypeByGenerators(IsRightRack, fam, arg,
GeneratorsOfRightQuasigroup);
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 MagmaByMultiplicationTableCreatorNC(
CanonicalCayleyTableOfLeftQuasigroupTable(T),
LeftQuasigroup,
IsLeftQuotientElement and IsMagmaByMultiplicationTableObj
);
end);
## And define the operation
InstallOtherMethod(LeftQuotient,
"for two elts in magma by mult table, when left has left quotients",
IsIdenticalObj,
[IsLeftQuotientElement, IsMagmaByMultiplicationTableObj],
function (l,r)
return DivisionTable(FamilyObj(l))[l![1],r![1]];
end);
## Create division tables as needed
InstallMethod(LeftDivisionTable,
"for a family with a multiplication table",
[IsFamily and HasMultiplicationTable],
function(fam)
local LS, n;
LS := LeftSectionList(fam);
n := Size(T);
return List(T, x->ListPerm(Inverse(x), n));
end);
## Create section lists as needed
InstallMethod(LeftSectionList,
"for a family with a multiplication table",
[IsFamily and HasMultiplicationTable],
function(fam)
return List(MultiplicationTable(fam), x->PermList(x));
end);