a problem with nice monomorphisms
Suppose we have a bijective map f: G -> H that was created with GroupHomomorphismByFunction, such that H is a group in IsHandledByNiceMonomorphism.
Then the function from the construction allows us to compute images, and we can compute preimages by composing n:= NiceMonomorphism( H ) with a GroupHomomorphismByImages map that is defined by mapping the images of the generators of G under the composition of f with n to the generators of G.
(This works only if the image of n is really nice, for example if n is an action homomorphism, but let us assume that this is the case.)
The available implementation in GAP does in principle support this, for example if f is an isomorphism defined by a function from a permutation group to a matrix group over a finite field.
I do not understand why the result of GroupHomomorphismByFunction has always the filter IsPreimagesByAsGroupGeneralMappingByImages; in the above situation, there is no need for computing an additional AsGroupGeneralMappingByImages map, the nice monomorphism of H can be used to compute the inverse of f without that.
But this is not really a problem.
However, if f is itself a nice monomorphism then the above mechanism does not work, because the GroupGeneralMappingByImagesNC method that is expected to create the inverse as a composition calls TryNextMethod(), in order to avoid recursion, and then one ends up in a generic method that wants to store lists of elements and images --if the groups are not very small then here one gets stuck.
Here is an example.
gap> G1:= AtlasGroup( "M11", IsPermGroup );;
gap> G2:= AtlasGroup( "M11", Characteristic, 2 );;
gap> isoBI:= GroupHomomorphismByImages( G1, G2, GeneratorsOfGroup( G1 ), GeneratorsOfGroup( G2 ) );;
gap> isoBF1:= GroupHomomorphismByFunction( G1, G2, x -> ImagesRepresentative( isoBI, x ) );;
gap> isoBF2:= GroupHomomorphismByFunction( G1, G2, x -> ImagesRepresentative( isoBI, x ) );;
gap> SetFilterObj( isoBF2, IsNiceMonomorphism );
gap> # compute a preimage
gap> x:= Product( GeneratorsOfGroup( G2 ) );;
gap> PreImagesRepresentative( isoBI, x );;
gap> PreImagesRepresentative( isoBF1, x );;
gap> PreImagesRepresentative( isoBF2, x );; # takes much longer ...
gap> # inspect the internal data of the maps
gap> REC_NAMES_COMOBJ( RestrictedInverseGeneralMapping( AsGroupGeneralMappingByImages( isoBF1 ) ) );
[ "RestrictedInverseGeneralMapping", "map1", "map2" ]
gap> REC_NAMES_COMOBJ( RestrictedInverseGeneralMapping( AsGroupGeneralMappingByImages( isoBF2 ) ) );
[ "Range", "Source", "RestrictedInverseGeneralMapping", "ImagesSource",
"PreImagesRange", "MappingGeneratorsImages", "images", "elements" ]
A preliminary workaround in my situation is to reset the filter IsNiceMonomorphism until the inverse is known. Any hint for a proper solution is welcome.
This is likely a relic from times when a) All nice monomorphism were to permutation groups and b) PreImage methods for action homomorphisms tended to find an element acting in the right way. I suspect the implication can be killed by now.
Thanks, @ahulpke.
Thus we can decide that GroupHomomorphismByFunction sets IsPreimagesByAsGroupGeneralMappingByImages only if the range is a permutation group. I will make some experiments what the consequences of such a change are (w.r.t. the GAP test suite).
Or we could be more "conservative", and keep GroupHomomorphismByFunction setting IsPreimagesByAsGroupGeneralMappingByImages in all cases except if the range is handled via a nice monomorphism.
Perhaps it makes sense to change also the setup for action homomorphisms; note that IsPreimagesByAsGroupGeneralMappingByImages is implied by IsActionHomomorphism.
(But I will not try this now.)
As far as I understand the setup, having a GroupHomomorphismByFunction with known MappingGeneratorsImages is at least as good as having its AsGroupGeneralMappingByImages, thus it would be better to work without an auxiliary ByImages mapping.