Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix LatticeSubgroup sometimes returning wrong results for matrix groups #4718

Merged
merged 1 commit into from
Dec 18, 2021

Conversation

fingolfin
Copy link
Member

... if used on a group which is handled by a NiceMonomorphism, which normally includes all matrix groups. Also fix an IsFinite method for non-rational cyclotomic matrix groups.

In both cases, the code wrongly assumed that the Image(NiceMonomorphism(g)) equals Image(NiceMonomorphism(g),g). The solution is to use NiceObject(g) which is also cached, as it is an attribute.

Also change a few more places to use NiceObject(g); while they were correct, using NiceObject is potentially more efficient.

Fixes #4717

@fingolfin fingolfin added kind: bug Issues describing general bugs, and PRs fixing them kind: bug: wrong result Issues describing bugs that result in mathematically or otherwise wrong results, and PRs fixing them release notes: use title For PRs: the title of this PR is suitable for direct use in the release notes labels Dec 11, 2021
@laurentbartholdi
Copy link
Contributor

laurentbartholdi commented Dec 11, 2021

I wrote a comment in another thread, that it seems dangerous to me to have both NiceObject and NiceMonomorphism in code, with the secret guarantee that the range of the latter is IdenticalObj to the parent of the former.

I see that the code contains quite a few RestrictedNiceMonomorphism, which precisely construct the restricted map I was thinking about. For these, it is safe to use Image(mono), which should be IdenticalObj to NiceObject(g), and cached.

How about the following cleanish way of implementing the guarantee above? each NiceObject has an attribute ComingFrom which is the NiceMonomorphism used to produce it. So for example HallSubgroup would become

function(g,l)
local mon,h;
   niceg:=NiceObject(g); 
   h:=HallSubgroup(niceg,l);
   if h = fail then
       return fail;
   elif IsList(h) then
       return List(h, k -> PreImage(ComingFrom(niceg), k));
   elif IsGroup(h) then
       return PreImage(ComingFrom(niceg),h);
   else
       Error("Unexpected return value from HallSubgroup");
   fi;
end);

where I replaced all the mon by ComingFrom(niceg).

@fingolfin
Copy link
Member Author

fingolfin commented Dec 13, 2021

I wrote a comment in another thread, that it seems dangerous to me to have both NiceObject and NiceMonomorphism in code, with the secret guarantee that the range of the latter is IdenticalObj to the parent of the former.

There is no "secret guarantee", and the the latter need not be "the parent of the former". The guarantee is that that NiceObject(G) = Image(NiceMonomorphism(G),G), and this is not "secret", it is documented explicitly.

I see that the code contains quite a few RestrictedNiceMonomorphism, which precisely construct the restricted map I was thinking about:

... and they do so with precisely the overhead I was thinking about :-), namely: the resulting map can be less efficient, be it because it is a new wrapper object around the actual homomorphism or be it because it was rewritten as a GHBI (group homomorphism by images), or for some other reasons.

For these, it is safe to use Image(mono), which should be IdenticalObj to NiceObject(g), and cached.

It is still not true that this image need be identical, only that it is equal. And one of the various motivations for NiceObject(g) is precisely to have it cached.

How about the following cleanish way of implementing the guarantee above? each NiceObject has an attribute ComingFrom which is the NiceMonomorphism used to produce it.

I don't see how this is any "cleaner" than what have, or for that matter, "safer": one could apply the same concerns about this: "is it guaranteed that ComingFrom(NiceMonomorphism(G) really is the same as G" etc.

But it certainly would be different, and using it would require adapting the whole library and lots of packages.

So for example HallSubgroup would become

function(g,l)
local mon,h;
   niceg:=NiceObject(g); 
   h:=HallSubgroup(niceg,l);
   if h = fail then
       return fail;
   elif IsList(h) then
       return List(h, k -> PreImage(ComingFrom(niceg), k));
   elif IsGroup(h) then
       return PreImage(ComingFrom(niceg),h);
   else
       Error("Unexpected return value from HallSubgroup");
   fi;
end);

where I replaced all the mon by ComingFrom(niceg).

return IsFinite( Image( NiceMonomorphism( G ) ) );
# the following does not use NiceObject(G) as the only method for
# that currently requires IsHandledByNiceMonomorphism
return IsFinite( Image( NiceMonomorphism( G ), G ) );
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why not IsFinite(NiceObject(G)) ?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

As explained in the comment right above this line, there is no method to compute NiceObject in this case. We could also change the existing NiceObject to apply to arbitrary groups, not just those in the filter IsHandledByNiceMonomorphism, but that's a bigger change with potentially further implications, and so I decided to go this way, as it minimizes the risk of a regression. One could investigate the mentioned alternative in a separate PR, but I'd rather not mix it with a bugfix.

@laurentbartholdi
Copy link
Contributor

laurentbartholdi commented Dec 13, 2021 via email

Copy link
Contributor

@hulpke hulpke left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The only problematic issue is in Image(hom), which predates the observation that it can be most effective to inherit nice monomorphisms. But for consistency using NiceObject in place of Image(hom,G) is probably best.

@fingolfin fingolfin closed this Dec 17, 2021
@fingolfin fingolfin reopened this Dec 17, 2021
... if used on a group which is handled by a `NiceMonomorphism`, which
normally includes all matrix groups. Also fix an `IsFinite` method
for non-rational cyclotomic matrix groups.

In both cases, the code wrongly assumed that the `Image(NiceMonomorphism(g))`
equals `Image(NiceMonomorphism(g),g)`. The solution is to use `NiceObject(g)`
which is also cached, as it is an attribute.

Also change a few more places to use `NiceObject(g)`; while they were
correct, using `NiceObject` is potentially more efficient.
@wilfwilson wilfwilson merged commit 44b108b into gap-system:master Dec 18, 2021
@fingolfin fingolfin deleted the mh/fix-nicemono-usage branch December 27, 2021 22:00
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
kind: bug: wrong result Issues describing bugs that result in mathematically or otherwise wrong results, and PRs fixing them kind: bug Issues describing general bugs, and PRs fixing them release notes: use title For PRs: the title of this PR is suitable for direct use in the release notes
Projects
None yet
Development

Successfully merging this pull request may close these issues.

LatticeSubgroups gives wrong result for SL
4 participants