Add quandles and split out functions based on multiplication tables
This commit is contained in:
parent
27c5f78120
commit
d304b53fde
|
@ -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);
|
|
@ -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
|
## GAP Categories and representations
|
||||||
|
|
||||||
## Self-distributivity
|
## Self-distributivity
|
||||||
# Note these are properties that should be defined just at the level of
|
# Note these are properties that can and therefore should be defined just at
|
||||||
# MultiplicativeElements and Magmas, hence although the LOOPS package defines
|
# the level of MultiplicativeElements and Magmas, hence although the LOOPS
|
||||||
# IsLDistributive and IsRDistributive for quasigroups, they would be ambiguous
|
# package defines IsLDistributive and IsRDistributive for quasigroups, they
|
||||||
# in the case of something like a semiring whose multiplicative structure was
|
# would be ambiguous in the case of something like a semiring whose
|
||||||
# a quasigroup (cf. https://arxiv.org/abs/0910.4760). Hence, we implement them
|
# multiplicative structure was a quasigroup
|
||||||
# in RAQ with new, non-conflicting terms.
|
# (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
|
# An element that knows that multiplication in its family is left
|
||||||
# self-distributive:
|
# self-distributive:
|
||||||
|
@ -20,10 +21,6 @@ DeclareCategoryCollections("IsLSelfDistElement");
|
||||||
DeclareCategory("IsRSelfDistElement", IsMultiplicativeElement);
|
DeclareCategory("IsRSelfDistElement", IsMultiplicativeElement);
|
||||||
DeclareCategoryCollections("IsRSelfDistElement");
|
DeclareCategoryCollections("IsRSelfDistElement");
|
||||||
|
|
||||||
# Predicates on tables:
|
|
||||||
DeclareProperty( "IsLeftSelfDistributiveTable", IsMatrix );
|
|
||||||
DeclareProperty( "IsRightSelfDistributiveTable", IsMatrix );
|
|
||||||
|
|
||||||
# Left self-distributive magmas:
|
# Left self-distributive magmas:
|
||||||
DeclareProperty("IsLSelfDistributive", IsMagma);
|
DeclareProperty("IsLSelfDistributive", IsMagma);
|
||||||
InstallTrueMethod(IsLSelfDistributive,
|
InstallTrueMethod(IsLSelfDistributive,
|
||||||
|
@ -34,11 +31,24 @@ DeclareProperty("IsRSelfDistributive", IsMagma);
|
||||||
InstallTrueMethod(IsRSelfDistributive,
|
InstallTrueMethod(IsRSelfDistributive,
|
||||||
IsMagma and IsRSelfDistElementCollection);
|
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("IsLeftRack", IsLeftQuasigroup and IsLSelfDistributive);
|
||||||
DeclareSynonym("IsRightRack", IsRightQuasigroup and IsRSelfDistributive);
|
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;
|
# Returns the closure of <gens> under * and LeftQuotient;
|
||||||
# the family of elements of M may be specified, and must be if <gens>
|
# the family of elements of M may be specified, and must be if <gens>
|
||||||
|
@ -47,6 +57,8 @@ DeclareGlobalFunction("LeftQuasigroup");
|
||||||
DeclareGlobalFunction("RightQuasigroup");
|
DeclareGlobalFunction("RightQuasigroup");
|
||||||
DeclareGlobalFunction("LeftRack");
|
DeclareGlobalFunction("LeftRack");
|
||||||
DeclareGlobalFunction("RightRack");
|
DeclareGlobalFunction("RightRack");
|
||||||
|
DeclareGlobalFunction("LeftQuandle");
|
||||||
|
DeclareGlobalFunction("RightQuandle");
|
||||||
|
|
||||||
# Underlying operation
|
# Underlying operation
|
||||||
DeclareGlobalFunction("CloneOfTypeByGenerators");
|
DeclareGlobalFunction("CloneOfTypeByGenerators");
|
||||||
|
@ -72,20 +84,3 @@ InstallImmediateMethod(GeneratorsOfMagma,
|
||||||
2,
|
2,
|
||||||
q -> GeneratorsOfRightQuasigroup(q)
|
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);
|
arg := Flat(arg);
|
||||||
else
|
else
|
||||||
arg := Flat(arg);
|
arg := Flat(arg);
|
||||||
fam := FamilyObj(arg[1]);
|
fam := FamilyObj(arg);
|
||||||
fi;
|
fi;
|
||||||
return CloneOfTypeByGenerators(IsLeftQuasigroup, fam, arg,
|
return CloneOfTypeByGenerators(IsLeftQuasigroup, fam, arg,
|
||||||
GeneratorsOfLeftQuasigroup,
|
GeneratorsOfLeftQuasigroup,
|
||||||
|
@ -45,13 +45,32 @@ InstallGlobalFunction(LeftRack, function(arg)
|
||||||
arg := Flat(arg);
|
arg := Flat(arg);
|
||||||
else
|
else
|
||||||
arg := Flat(arg);
|
arg := Flat(arg);
|
||||||
fam := FamilyObj(arg[1]);
|
fam := FamilyObj(arg);
|
||||||
fi;
|
fi;
|
||||||
return CloneOfTypeByGenerators(IsLeftRack, fam, arg,
|
return CloneOfTypeByGenerators(IsLeftRack, fam, arg,
|
||||||
GeneratorsOfLeftQuasigroup,
|
GeneratorsOfLeftQuasigroup,
|
||||||
LeftRackByMultiplicationTableNC);
|
LeftRackByMultiplicationTableNC);
|
||||||
end);
|
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)
|
InstallGlobalFunction(RightQuasigroup, function(arg)
|
||||||
local fam;
|
local fam;
|
||||||
if Length(arg) = 0 then
|
if Length(arg) = 0 then
|
||||||
|
@ -64,7 +83,7 @@ InstallGlobalFunction(RightQuasigroup, function(arg)
|
||||||
arg := Flat(arg);
|
arg := Flat(arg);
|
||||||
else
|
else
|
||||||
arg := Flat(arg);
|
arg := Flat(arg);
|
||||||
fam := FamilyObj(arg[1]);
|
fam := FamilyObj(arg);
|
||||||
fi;
|
fi;
|
||||||
return CloneOfTypeByGenerators(IsRightQuasigroup, fam, arg,
|
return CloneOfTypeByGenerators(IsRightQuasigroup, fam, arg,
|
||||||
GeneratorsOfRightQuasigroup,
|
GeneratorsOfRightQuasigroup,
|
||||||
|
@ -83,183 +102,53 @@ InstallGlobalFunction(RightRack, function(arg)
|
||||||
arg := Flat(arg);
|
arg := Flat(arg);
|
||||||
else
|
else
|
||||||
arg := Flat(arg);
|
arg := Flat(arg);
|
||||||
fam := FamilyObj(arg[1]);
|
fam := FamilyObj(arg);
|
||||||
fi;
|
fi;
|
||||||
return CloneOfTypeByGenerators(IsRightRack, fam, arg,
|
return CloneOfTypeByGenerators(IsRightRack, fam, arg,
|
||||||
GeneratorsOfRightQuasigroup,
|
GeneratorsOfRightQuasigroup,
|
||||||
RightRackByMultiplicationTableNC);
|
RightRackByMultiplicationTableNC);
|
||||||
end);
|
end);
|
||||||
|
|
||||||
## Predicates to check tables for distributivity
|
InstallGlobalFunction(RightQuandle, function(arg)
|
||||||
InstallMethod(IsRightSelfDistributiveTable, "for matrix",
|
local fam;
|
||||||
[ IsMatrix ],
|
if Length(arg) = 0 then
|
||||||
T -> IsLeftSelfDistributiveTable(TransposedMat(T))
|
Error("usage: RightQuandle([<family>], <gens>)");
|
||||||
);
|
fi;
|
||||||
|
# Extract the family
|
||||||
InstallMethod(IsLeftSelfDistributiveTable, "for matrix",
|
if IsFamily(arg[1]) then
|
||||||
[ IsMatrix ],
|
fam := arg[1];
|
||||||
function(T)
|
Remove(arg, 1);
|
||||||
# Everybody else does it by checking all of the cases, so why not me, too?
|
arg := Flat(arg);
|
||||||
# Is there a better way?
|
else
|
||||||
local n,i,j,k;
|
arg := Flat(arg);
|
||||||
n := Length(T);
|
fam := FamilyObj(arg);
|
||||||
for i in [1..n] do for j in [1..n] do for k in [1..n] do
|
fi;
|
||||||
if T[i, T[j,k]] <> T[T[i,j], T[i,k]] then return false; fi;
|
return CloneOfTypeByGenerators(IsRightQuandle, fam, arg,
|
||||||
od; od; od;
|
GeneratorsOfRightQuasigroup,
|
||||||
return true;
|
RightQuandleByMultiplicationTableNC);
|
||||||
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));
|
|
||||||
end);
|
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
|
## View and print and such
|
||||||
LeftObjString@ := function(Q)
|
LeftObjString@ := function(Q)
|
||||||
# Don't test distributivity if we haven't already
|
# 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";
|
return "LeftQuasigroup";
|
||||||
end;
|
end;
|
||||||
|
|
||||||
RightObjString@ := function(Q)
|
RightObjString@ := function(Q)
|
||||||
# Don't test distributivity if we haven't already
|
# 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";
|
return "RightQuasigroup";
|
||||||
end;
|
end;
|
||||||
|
|
||||||
|
@ -324,12 +213,22 @@ InstallMethod(Display, "for a right quasigroup with multiplication table",
|
||||||
end);
|
end);
|
||||||
|
|
||||||
LeftObjView@ := function(Q)
|
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";
|
return "<left quasigroup";
|
||||||
end;
|
end;
|
||||||
|
|
||||||
RightObjView@ := function(Q)
|
RightObjView@ := function(Q)
|
||||||
|
# Don't test distributivity if we haven't already
|
||||||
if HasIsRSelfDistributive(Q) and IsRightRack(Q) then
|
if HasIsRSelfDistributive(Q) and IsRightRack(Q) then
|
||||||
|
if HasIsElementwiseIdempotent(Q) and IsElementwiseIdempotent(Q) then
|
||||||
|
return "<right quandle";
|
||||||
|
fi;
|
||||||
return "<right rack";
|
return "<right rack";
|
||||||
fi;
|
fi;
|
||||||
return "<right quasigroup";
|
return "<right quasigroup";
|
||||||
|
@ -355,54 +254,3 @@ InstallMethod(ViewString, "for a right quasigroup with generators",
|
||||||
String(Size(GeneratorsOfRightQuasigroup(Q))),
|
String(Size(GeneratorsOfRightQuasigroup(Q))),
|
||||||
" generators>"));
|
" 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");
|
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