2017-10-18 10:46:13 +00:00
|
|
|
## structure.gi RAQ Implementation of definitiions, reps, and elt operations
|
|
|
|
|
2017-10-20 13:25:22 +00:00
|
|
|
## Testing properties of collections the hard way if we have to
|
|
|
|
|
|
|
|
InstallMethod(IsElementwiseIdempotent, "for finite collections",
|
|
|
|
[IsMultiplicativeElementCollection and IsFinite],
|
|
|
|
M -> ForAll(Elements(M), m->IsIdempotent(m))
|
|
|
|
);
|
|
|
|
|
|
|
|
InstallMethod(IsLSelfDistributive,
|
|
|
|
"for arbitrary multiplicative collections, the hard way",
|
|
|
|
[IsMultiplicativeElementCollection],
|
|
|
|
function (C)
|
|
|
|
local a,b,d;
|
|
|
|
for a in C do for b in C do for d in C do
|
|
|
|
if d*(a*b) <> (d*a)*(d*b) then return false; fi;
|
|
|
|
od; od; od;
|
|
|
|
return true;
|
|
|
|
end);
|
|
|
|
|
|
|
|
InstallMethod(IsRSelfDistributive,
|
|
|
|
"for arbitrary multiplicative collections, the hard way",
|
|
|
|
[IsMultiplicativeElementCollection],
|
|
|
|
function (C)
|
|
|
|
local a,b,d;
|
|
|
|
for a in C do for b in C do for d in C do
|
|
|
|
if (a*b)*d <> (a*d)*(b*d) then return false; fi;
|
|
|
|
od; od; od;
|
|
|
|
return true;
|
|
|
|
end);
|
|
|
|
|
2017-10-18 10:46:13 +00:00
|
|
|
## Create structures with generators
|
2017-10-20 13:25:22 +00:00
|
|
|
|
2017-10-18 11:19:57 +00:00
|
|
|
InstallGlobalFunction(CloneOfTypeByGenerators,
|
2017-10-18 20:00:02 +00:00
|
|
|
function(cat, fam, gens, genAttrib, tableCstr)
|
2017-10-18 10:46:13 +00:00
|
|
|
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));
|
2017-10-18 19:37:48 +00:00
|
|
|
SetConstructorFromTable(M, tableCstr);
|
2017-10-18 10:46:13 +00:00
|
|
|
return M;
|
|
|
|
end);
|
|
|
|
|
2017-10-20 13:25:22 +00:00
|
|
|
## Helpers for the constructors below:
|
|
|
|
|
|
|
|
ArgHelper@ := function(parmlist)
|
|
|
|
# returns a list of the family and the flat list of elements of parmlist
|
|
|
|
if Length(parmlist) = 0 then
|
|
|
|
Error("usage: RAQ constructors take an optional family, followed by gens");
|
|
|
|
fi;
|
|
|
|
if IsFamily(parmlist[1]) then return [Remove(parmlist,1), Flat(parmlist)]; fi;
|
|
|
|
parmlist := Flat(parmlist);
|
|
|
|
return [FamilyObj(parmlist), parmlist];
|
|
|
|
end;
|
|
|
|
|
|
|
|
CheckLQGprop@ := function(gens)
|
|
|
|
local g, h;
|
|
|
|
# Make sure all elements in gens have left quotient property pairwise
|
|
|
|
for g in gens do for h in gens do
|
|
|
|
if g*LeftQuotient(g,h) <> h or LeftQuotient(g,g*h) <> h then
|
|
|
|
Error("left quasigroup property of left quotients violated");
|
|
|
|
fi;
|
|
|
|
od; od;
|
|
|
|
return;
|
|
|
|
end;
|
|
|
|
|
|
|
|
CheckRQGprop@ := function(gens)
|
|
|
|
local g, h;
|
|
|
|
# Make sure all elements in gens have right quotient property pairwise
|
|
|
|
for g in gens do for h in gens do
|
|
|
|
if (h*g)/g <> h or (h/g)*g <> h then
|
|
|
|
Error("right quasigroup property of / violated");
|
|
|
|
fi;
|
|
|
|
od; od;
|
|
|
|
return;
|
|
|
|
end;
|
|
|
|
|
2017-10-18 10:46:13 +00:00
|
|
|
## Functions for each of the magma categories here
|
|
|
|
InstallGlobalFunction(LeftQuasigroup, function(arg)
|
2017-10-20 13:25:22 +00:00
|
|
|
arg := ArgHelper@(arg);
|
|
|
|
CheckLQGprop@(arg[2]);
|
|
|
|
return LeftQuasigroupNC(arg[1], arg[2]);
|
|
|
|
end);
|
|
|
|
|
|
|
|
InstallGlobalFunction(LeftQuasigroupNC, function(fam, gens)
|
|
|
|
return CloneOfTypeByGenerators(IsLeftQuasigroup, fam, gens,
|
2017-10-18 19:37:48 +00:00
|
|
|
GeneratorsOfLeftQuasigroup,
|
2017-10-19 00:26:18 +00:00
|
|
|
LeftQuasigroupByMultiplicationTableNC);
|
2017-10-18 10:46:13 +00:00
|
|
|
end);
|
|
|
|
|
|
|
|
InstallGlobalFunction(LeftRack, function(arg)
|
2017-10-20 13:25:22 +00:00
|
|
|
arg := ArgHelper@(arg);
|
|
|
|
CheckLQGprop@(arg[2]);
|
|
|
|
if not IsLSelfDistributive(arg[2]) then
|
|
|
|
Error("Left rack must have left distributive generators");
|
2017-10-18 10:46:13 +00:00
|
|
|
fi;
|
2017-10-20 13:25:22 +00:00
|
|
|
return LeftRackNC(arg[1], arg[2]);
|
|
|
|
end);
|
|
|
|
|
2017-10-20 13:28:01 +00:00
|
|
|
InstallGlobalFunction(LeftRackNC, function(fam, gens)
|
2017-10-20 13:25:22 +00:00
|
|
|
return CloneOfTypeByGenerators(IsLeftRack, fam, gens,
|
2017-10-18 19:37:48 +00:00
|
|
|
GeneratorsOfLeftQuasigroup,
|
|
|
|
LeftRackByMultiplicationTableNC);
|
2017-10-18 10:46:13 +00:00
|
|
|
end);
|
|
|
|
|
2017-10-20 09:08:09 +00:00
|
|
|
InstallGlobalFunction(LeftQuandle, function(arg)
|
2017-10-20 13:25:22 +00:00
|
|
|
arg := ArgHelper@(arg);
|
|
|
|
CheckLQGprop@(arg[2]);
|
|
|
|
if not IsLSelfDistributive(arg[2]) then
|
|
|
|
Error("Left quandle must have left distributive generators");
|
2017-10-20 09:08:09 +00:00
|
|
|
fi;
|
2017-10-20 13:25:22 +00:00
|
|
|
if not IsElementwiseIdempotent(arg[2]) then
|
|
|
|
Error("Quandles must contain only idempotent elements");
|
2017-10-20 09:08:09 +00:00
|
|
|
fi;
|
2017-10-20 13:25:22 +00:00
|
|
|
return LeftQuandleNC(arg[1], arg[2]);
|
|
|
|
end);
|
|
|
|
|
|
|
|
InstallGlobalFunction(LeftQuandleNC, function(fam, gens)
|
|
|
|
return CloneOfTypeByGenerators(IsLeftQuandle, fam, gens,
|
2017-10-20 09:08:09 +00:00
|
|
|
GeneratorsOfLeftQuasigroup,
|
|
|
|
LeftQuandleByMultiplicationTableNC);
|
|
|
|
end);
|
|
|
|
|
2017-10-18 10:46:13 +00:00
|
|
|
InstallGlobalFunction(RightQuasigroup, function(arg)
|
2017-10-20 13:25:22 +00:00
|
|
|
arg := ArgHelper@(arg);
|
|
|
|
CheckRQGprop@(arg[2]);
|
|
|
|
return RightQuasigroupNC(arg[1], arg[2]);
|
|
|
|
end);
|
|
|
|
|
|
|
|
InstallGlobalFunction(RightQuasigroupNC, function(fam, gens)
|
|
|
|
return CloneOfTypeByGenerators(IsRightQuasigroup, fam, gens,
|
|
|
|
GeneratorsOfRightQuasigroup,
|
2017-10-19 00:26:18 +00:00
|
|
|
RightQuasigroupByMultiplicationTableNC);
|
2017-10-18 10:46:13 +00:00
|
|
|
end);
|
|
|
|
|
|
|
|
InstallGlobalFunction(RightRack, function(arg)
|
2017-10-20 13:25:22 +00:00
|
|
|
arg := ArgHelper@(arg);
|
|
|
|
CheckRQGprop@(arg[2]);
|
|
|
|
if not IsRSelfDistributive(arg[2]) then
|
|
|
|
Error("Right rack must have right distributive generators");
|
2017-10-18 10:46:13 +00:00
|
|
|
fi;
|
2017-10-20 13:25:22 +00:00
|
|
|
return RightRackNC(arg[1], arg[2]);
|
|
|
|
end);
|
|
|
|
|
2017-10-20 13:28:01 +00:00
|
|
|
InstallGlobalFunction(RightRackNC, function(fam, gens)
|
2017-10-20 13:25:22 +00:00
|
|
|
return CloneOfTypeByGenerators(IsRightRack, fam, gens,
|
2017-10-18 19:37:48 +00:00
|
|
|
GeneratorsOfRightQuasigroup,
|
|
|
|
RightRackByMultiplicationTableNC);
|
2017-10-18 10:46:13 +00:00
|
|
|
end);
|
|
|
|
|
2017-10-20 09:08:09 +00:00
|
|
|
InstallGlobalFunction(RightQuandle, function(arg)
|
2017-10-20 13:25:22 +00:00
|
|
|
arg := ArgHelper@(arg);
|
|
|
|
CheckLQGprop@(arg[2]);
|
|
|
|
if not IsRSelfDistributive(arg[2]) then
|
|
|
|
Error("Right quandle must have right distributive generators");
|
2017-10-20 09:08:09 +00:00
|
|
|
fi;
|
2017-10-20 13:25:22 +00:00
|
|
|
if not IsElementwiseIdempotent(arg[2]) then
|
|
|
|
Error("Quandles must contain only idempotent elements");
|
2017-10-20 09:08:09 +00:00
|
|
|
fi;
|
2017-10-20 13:25:22 +00:00
|
|
|
return RightQuandleNC(arg[1], arg[2]);
|
|
|
|
end);
|
|
|
|
|
|
|
|
InstallGlobalFunction(RightQuandleNC, function(fam, gens)
|
|
|
|
return CloneOfTypeByGenerators(IsRightQuandle, fam, gens,
|
2017-10-20 09:08:09 +00:00
|
|
|
GeneratorsOfRightQuasigroup,
|
|
|
|
RightQuandleByMultiplicationTableNC);
|
2017-10-18 19:37:48 +00:00
|
|
|
end);
|
2017-10-18 19:55:52 +00:00
|
|
|
|
2017-10-18 23:12:31 +00:00
|
|
|
## View and print and such
|
|
|
|
LeftObjString@ := function(Q)
|
2017-10-19 00:38:07 +00:00
|
|
|
# Don't test distributivity if we haven't already
|
2017-10-20 09:08:09 +00:00
|
|
|
if HasIsLSelfDistributive(Q) and IsLeftRack(Q) then
|
|
|
|
if HasIsElementwiseIdempotent(Q) and IsElementwiseIdempotent(Q) then
|
|
|
|
return "LeftQuandle";
|
|
|
|
fi;
|
|
|
|
return "LeftRack";
|
|
|
|
fi;
|
2017-10-18 23:12:31 +00:00
|
|
|
return "LeftQuasigroup";
|
|
|
|
end;
|
2017-10-20 09:08:09 +00:00
|
|
|
|
2017-10-18 23:12:31 +00:00
|
|
|
RightObjString@ := function(Q)
|
2017-10-19 00:38:07 +00:00
|
|
|
# Don't test distributivity if we haven't already
|
2017-10-20 09:08:09 +00:00
|
|
|
if HasIsRSelfDistributive(Q) and IsRightRack(Q) then
|
|
|
|
if HasIsElementwiseIdempotent(Q) and IsElementwiseIdempotent(Q) then
|
|
|
|
return "RightQuandle";
|
|
|
|
fi;
|
|
|
|
return "RightRack";
|
|
|
|
fi;
|
2017-10-18 23:12:31 +00:00
|
|
|
return "RightQuasigroup";
|
|
|
|
end;
|
|
|
|
|
|
|
|
InstallMethod(String, "for a left quasigroup",
|
|
|
|
[IsLeftQuasigroup],
|
2017-10-18 23:22:48 +00:00
|
|
|
Q -> Concatenation(LeftObjString@(Q), "(...)"));
|
2017-10-18 23:12:31 +00:00
|
|
|
|
|
|
|
InstallMethod(String, "for a left quasigroup with generators",
|
|
|
|
[IsLeftQuasigroup and HasGeneratorsOfLeftQuasigroup],
|
|
|
|
Q -> Concatenation(LeftObjString@(Q), "( ",
|
|
|
|
String(GeneratorsOfLeftQuasigroup(Q)), " )"));
|
|
|
|
|
|
|
|
InstallMethod(String, "for a left quasigroup with multiplication table",
|
|
|
|
[IsLeftQuasigroup and HasMultiplicationTable],
|
|
|
|
Q -> Concatenation(LeftObjString@(Q),
|
|
|
|
"ByMultiplicationTableNC( ",
|
|
|
|
String(MultiplicationTable(Q)), " )"));
|
|
|
|
|
|
|
|
InstallMethod(String, "for a right quasigroup",
|
|
|
|
[IsRightQuasigroup],
|
2017-10-18 23:22:48 +00:00
|
|
|
Q -> Concatenation(RightObjString@(Q), "(...)"));
|
2017-10-18 23:12:31 +00:00
|
|
|
|
|
|
|
InstallMethod(String, "for a right quasigroup with generators",
|
|
|
|
[IsRightQuasigroup and HasGeneratorsOfRightQuasigroup],
|
|
|
|
Q -> Concatenation(RightObjString@(Q), "( ",
|
|
|
|
String(GeneratorsOfRightQuasigroup(Q)), " )"));
|
|
|
|
|
|
|
|
InstallMethod(String, "for a right quasigroup with multiplication table",
|
|
|
|
[IsRightQuasigroup and HasMultiplicationTable],
|
|
|
|
Q -> Concatenation(RightObjString@(Q),
|
|
|
|
"ByMultiplicationTableNC( ",
|
|
|
|
String(MultiplicationTable(Q)), " )"));
|
|
|
|
|
2017-10-18 23:49:29 +00:00
|
|
|
InstallMethod(PrintString, "for a left quasigroup",
|
|
|
|
[IsLeftQuasigroup], Q -> String(Q));
|
|
|
|
|
|
|
|
InstallMethod(PrintString, "for a right quasigroup",
|
|
|
|
[IsRightQuasigroup], Q -> String(Q));
|
|
|
|
|
2017-10-18 23:30:57 +00:00
|
|
|
InstallMethod(DisplayString, "for a left quasigroup",
|
|
|
|
[IsLeftQuasigroup], Q -> String(Q));
|
|
|
|
|
2017-10-18 23:49:29 +00:00
|
|
|
InstallMethod(DisplayString, "for a right quasigroup",
|
2017-10-18 23:30:57 +00:00
|
|
|
[IsRightQuasigroup], Q -> String(Q));
|
2017-10-18 23:12:31 +00:00
|
|
|
|
|
|
|
InstallMethod(Display, "for a left quasigroup with multiplication table",
|
|
|
|
[IsLeftQuasigroup and HasMultiplicationTable],
|
|
|
|
function(Q)
|
2017-10-18 23:35:13 +00:00
|
|
|
Print(LeftObjString@(Q), " with ", Size(Q),
|
2017-10-18 23:12:31 +00:00
|
|
|
" elements, generated by ",
|
|
|
|
GeneratorsOfLeftQuasigroup(Q), ", with table\n");
|
|
|
|
Display(MultiplicationTable(Q));
|
|
|
|
end);
|
|
|
|
|
|
|
|
InstallMethod(Display, "for a right quasigroup with multiplication table",
|
|
|
|
[IsRightQuasigroup and HasMultiplicationTable],
|
|
|
|
function(Q)
|
2017-10-18 23:35:13 +00:00
|
|
|
Print(RightObjString@(Q), " with ", Size(Q),
|
2017-10-18 23:12:31 +00:00
|
|
|
" elements, generated by ",
|
|
|
|
GeneratorsOfRightQuasigroup(Q), ", with table\n");
|
|
|
|
Display(MultiplicationTable(Q));
|
|
|
|
end);
|
|
|
|
|
|
|
|
LeftObjView@ := function(Q)
|
2017-10-20 09:08:09 +00:00
|
|
|
# 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;
|
2017-10-18 23:12:31 +00:00
|
|
|
return "<left quasigroup";
|
|
|
|
end;
|
2017-10-20 09:08:09 +00:00
|
|
|
|
2017-10-18 23:12:31 +00:00
|
|
|
RightObjView@ := function(Q)
|
2017-10-20 09:08:09 +00:00
|
|
|
# Don't test distributivity if we haven't already
|
2017-10-19 00:40:48 +00:00
|
|
|
if HasIsRSelfDistributive(Q) and IsRightRack(Q) then
|
2017-10-20 09:08:09 +00:00
|
|
|
if HasIsElementwiseIdempotent(Q) and IsElementwiseIdempotent(Q) then
|
|
|
|
return "<right quandle";
|
|
|
|
fi;
|
2017-10-19 00:40:48 +00:00
|
|
|
return "<right rack";
|
|
|
|
fi;
|
2017-10-18 23:12:31 +00:00
|
|
|
return "<right quasigroup";
|
|
|
|
end;
|
|
|
|
|
|
|
|
InstallMethod(ViewString, "for a left quasigroup",
|
|
|
|
[IsLeftQuasigroup],
|
2017-10-18 23:37:07 +00:00
|
|
|
Q -> Concatenation(LeftObjView@(Q), ">"));
|
2017-10-18 23:12:31 +00:00
|
|
|
|
|
|
|
InstallMethod(ViewString, "for a left quasigroup with generators",
|
|
|
|
[IsLeftQuasigroup and HasGeneratorsOfLeftQuasigroup],
|
|
|
|
Q -> Concatenation(LeftObjView@(Q), " with ",
|
2017-10-18 23:39:48 +00:00
|
|
|
String(Size(GeneratorsOfLeftQuasigroup(Q))),
|
2017-10-18 23:12:31 +00:00
|
|
|
" generators>"));
|
|
|
|
|
|
|
|
InstallMethod(ViewString, "for a right quasigroup",
|
|
|
|
[IsRightQuasigroup],
|
2017-10-18 23:37:07 +00:00
|
|
|
Q -> Concatenation(RightObjView@(Q), ">"));
|
2017-10-18 23:12:31 +00:00
|
|
|
|
|
|
|
InstallMethod(ViewString, "for a right quasigroup with generators",
|
|
|
|
[IsRightQuasigroup and HasGeneratorsOfRightQuasigroup],
|
|
|
|
Q -> Concatenation(RightObjView@(Q), " with ",
|
2017-10-18 23:39:48 +00:00
|
|
|
String(Size(GeneratorsOfRightQuasigroup(Q))),
|
2017-10-18 23:12:31 +00:00
|
|
|
" generators>"));
|
|
|
|
|