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
Added method to calculate Abelian Invariants #16670
Changes from 8 commits
0fe754f
c47ba9d
bf1a804
01eb2b8
2b4fa7b
bf270bb
a8ea915
8b5c6b8
7e758a4
b063c70
08542ff
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -3,6 +3,7 @@ | |
from random import randrange, choice | ||
from math import log | ||
from sympy.ntheory import primefactors | ||
from sympy import multiplicity | ||
|
||
from sympy.combinatorics import Permutation | ||
from sympy.combinatorics.permutations import (_af_commutes_with, _af_invert, | ||
|
@@ -116,6 +117,8 @@ class PermutationGroup(Basic): | |
|
||
.. [13] http://www.math.colostate.edu/~hulpke/CGT/cgtnotes.pdf | ||
|
||
.. [14] https://www.gap-system.org/Manuals/doc/ref/manual.pdf | ||
|
||
""" | ||
is_group = True | ||
|
||
|
@@ -1702,6 +1705,79 @@ def is_abelian(self): | |
return False | ||
return True | ||
|
||
def abelian_invariants(self): | ||
""" | ||
Returns the abelian invariants for the given group. | ||
Let ``G`` be a nontrivial finite abelian group. Then G is isomorphic to | ||
the direct product of finitely many nontrivial cyclic groups of | ||
prime-power order. | ||
|
||
The prime-powers that occur as the orders of the factors are uniquely | ||
determined by G. More precisely, the primes that occur in the orders of the | ||
factors in any such decomposition of ``G`` are exactly the primes that divide | ||
``|G|`` and for any such prime ``p``, if the orders of the factors that are | ||
p-groups in one such decomposition of ``G`` are ``p^{t_1} >= p^{t_2} >= ... p^{t_r}``, | ||
then the orders of the factors that are p-groups in any such decomposition of ``G`` | ||
are ``p^{t_1} >= p^{t_2} >= ... p^{t_r}``. | ||
|
||
The uniquely determined integers ``p^{t_1} >= p^{t_2} >= ... p^{t_r}``, taken | ||
for all primes that divide ``|G|`` are called the invariants of the nontrivial | ||
group ``G`` as suggested in ([14], p. 542). | ||
|
||
Notes | ||
===== | ||
|
||
We adopt the convention that the invariants of a trivial group are []. | ||
|
||
Examples | ||
======== | ||
|
||
>>> from sympy.combinatorics import Permutation | ||
>>> from sympy.combinatorics.perm_groups import PermutationGroup | ||
>>> a = Permutation([0, 2, 1]) | ||
>>> b = Permutation([1, 0, 2]) | ||
>>> G = PermutationGroup([a, b]) | ||
>>> G.abelian_invariants() | ||
[2] | ||
>>> from sympy.combinatorics.named_groups import CyclicGroup | ||
>>> G = CyclicGroup(7) | ||
>>> G.abelian_invariants() | ||
[7] | ||
|
||
""" | ||
if self.is_trivial: | ||
return [] | ||
gns = self.generators | ||
inv = [] | ||
der = self.derived_subgroup() | ||
G = self | ||
|
||
for p in primefactors(G.order()): | ||
ranks = [] | ||
r = 2 | ||
while r > 1: | ||
H = der | ||
l = [] | ||
for g in gns: | ||
elm = g**p | ||
if not H.contains(elm): | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. By fixed There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I mean that There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Okay, I got it! There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Done!, please have a look. |
||
l.append(elm) | ||
H = PermutationGroup(H.generators + l) | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Minor optimization:
|
||
r = G.order()//H.order() | ||
G = H | ||
gns = G.generators | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I've checked and yes it's consistent with the previous result. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. In that case, I would suggest that the creation of
It should be possible to use the name There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I think the above There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Yes, of course. I did forget to add the for part. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. After applying above changes one of the test-case seems to fail i.e the result is not consistent with GAP.
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Perhaps this There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
And the reason seems to be same that you have mentioned above after calculating So, I think the current commit is okay! |
||
if r != 1: | ||
ranks.append(multiplicity(p, r)) | ||
|
||
if ranks: | ||
l = [1]*ranks[0] | ||
for i in ranks: | ||
for j in range(0, i): | ||
l[j] = l[j]*p | ||
inv.extend(l) | ||
inv.sort() | ||
return inv | ||
|
||
def is_elementary(self, p): | ||
"""Return ``True`` if the group is elementary abelian. An elementary | ||
abelian group is a finite abelian group, where every nontrivial | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
How about using something more informative like
pows
instead ofl
(that may sometimes look like 1)?There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
That's right I myself got confused between
1
andl
several times.