Skip to content

Commit

Permalink
Add some more comments, rename some local variables
Browse files Browse the repository at this point in the history
  • Loading branch information
fingolfin committed Jun 2, 2022
1 parent 879672c commit b953e0a
Showing 1 changed file with 71 additions and 50 deletions.
121 changes: 71 additions & 50 deletions lib/csetperm.gi
Original file line number Diff line number Diff line change
Expand Up @@ -555,104 +555,123 @@ InstallMethod(Intersection2, "perm cosets", IsIdenticalObj,
[IsRightCoset and IsPermCollection,IsRightCoset and IsPermCollection],0,
function(cos1,cos2)
local H1, H2, x1, x2, shift, sigma, listMoved_H1, listMoved_H2,
listMoved_H12, listMoved_sigma, U, set2, set1, eRepr,
set2_img, set1_img, H1_sigma, H2_sigma, test, H12, swap,
eCos, rho, diff12, diff21, fset1, fset2;
# We set cosInt = cos1 cap cos2 = H1 x1 cap H2 x2
listMoved_sigma, U, repr, H1_sigma, H2_sigma, H12, swap, rho, diff;
# We set cosInt = cos1 \cap cos2 = H1 x1 \cap H2 x2
H1:=ActingDomain(cos1);
H2:=ActingDomain(cos2);
x1:=Representative(cos1);
x2:=Representative(cos2);
if H1=H2 then
if cos1=cos2 then
return cos1;
else
return [];
fi;
fi;
x1:=Representative(cos1);
x2:=Representative(cos2);
# We are using that
# H1*x1 \cap H2*x2 = (H1 \cap H2*x2/x1)*x1 = (H1 \cap H2*sigma)*shift,
# where shift and sigma are defined as below:
shift:=x1;
sigma:=x2 / x1;
# Reducing as much as possible in advance

# Reducing as much as possible in advance by using various relatively
# cheap to compute criteria
while true do
listMoved_H1:=MovedPoints(H1);
listMoved_H2:=MovedPoints(H2);
listMoved_H12:=Union(listMoved_H1, listMoved_H2);
listMoved_sigma:=MovedPoints(sigma);

# If the coset intersection is non-empty, then there is h1 \in H1
# and h2 \in H2 such that h1 = h2*sigma, in other words, sigma
# is contained in the group H12 generated by H1 and H2. A necessary
# condition for this is that the points moved by sigma are a subset
# of the points moved by H12.
if not IsSubset(listMoved_H12, listMoved_sigma) then
# If the coset intersection is non-empty, then there is h1 \in H1 and
# h2 \in H2 such that h1 = h2*sigma. Therefore sigma is contained in
# the group generated by H1 and H2. A necessary condition for this is
# that the points moved by sigma are a subset of the points moved by
# H1 and H2.
if not IsSubset(Union(listMoved_H1, listMoved_H2), listMoved_sigma) then
return [];
fi;

# Suppose x is an element of the intersection of the two cosets. Then for
# any positive integer n, we know that n^x is contained in n^H1 but
# also in (n^H2)^\sigma. Thus if the intersection of n^H1 and
# (n^H2)^\sigma is empty, then the intersection of the cosets is also
# empty. Clearly the orbit intersection contains n whenever n is fixed
# by sigma, so we only have to consider this for n moved by sigma.
# Suppose x is an element of H1 \cap H2*sigma. Then for any positive
# integer n, we know that n^x is contained in n^H1 but also in
# (n^H2)^\sigma. Thus if the intersection of n^H1 and (n^H2)^\sigma is
# empty, then the intersection of the cosets is also empty. Clearly
# the orbit intersection contains n whenever n is fixed by sigma, so
# we only have to consider this for n moved by sigma.
if ForAny(listMoved_sigma, n -> IsEmpty(Intersection(Orbit(H1,n), OnTuples(Orbit(H2,n),sigma)))) then
return [];
fi;

# Easy reductions: points that are moved by sigma outside of one group allow us to reduce the problem
diff12:=Difference(listMoved_H1, listMoved_H2);
diff21:=Difference(listMoved_H2, listMoved_H1);
set2:=Intersection(diff21, listMoved_sigma);
if Length(set2) > 0 then
set2_img:=OnTuples(set2, Inverse(sigma));
eRepr:=RepresentativeAction(H2, set2, set2_img, OnTuples);
if eRepr=fail then
# If there are points that are moved by sigma and by H2 but not by H1,
# then there must be an element in H2 which matches the action of sigma
# on these points, or else the intersection is empty
diff:=Difference(Intersection(listMoved_H2, listMoved_sigma), listMoved_H1);
if Length(diff) > 0 then
repr:=RepresentativeAction(H2, diff, OnTuples(diff, Inverse(sigma)), OnTuples);
if repr=fail then
return [];
fi;
sigma:=eRepr * sigma;
H2:=Stabilizer(H2, set2, OnTuples);
# Since repr is in H2, we can replace sigma by repr*sigma
# without changing the coset H2*sigma. The new sigma then fixes
# all points in diff, as does H1. Hence replacing H2 by the
# stabilizer in H2 of diff does not change H1 \cap H2 sigma.
sigma:=repr * sigma;
H2:=Stabilizer(H2, diff, OnTuples);
continue;
fi;
set1:=Intersection(diff12, listMoved_sigma);
if Length(set1) > 0 then
# cosInt = (H1 \cap H2 sigma) shift
# = (H1 sigma^{-1} \cap H2) sigma shift
# = (stab(H1) repr sigma^{-1} \cap H2) sigma shift
# = (stab(H1) \cap H2 sigma repr^{-1} ) repr shift
set1_img:=OnTuples(set1, sigma);
eRepr:=RepresentativeAction(H1, set1, set1_img, OnTuples);
if eRepr=fail then

# Mirror to the previous check:
# If there are points that are moved by sigma and by H1 but not by H2,
# then there must be an element in H1 which matches the action of sigma
# on these points, or else the intersection is empty
diff:=Difference(Intersection(listMoved_H1, listMoved_sigma), listMoved_H2);
if Length(diff) > 0 then
repr:=RepresentativeAction(H1, diff, OnTuples(diff, sigma), OnTuples);
if repr=fail then
return [];
fi;
H1:=Stabilizer(H1, set1, OnTuples);
sigma:=sigma / eRepr;
shift:=eRepr * shift;
# Again this is similar to the case before, except that we are adjusting
# H1 now and thus also need to take `shift` into account. The situation
# is as follows:
#
# cosInt = (H1 \cap H2 sigma) shift
# = (H1 sigma^{-1} \cap H2) sigma shift
# = (Stab_{H1}(diff) repr sigma^{-1} \cap H2) sigma shift
# = (Stab_{H1}(diff) \cap H2 sigma repr^{-1} ) repr shift
H1:=Stabilizer(H1, diff, OnTuples);
sigma:=sigma / repr;
shift:=repr * shift;
continue;
fi;
# easy termination criterion

# easy termination criterion: reduction to group intersection
if sigma in H2 then
U:=Intersection(H1, H2);
return RightCoset(U, shift);
fi;

# easy termination criterion: reduction to group intersection
if sigma in H1 then
# cosInt = (H1 \cap H2 sigma) shift
# = (H1 sigma^{-1} \cap H2) sigma shift
U:=Intersection(H1, H2);
return RightCoset(U, sigma * shift);
fi;
# reduction on sets which is easy
fset1:=Difference(listMoved_H1, Union(listMoved_H2, listMoved_sigma));
if Length(fset1) > 0 then
H1:=Stabilizer(H1, fset1, OnTuples);

# any element of H1 which moves points not moved by sigma or anything
# in H2 can not be in the intersection, so we may as well remove them
# by a stabilizer computation
diff:=Difference(listMoved_H1, Union(listMoved_H2, listMoved_sigma));
if Length(diff) > 0 then
H1:=Stabilizer(H1, diff, OnTuples);
continue;
fi;
fset2:=Difference(listMoved_H2, Union(listMoved_H1, listMoved_sigma));
if Length(fset2) > 0 then
H2:=Stabilizer(H2, fset2, OnTuples);

# the same but with the roles of H1 and H2 reversed
diff:=Difference(listMoved_H2, Union(listMoved_H1, listMoved_sigma));
if Length(diff) > 0 then
H2:=Stabilizer(H2, diff, OnTuples);
continue;
fi;

# More general but more expensive than previous check
H1_sigma:=ClosureGroup(H1, sigma);
if not IsSubgroup(H1_sigma, H2) then
Expand All @@ -667,11 +686,13 @@ function(cos1,cos2)
# No more reduction tricks available
break;
od;

# A final termination criterion
H12:=ClosureGroup(H1, H2);
if not sigma in H12 then
return [];
fi;

# We are now inspired by the algorithm from
# Lazlo Babai, Coset Intersection in Moderately Exponential Time
#
Expand Down

0 comments on commit b953e0a

Please sign in to comment.