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

Maximal normal subgroups fixes #705

Merged

Conversation

hungaborhorvath
Copy link
Contributor

@hungaborhorvath hungaborhorvath commented Apr 2, 2016

Fix some issues with MaximalNormalSubgroups introduced from #692 after merging #552.

  • NormalSubgroup computation method is only called for finite groups.
  • Redispatch is added for two methods (finite, solvable). (Not added for abelian, because abelian
    groups should be recognized by the IsSolvabe test.)
  • New generic method added checking if AbelianInvariants has 0.
  • Abelian method checks if AbelianInvariants has 0 (for non pc-groups).
  • If GAP finds that there are infinitely many maximal normal subgroups, then
    it returns fail instead of erroring out (e.g. if 0 is in AbelianInvariants).
  • Manual is changed to reflect this new behaviour, an example is added, as well.
  • Lists are replaced by sorted lists in test file and some more tests are added.

I tried to heed to the guidelines set in #692. I believe there can be two possibilities for concern here. One is the obvious behaviour change if 0 is in AbelianInvariants meaning there are infinitely many maximal normal subgroups, then earlier MaximalNormalSubgroups would simply error with no method found, and now it returns fail. The other is that earlier the method calling NormalSubgroups first and then checking for maximal ones in that list is now only called for finite groups in grp.gi:4464. I do not know if any method for NormalSubgroups for infinite groups exists, but if there are some then it should be discussed how to reintroduce the computing NormalSubgroups first method for MaximalNormalSubgroups for such groups.

Test should run with -A -m 100m -o 1g, but instead of 1.8 seconds it runs for 75.5 seconds on my machine with these parameters. I am not sure if anything should be done about this.

@markuspf
Copy link
Member

markuspf commented Apr 2, 2016

I am not sure whether fail is the correct response here.
If there are infinitely many maximal normal subgroups, is there hope of describing them by using an Iterator for example (and if so, will that be of any use at all?)

@hungaborhorvath
Copy link
Contributor Author

@markuspf Hm, yes, they should be able to be described in such a way, at least if the group is solvable. I doubt, though, that it is worth the effort.

Originally, I made the method error out with a message in such a situation, because I assumed that the user could benefit from the knowledge of too many maximal normal subgroups, and I did not think of iterators. I still think that until a method for such an iterator is not present, it would be worth to notify the user about the situation either by erroring or failing or maybe some other way.

## can be computed very quickly. Thus if you suspect your group to be
## abelian or solvable, then check it before computing the maximal normal
## subgroups.
##
Copy link
Member

Choose a reason for hiding this comment

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

This is not in the documentation, and I wonder whether this would be appropriate (actually both points: If you can get your hands on a character table, or if the group is abelian or solvable MaximalNormalSubgroups can be computed more effciently)?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Added the note to the manual and added an infinite example to emphasize that MaximalNormalSubgroups works for some infinite groups.

Copy link
Member

Choose a reason for hiding this comment

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

Seems good

@markuspf
Copy link
Member

A note on the test runtime as well. As @hulpke pointed out in #722 (and it has been noted before), the testinstall runtimes seem to be getting a bit out of hand.

I actually made a proposal for rearranging the tests a bit, and give the testsuites slightly better names: https://github.com/gap-system/gap/wiki/Testing-methods-and-targets An appropriate pull-request is in progress, but not done yet. The current testinstall target can be roughly translated to test-core-quick.

Copy link
Member

@fingolfin fingolfin left a comment

Choose a reason for hiding this comment

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

Thanks for your effort, and sorry for no feedback in half a year :-(.

In case you are not sick of us and still willing to work on this, perhaps you could also rebase it -- this then should trigger the new code coverage tests, which will help us see if the new code is fully exercised by the new tests.

Thanks once more!


if 0 in AbelianInvariants(G) then
# (p) is a maximal normal subgroup in Z for every prime p
return fail;
Copy link
Member

Choose a reason for hiding this comment

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

Regarding this line, @markuspf previously asked whether returning fail here makes sense or not. And @hungaborhorvath stated that he initially had an Error() here, but found fail to be more useful. I mostly agree with the latter. And regarding the possibility of returning an infinite iterator here: Sure, that might be possible for some cases at least, but I also doubt it'd be that useful... Perhaps some day somebody will arrive at a situation where it is useful, and then we can revisit this. Until then, I think it would be a waste of time to implement such an iterator, plus, let's not forgot the golden rule "code you don't actually use is always wrong" ;-).

We could of course add a new constant UnableToCompute or ResultIsInfinite or so, but again: as long as nobody actually uses this...

Finally, the "rule" to a degree even applies to fail. @hungaborhorvath do you use this, or is this just a case of "might be useful"? In the latter case, I'd just put an error here. Then, if we later find a use case where we should return fail and/or some other special constant, we can reopen this, without breaking any existing code. While if we return fail now, we can never again change it without risking to break somebody's code... So in this sense, Error is the safe and future proof solution :-)

