Skip to content

Commit

Permalink
semitrans: improve direct products
Browse files Browse the repository at this point in the history
  • Loading branch information
wilfwilson committed Jul 14, 2017
1 parent 9ee35e5 commit fe6c5c7
Show file tree
Hide file tree
Showing 2 changed files with 75 additions and 30 deletions.
2 changes: 1 addition & 1 deletion doc/properties.xml
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ gap> R := RectangularBand(3, 2);
<regular transformation semigroup of size 6, degree 6 with 3
generators>
gap> S := DirectProduct(G, R);
<transformation semigroup of size 47520, degree 17 with 5 generators>
<transformation semigroup of size 47520, degree 17 with 9 generators>
gap> IsRectangularGroup(R);
true
gap> IsRectangularGroup(G);
Expand Down
103 changes: 74 additions & 29 deletions gap/semigroups/semitrans.gi
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
#############################################################################
##
#W semitrans.gi
#Y Copyright (C) 2013-15 James D. Mitchell
#Y Copyright (C) 2013-17 James D. Mitchell
##
## Licensing information can be found in the README file of this package.
##
Expand Down Expand Up @@ -123,7 +123,8 @@ end);
InstallMethod(DirectProductOp, "for a list and a transformation semigroup",
[IsList, IsTransformationSemigroup],
function(list, S)
local target, D, dfs;
local out, nrfactors, allgens, degs, offset, pre_multipliers, pos_multipliers,
indecomposable, gens, word, w, elts, product, iter, i, x, choice;

# Check the arguments.
if IsEmpty(list) then
Expand All @@ -135,35 +136,79 @@ function(list, S)
TryNextMethod();
fi;

target := Product(list, Size);
D := fail;

dfs := function(image, deg, depth)
local x, n, next;
if D <> fail and Size(D) = target then
return;
elif depth = Length(list) then
x := Transformation(image);
if D = fail then
D := Semigroup(x);
elif not x in D then
D := ClosureSemigroup(D, x);
fi;
return;
fi;
depth := depth + 1;
n := DegreeOfTransformationSemigroup(list[depth]);
for x in list[depth] do
next := Concatenation(image, ImageListOfTransformation(x, n) + deg);
dfs(next, n + deg, depth);
if Size(D) = target then
return;
out := [];

nrfactors := Length(list);

allgens := List(list, x -> Unique(GeneratorsOfSemigroup(x)));
degs := List(list, DegreeOfTransformationSemigroup);

offset := EmptyPlist(nrfactors);
offset[1] := 0;
for i in [2 .. nrfactors] do
offset[i] := offset[i - 1] + degs[i - 1];
od;

pre_multipliers := List([1 .. nrfactors], x -> []);
pos_multipliers := List([1 .. nrfactors], x -> []);
indecomposable := List([1 .. nrfactors], x -> []);
gens := List([1 .. nrfactors], x -> []);

# Work out pre- and post-multipliers
for i in [1 .. nrfactors] do
for x in allgens[i] do
word := NonTrivialFactorization(list[i], x);
if word = fail then
# This generator has to appear with every other
w := ImageListOfTransformation(x, degs[i]) + offset[i];
Add(indecomposable[i], w);
else
if i > 1 then
w := EvaluateWord(allgens[i], word{[1 .. Length(word) - 1]});
w := ImageListOfTransformation(w, degs[i]) + offset[i];
AddSet(pre_multipliers[i], w);
fi;
if i < nrfactors then
w := EvaluateWord(allgens[i], word{[2 .. Length(word)]});
w := ImageListOfTransformation(w, degs[i]) + offset[i];
AddSet(pos_multipliers[i], w);
fi;
Add(gens[i], ImageListOfTransformation(x, degs[i]) + offset[i]);
fi;
od;
return;
end;
dfs([], 0, 0);
return D;
od;

if ForAny(indecomposable, x -> not IsEmpty(x)) then
elts := EmptyPlist(nrfactors);
for i in [1 .. nrfactors] do
elts[i] := List(Elements(list[i]),
x -> ImageListOfTransformation(x, degs[i]) + offset[i]);
od;
for i in Filtered([1 .. nrfactors], x -> not IsEmpty(indecomposable[x])) do
product := Concatenation(elts{[1 .. i - 1]},
indecomposable{[i]},
elts{[i + 1 .. nrfactors]});
iter := IteratorOfCartesianProduct(product);
for choice in iter do
# These generators are irredundant
AddSet(out, Transformation(Concatenation(choice)));
od;
od;
fi;

if not ForAny(gens, IsEmpty) then
for i in [1 .. nrfactors] do
product := Concatenation(pos_multipliers{[1 .. i - 1]},
gens{[i]},
pre_multipliers{[i + 1 .. nrfactors]});
iter := IteratorOfCartesianProduct(product);
for choice in iter do
AddSet(out, Transformation(Concatenation(choice)));
od;
od;
fi;

return Semigroup(out);
end);

InstallMethod(IsConnectedTransformationSemigroup,
Expand Down

0 comments on commit fe6c5c7

Please sign in to comment.