Add quandles and split out functions based on multiplication tables
This commit is contained in:
parent
27c5f78120
commit
d304b53fde
31
gap/bytable.gd
Normal file
31
gap/bytable.gd
Normal file
@ -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);
|
271
gap/bytable.gi
Normal file
271
gap/bytable.gi
Normal file
@ -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 <T> 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 <T> 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 <T> must have each row a permutation of ",
|
||||
"the same entries.");
|
||||
fi;
|
||||
T := CanonicalCayleyTableOfLeftQuasigroupTable(T);
|
||||
if not IsLeftSelfDistributiveTable(T) then
|
||||
Error("Multiplication table <T> 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 <T> 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 <T> 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 <T> must have each column a permutation of ",
|
||||
"the same entries.");
|
||||
fi;
|
||||
T := CanonicalCayleyTable(T);
|
||||
if not IsRightSelfDistributiveTable(T) then
|
||||
Error("Multiplication table <T> 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 <T> 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 <T> 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)))
|
||||
);
|
@ -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 <gens> under * and LeftQuotient;
|
||||
# the family of elements of M may be specified, and must be if <gens>
|
||||
@ -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");
|
||||
|
282
gap/structure.gi
282
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([<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);
|
||||
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 <T> 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([<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);
|
||||
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 <T> 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 <T> must have each row a permutation of ",
|
||||
"the same entries.");
|
||||
fi;
|
||||
T := CanonicalCayleyTableOfLeftQuasigroupTable(T);
|
||||
if not IsLeftSelfDistributiveTable(T) then
|
||||
Error("Multiplication table <T> 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 <T> must have each column a permutation of ",
|
||||
"the same entries.");
|
||||
fi;
|
||||
T := CanonicalCayleyTable(T);
|
||||
if not IsRightSelfDistributiveTable(T) then
|
||||
Error("Multiplication table <T> 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 "<left rack"; fi;
|
||||
# Don't test distributivity if we haven't already
|
||||
if HasIsLSelfDistributive(Q) and IsLeftRack(Q) then
|
||||
if HasIsElementwiseIdempotent(Q) and IsElementwiseIdempotent(Q) then
|
||||
return "<left quandle";
|
||||
fi;
|
||||
return "<left rack";
|
||||
fi;
|
||||
return "<left quasigroup";
|
||||
end;
|
||||
|
||||
|
||||
RightObjView@ := function(Q)
|
||||
# Don't test distributivity if we haven't already
|
||||
if HasIsRSelfDistributive(Q) and IsRightRack(Q) then
|
||||
if HasIsElementwiseIdempotent(Q) and IsElementwiseIdempotent(Q) then
|
||||
return "<right quandle";
|
||||
fi;
|
||||
return "<right rack";
|
||||
fi;
|
||||
return "<right quasigroup";
|
||||
@ -355,54 +254,3 @@ InstallMethod(ViewString, "for a right quasigroup with generators",
|
||||
String(Size(GeneratorsOfRightQuasigroup(Q))),
|
||||
" generators>"));
|
||||
|
||||
# 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)))
|
||||
);
|
||||
|
11
init.g
11
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");
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user