add direct prodcts
This commit is contained in:
parent
890e943901
commit
4b723e17f6
@ -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);
|
||||
|
117
gap/structure.gi
117
gap/structure.gi
@ -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);
|
||||
|
Loading…
Reference in New Issue
Block a user