## gap> List(MaximalNormalSubgroups(f/[x^2, y^2]), GeneratorsOfGroup);
## [ [ x, y*x*y^-1 ], [ y, x*y*x^-1 ], [ y*x^-1 ] ]
## gap> MaximalNormalSubgroups( AbelianGroup( [ 0 ] ) );
## fail
## ]]></Example>
Copy link
Member

Choose a reason for hiding this comment

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

These documentation changes look good to me.

InstallMethod( MaximalNormalSubgroups,
"generic search",
[ IsGroup ],
[ IsGroup and IsFinite ],
Copy link
Member

Choose a reason for hiding this comment

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

ok

RedispatchOnCondition( MaximalNormalSubgroups, true,
[ IsGroup ],
[ IsFinite ], 0);

Copy link
Member

Choose a reason for hiding this comment

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

ok

RankFilter(IsGroup and IsFinite)
- RankFilter(IsGroup and IsNilpotentGroup),
RankFilter( IsGroup and IsFinite and IsNilpotentGroup )
- RankFilter( IsGroup and IsNilpotentGroup ),
Copy link
Member

Choose a reason for hiding this comment

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

makes sense

# convert it to an Abelian PcGroup with same invariants
Gf := AbelianGroup(IsPcGroup, AbInv);
hom := IsomorphismGroups(G, Gf);
MaxGf := NormalMaximalSubgroups(Gf);
Copy link
Member

Choose a reason for hiding this comment

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

perhaps add a comment which points out that for abelian groups, all maximal normal subgroup are also normal maximal subgroups (and vice-versa), lest people might get confused (well... "people" = me in this case... but perhaps I am unique in this regard ... :-).

else
# convert it to an Abelian PcGroup with same invariants
Gf := AbelianGroup(IsPcGroup, AbInv);
hom := IsomorphismGroups(G, Gf);
Copy link
Member

Choose a reason for hiding this comment

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

Computing IsomorphismGroups might be wasteful here... Why not use IsomorphismPcGroup? I.e. replace the preceding two lines by

hom := IsomorphismPcGroup(G);
Gf := Image(hom);

Copy link
Member

Choose a reason for hiding this comment

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

As a bonus, if G is already a pc group, then this immediatly returns an identity mapping.

# rank, otherwise the method for normal subgroup computation
# is selected.
RankFilter( IsGroup and IsFinite and IsSolvableGroup )
- RankFilter( IsGroup and IsSolvableGroup ),
Copy link
Member

Choose a reason for hiding this comment

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

ok

RedispatchOnCondition( MaximalNormalSubgroups, true,
[ IsGroup ],
[ IsSolvableGroup ], 0);

Copy link
Member

Choose a reason for hiding this comment

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

ok

[ 2, 4, 5, 7, 8, 9, 25 ], [ 2, 4, 5, 7, 8, 9, 25 ],
[ 2, 4, 5, 7, 8, 9, 25 ], [ 2, 3, 4, 5, 5, 7, 8, 9 ],
gap> SortedList(List(MaximalNormalSubgroups(A),N -> AbelianInvariants(N)));
[ [ 2, 2, 3, 5, 7, 8, 9, 25 ], [ 2, 2, 3, 5, 7, 8, 9, 25 ],
Copy link
Member

Choose a reason for hiding this comment

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

Yup, using SortedList seems like a good idea, to keep the tests stable

@hungaborhorvath
Copy link
Contributor Author

hungaborhorvath commented Nov 4, 2016

@fingolfin I think I have managed to remove the commit about the fail (originally it was error, so that should do the trick). In the last commit I have applied your suggestions, I hope I did not leave out anything. Also rebased, hopefully succeeded.

Edit: Nope, I must have messed up something.... I will take it slowly and one step at a time.

Edit2: It should be ok now. Let us see if tests run.

@codecov-io
Copy link

codecov-io commented Nov 4, 2016

Current coverage is 48.66% (diff: 92.30%)

Merging #705 into master will decrease coverage by 0.15%

@@             master       #705   diff @@
==========================================
  Files           424        424          
  Lines        222089     222098     +9   
  Methods        3426       3426          
  Messages          0          0          
  Branches          0          0          
==========================================
- Hits         108441     108091   -350   
- Misses       113648     114007   +359   
  Partials          0          0          

Powered by Codecov. Last update becaeff...d4181c3

- NormalSubgroup computation method is only called for finite groups.
- Redispatch is added for two methods (finite, solvable).
- New generic method added checking if AbelianInvariants has 0.
- Abelian method checks if AbelianInvariants has 0 (for non pc-groups).
- Lists are replaced by sorted lists in test file.

if 0 in AbelianInvariants(G) then
# (p) is a maximal normal subgroup in Z for every prime p
Error("number of maximal normal subgroups is infinity");
Copy link
Member

Choose a reason for hiding this comment

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

According to https://codecov.io/gh/gap-system/gap/pull/705/compare this is not covered by the tests. Could you please add a test case? E.g. using an abelian FP group with a single generator)

Copy link
Member

Choose a reason for hiding this comment

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

Actually, you might need one with two generators, as one with a single generator is abelian, the systems knows that, and thus the other currently untested error should get triggered... :)

Copy link
Contributor Author

Choose a reason for hiding this comment

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

@fingolfin Previously, when it returned fail, I had a test for it, that is not a problem.

But I have no idea how to write a test for an error into a tst file. Should I just copy everything from my GAP output to the tst file? Or does it have a special method? Is the output even stable (apart from the error message)?

Copy link
Contributor

@ChrisJefferson ChrisJefferson Nov 5, 2016

Choose a reason for hiding this comment

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

@hungaborhorvath : I often find the easiest thing to do is to run the test without an output, and then cut+paste the output GAP gives you (when it tells you the test is wrong). Here's an example test which produces an error.

gap> 1/0;
Error, Rational operations: <divisor> must not be zero

Note how the line / file / backtrace are all missing (they are disabled when you test, specifically for this reason).

Copy link
Member

Choose a reason for hiding this comment

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

The .tst file basically should contain the first line of the error message.. but as @ChrisJefferson says, you can simply run the test file manually, and if you got it wrong, it'll tell you.

Just in case you don't know, you can run an individual test file with the Test functio (that's much quicker than running the whole make testinstall etc.)

