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

Add methods for isomorphism computation #14861

Merged
merged 6 commits into from Jul 7, 2018

Conversation

Projects
None yet
3 participants
@RavicharanN
Contributor

RavicharanN commented Jul 2, 2018

Brief description of what is fixed or changed

A group_isomorphismmethod has been added to compute the isomorphism between 2 groups. Corresponding tests have also been added.

Other comments

The isomorphism methods are currently implemented for finite groups and only a few special cases of infinite groups.

To-do

  • Imrove the documentation.
  • Add isomorphism computaion for a few special cases.

@RavicharanN RavicharanN changed the title from Add Isomorphism computation between 2 groups. to Add methods for isomorphism computation Jul 2, 2018

gens.append(g_isomorphism.invert(g))
else:
gens = G.generators
T = homomorphism(G, H, gens, images, check=False)

This comment has been minimized.

@valglad

valglad Jul 2, 2018

Contributor

It could be neater to just call homomorphism directly with _H as the co-domain and check=True and catching the error if it's not well-defined, then checking if that is an isomorphism, and if it is, defining another one in case H is actually an FpGroup.

else:
gens = G.generators
T = homomorphism(G, H, gens, images, check=False)
if T.is_injective() and T.is_surjective():

This comment has been minimized.

@valglad

valglad Jul 2, 2018

Contributor

T.is_isomorphism() does this.

if (g_order in sieve) and (h_order in sieve):
if g_order == h_order:
return True
return False

This comment has been minimized.

@valglad

valglad Jul 2, 2018

Contributor

You are still not using the condition with Euler's totient function. Is it tricky to implement?

This comment has been minimized.

@RavicharanN

RavicharanN Jul 2, 2018

Contributor

Will update that

# Two infinite FpGroups with the same generators are isomorphic
# when the relators are same but are ordered differently.
if G.generators == H.generators and (G.relators).sort() == (H.relators).sort():
return homomorphism(G, H, G.generators, H.generators)

This comment has been minimized.

@valglad

valglad Jul 2, 2018

Contributor

This output is not of a valid form for either value of compute, this should be preceded by a boolean.

if not isomorphism:
n = g_order
if (g_order == h_order) and (igcd(n, totient(n))) == 1:
return True

This comment has been minimized.

@valglad

valglad Jul 3, 2018

Contributor

Could be useful to leave a comment explaining that in this case the group is cyclic.

gens = []
if isinstance(H, FpGroup):
for s in subset:
images.append(h_isomorphism.invert(s))

This comment has been minimized.

@valglad

valglad Jul 3, 2018

Contributor

images = h_isomorphism.invert(subset) should do it, provided subset is a list.

def group_isomorphism(G, H, isomorphism=False):
'''
Compute an isomorphism between 2 given groups.

This comment has been minimized.

@valglad

valglad Jul 3, 2018

Contributor

If this is how we describe it, then isomorphism should be True by default. Possibly worth actually having a little function like

def is_isomorphic(G, H):
    return group_isomorphism(G, H, isomorphism=False)

just because that would be shorter to use.

if not isinstance(G, (PermutationGroup, FpGroup)):
raise TypeError("The group must be a PermutationGroup or a finite FpGroup")
if not isinstance(H, (PermutationGroup, FpGroup)):
raise TypeError("The group must be a PermutationGroup or a finite FpGroup")

This comment has been minimized.

@valglad

valglad Jul 6, 2018

Contributor

It doesn't have to be finite anymore because we can do some things with infinite groups!

return True
return (True, homomorphism(G, H, G.generators, H.generators))
# `_H` is the permutation groups isomorphic to `H`.

This comment has been minimized.

@valglad

valglad Jul 6, 2018

Contributor

group

raise NotImplementedError("Isomorphism methods are not implemented for infinite groups.")
_H, h_isomorphism = H._to_perm_group()
if (g_order != h_order) and (G.is_abelian != H.is_abelian):

This comment has been minimized.

@valglad

valglad Jul 6, 2018

Contributor

This should be an or condition.

if not isomorphism:
# Two groups of same cyclic numbered order
# are ismorphic to each other.

This comment has been minimized.

@valglad

valglad Jul 6, 2018

Contributor

"the same" and "isomorphic"

if (g_order == h_order) and (igcd(n, totient(n))) == 1:
return True
# Match the generators of `_G` with the subsets of `_H`

This comment has been minimized.

@valglad

valglad Jul 6, 2018

Contributor

G and just subsets, without the article.

# Match the generators of `_G` with the subsets of `_H`
gens = G.generators
for subset in itertools.permutations(_H, len(gens)):
gens = list(gens)

This comment has been minimized.

@valglad

valglad Jul 6, 2018

Contributor

You can do this outside the loop when you first define gens

gens = list(gens)
images = list(subset)
images.extend([_H.identity]*(len(G.generators)-len(images)))
gens.extend([g for g in G.generators if g not in gens])

This comment has been minimized.

@valglad

valglad Jul 6, 2018

Contributor

gens == list(G.generators) so surely the list comprehension will always be empty.

gens.extend([g for g in G.generators if g not in gens])
_images = dict(zip(gens,images))
if _check_homomorphism(G, _H, _images):
images = []

This comment has been minimized.

@valglad

valglad Jul 6, 2018

Contributor

You don't need to define this.

# `_H` is the permutation groups isomorphic to `H`.
_H = H
h_isomorphism = None

This comment has been minimized.

@valglad

valglad Jul 6, 2018

Contributor

You don't need to define h_isomorphism here.

This comment has been minimized.

@RavicharanN

RavicharanN Jul 7, 2018

Contributor

I think static scoping might cause problems if this is not defined. If h_isomorphism is initialized inside that if block, I think that variable would be local to that scope.

This comment has been minimized.

@valglad

valglad Jul 7, 2018

Contributor

An if statement doesn't usually count as a new scope - you'd need something major for that, like a function inside a function. You could try it with a simple script but I'm certain it works in Python.

if _check_homomorphism(G, _H, _images):
images = []
if isinstance(H, FpGroup):
images = h_isomorphism.invert(list(subset))

This comment has been minimized.

@valglad

valglad Jul 6, 2018

Contributor

This can be .invert(images).

if isinstance(H, FpGroup):
images = h_isomorphism.invert(list(subset))
else:
images = subset

This comment has been minimized.

@valglad

valglad Jul 6, 2018

Contributor

You don't need this line at all if you don't rewrite images with [] as you do before the if.

# It is a valid isomorphism
if not isomorphism:
return True
else:

This comment has been minimized.

@valglad

valglad Jul 6, 2018

Contributor

No need for this else.

P = PermutationGroup(p)
assert not is_isomorphic(D, P)
# Cyclic Groups of different prime order are not isomorphic to each other.

This comment has been minimized.

@valglad

valglad Jul 6, 2018

Contributor

No groups of different order are isomorphic to each other - you don't really need the comment there, I think the test is clear as it is.

B = CyclicGroup(7)
assert not is_isomorphic(A, B)
# Two groups of same prime order are isomorphic to each other.

This comment has been minimized.

@valglad

valglad Jul 6, 2018

Contributor

"the same"

@valglad

This comment has been minimized.

Contributor

valglad commented Jul 6, 2018

This is mostly good now - there are some typos and redundant lines but once that's fixed, it should be good to merge.

@valglad

This comment has been minimized.

Contributor

valglad commented Jul 7, 2018

I think this is ready

@valglad valglad merged commit 9388097 into sympy:master Jul 7, 2018

1 check passed

continuous-integration/travis-ci/pr The Travis CI build passed
Details
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment