add direct prodcts

This commit is contained in:
Glen Whitney 2017-10-25 16:18:35 +02:00
parent 890e943901
commit 4b723e17f6
2 changed files with 176 additions and 0 deletions

View File

@ -394,3 +394,62 @@ InstallMethod(Opposite, "for right rack",
[ IsRightRack and IsBuiltFromMultiplicationTable],
L -> LeftRackByMultiplicationTableNC(TransposedMat(MultiplicationTable(L)))
);
# Note that opposite of quandles seems to come for free from above, which is
# good.
## Direct products
# As in the case of general one-sided quasigroups, this implementation should
# only be called with a second-argument collection which is not a group or
# quasigroup.
InstallOtherMethod(DirectProductOp,
"for a list and non-quasigroup magma built form multiplication table",
[IsList, IsMagma and IsBuiltFromMultiplicationTable],
function (list, first)
local item, i, jof, bigtable;
# Simple checks
if IsEmpty(list) then
Error("Usage: Cannot take DirectProduct of zero items.");
elif Length(list) = 1 then
return list[1];
fi;
# See if we can handle all objects
for i in [2..Length(list)] do
if not HasMultiplicationTable(list(i)) then
return DirectProductOp(Permuted(list, (1,i)), list[i]);
fi;
od;
# OK, safe to take everyone's multiplication table.
# So go ahead and make the big thing
bigtable := ProductTableOfCanonicalCayleyTables(
List(list, MultiplicationTable));
# But we have to figure out what to do with it.
jof := RoughJoinOfFilters@(list, first);
# Dispatch modeled after the general one
if "IsMagmaWithOne" in jof then
if "IsMonoid" in jof then
return MonoidByMultiplicationTable(bigtable);
fi;
return MagmaWithOneByMultiplicationTable(bigtable);
fi;
if "IsAssociative" in jof then
return SemigroupByMultiplicationTable(bigtable);
elif "IsLeftQuasigroup" in jof then
if "IsLSelfDistributive" in jof then
if "IsElementwiseIdempotent" in jof then
return LeftQuandleByMultiplicationTableNC(bigtable);
fi;
return LeftRackByMultiplicationTableNC(bigtable);
fi;
return LeftQuandleByMultiplicationTableNC(bigtable);
elif "IsRightQuasigroup" in jof then
if "IsLSelfDistributive" in jof then
if "IsElementwiseIdempotent" in jof then
return RightQuandleByMultiplicationTableNC(bigtable);
fi;
return RightRackByMultiplicationTableNC(bigtable);
fi;
return RightQuandleByMultiplicationTableNC(bigtable);
fi;
return MagmaByMultiplicationTable(bigtable);
end);

View File

@ -503,3 +503,120 @@ InstallMethod(Opposite, "for a right quandle",
Q -> OppHelper@(Q, GeneratorsOfRightQuasigroup, LeftQuandleNC)
);
# Direct Products
# We actually try to handle here the general cases that are not otherwise
# handled by the groups functions in GAP as a whole, or the LOOPS package
# Helper for roughly creating the join of the filters of a bunch of objects.
FiltersOfObj@ := function(obj)
local f;
f := CategoriesOfObject(obj);
Append(f,KnownTruePropertiesOfObject(obj));
Append(f,List(KnownAttributesOfObject(obj), x -> Concatenate("Has", x)));
return f;
end;
# From the implementation of DirectProductOp for groups and quasigroups, the
# below will only be called with a second-argument collection which is not a
# group or quasigroup.
# This is a helper that creates a rough join of the filters of a list of
# objects, using the same arguments as directproduct op (the redundant "first"
# argument, which is handy for seeding the filter list)
RoughJoinOfFilters@ := function(list, first);
local item, jof;
jof := Set(FiltersOfObj@(first));
for item in list{[2..Length(list)]} do
IntersectSet(jof, FiltersOfObj@);
od;
end;
InstallOtherMethod(DirectProductOp, "for a list and non-quasigroup magma",
[IsList, IsMagma],
function (list, first)
local item, i, jof, ids, gens, g, current, genfunc, genlists;
# Simple checks
if IsEmpty(list) then
Error("Usage: Cannot take DirectProduct of zero items.");
elif Length(list) = 1 then
return list[1];
fi;
jof := RoughJoinOfFilters(list, first);
# The dispatch below is somewhat ad-hoc, but covers the major existing cases
# First, if we don't have generators for all of the items, we're kinda out
# of luck here:
if not ForAny(jof, nm -> StartsWith(nm,"HasGenerators")) then
TryNextMethod();
fi;
# Next, if anything is not even a magma, recommend cartesian product
if not "IsMagma" in jof then
Info(InfoRAQ, 1, "Try Cartesian() for products of collections.");
TryNextMethod();
fi;
# The primary division now is between entities with identities, for which
# the product will have a smaller generating set, and those which do
# not, for which the generators is the full cartesian product of generators.
if "IsMagmaWithOne" in jof then
# Code basically copied from DirectProductOp() for general groups;
# would be better if this could be moved into the GAP core
ids := List(list, One);
gens := [];
for i in [1..Length(list)] do
for g in GeneratorsOfMagmaWithOne(list[i]) do
current := ShallowCopy(ids);
current[i] = g;
Add(gens, DirectProductElement(current));
od;
od;
# Now, we want the most specific structure we know about here.
# Only aware of MagmaWithOne and Monoid, as direct products of
# loops are already covered by the LOOPS package:
if "IsMonoid" in jof then
return MonoidByGenerators(gens);
fi;
return MagmaWithOneByGenerators(gens);
fi;
# OK, here we know not all structures have inverses. Therefore, we must
# resort to the full cartesian product of generators.
# But we need to figure out what function to use to obtain the generators.
if "HasGeneratorsOfLeftQuasigroup" in jof then
genfunc := GeneratorsOfLeftQuasigroup;
elif "HasGeneratorsOfRightQuasigroup" in jof then
genfunc := GeneratorsOfRightQuasigroup;
elif "HasGeneratorsOfMagma" in jof then
genfunc := GeneratorsOfMagma;
else
Info(InfoRAQ,1, "RAQ: Unusual product, each of ", list,
" has generators, but not sure what kind; trying next method.");
TryNextMethod();
fi;
genlists := List(list, genfunc);
gens := Cartesian(genlists);
Apply(gens, DirectProductElement);
# Again, we need to figure out what sort of structure we might have
if "IsAssociative" in jof then
return SemigroupByGenerators(gens);
elif "IsLeftQuasigroup" in jof then
if "IsLSelfDistributive" in jof then
if "IsElementwiseIdempotent" in jof then
return LeftQuandleNC(gens);
fi;
return LeftRackNC(gens);
fi;
return LeftQuasigroupNC(gens);
elif "IsRightQuasigroup" in jof then
if "IsRSelfDistributive" in jof then
if "IsElementwiseIdempotent" in jof then
return RightQuandleNC(gens);
fi;
return RightRackNC(gens);
fi;
return RightQuasigroupNC(gens);
fi;
# Not seeing any additional structure; did I miss anything?
return MagmaByGenerators(gens);
end);