AbInv := AbelianInvariants(G);
if 0 in AbInv then
# (p) is a maximal normal subgroup in Z for every prime p
Error("number of maximal normal subgroups is infinity");
Copy link
Member

Choose a reason for hiding this comment

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

This line is untested, too.

@hungaborhorvath
Copy link
Contributor Author

I think I have added tests for the errors. Let me know if I missed any, I am not sure how to read codecov.... Thank you.

@fingolfin
Copy link
Member

To read codecov, click on the "Current coverage" link, then on the webpage that opens, there is a horizontal list ("tab bar"?) with four enries: Overview, Commits, Compare, Graphs. Select "compare". The resulting page shows you the changes in this PR; light red and light green to indicate removals / additions. Now, in the left most column (the one with line numbers) you'll also see dark green / dark red blotches. Those indicate lines that are actually code; green means this line is executed by some test, while dark red means this line is never triggered. Right now, everything is reached, except for one "end" line, which is kind of a bug, I think (well, it indeed is never reached, because we return before it... perhaps moving the TryNextMethod() out of the else and to the top level of the function helps? In any case, it is is not important, your test coverage is perfect.).

@fingolfin
Copy link
Member

@ChrisJefferson would know better regarding that red "end" ... but again, it's harmless

@fingolfin
Copy link
Member

Does the test still require 75 seconds, instead of 2? That is something we need to worry about. Perhaps we can split the test in those which are run on testinstall, and those which are run in the full test suite... or perhaps we can replace some of the slow tests by faster ones? Haven't yet had a chance to figure out which is causing what.

@hungaborhorvath
Copy link
Contributor Author

@fingolfin Thank you for explaining the codecov, I understand it now.

About the running time: yes, without packages it is still very long. I guess it is the fp-groups, but I have not checked explicitly.

@ChrisJefferson
Copy link
Contributor

The red 'end' is because GAP adds an implicit "return" to the end of functions, which is then not executed. I am currently doing a cleanup which will clean up this, and some other issues.

@hungaborhorvath
Copy link
Contributor Author

The culprit for the long runtime was the fp-group D360. I changed to D36, and now tests run in less than 1 second with or without packages. I do not remember why I chose 360 originally....

@fingolfin
Copy link
Member

For me, the tests now indeed run in less than 1 second. While on master (!), it takes over 70 seconds to run tst/testinstall/opers/MaximalNormalSubgroups.tst.

Clear win! :-)

@fingolfin fingolfin merged commit 312ab24 into gap-system:master Nov 9, 2016
@markuspf
Copy link
Member

markuspf commented Nov 9, 2016

Thank you very much for your hard work @hungaborhorvath!

@hungaborhorvath hungaborhorvath deleted the MaximalNormalSubgroupsFixes branch November 9, 2016 19:02
@olexandr-konovalov olexandr-konovalov added the release notes: not needed PRs introducing changes that are wholly irrelevant to the release notes label Jan 20, 2018
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
release notes: not needed PRs introducing changes that are wholly irrelevant to the release notes
Projects
None yet
Development

Successfully merging this pull request may close these issues.

6 participants