Add methods for isomorphism computation #14861

Merged
merged 6 commits into from Jul 7, 2018
+169 −4

Conversation

Projects
None yet
3 participants
Contributor

RavicharanN commented Jul 2, 2018

Brief description of what is fixed or changed

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

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 added some commits Jul 2, 2018

``` Add isomorphism methods ```
``` 20aca41 ```
``` Add tests ```
``` 49b883d ```

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

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

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():

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

valglad Jul 2, 2018 • edited

Contributor

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

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)

valglad Jul 2, 2018 • edited

Contributor

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

RavicharanN added some commits Jul 2, 2018

``` Add euler totient and other minor changes ```
``` be24a2f ```
``` Fix minor bug that causes test failures ```
``` 7f89b00 ```

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

Contributor

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

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.

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.

Abdullahjavednesar added combinatorics PR: author's turn labels Jul 4, 2018

``` Minor changes in the implementation ```
``` 7175ae7 ```

 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")

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`.

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):

Contributor

This should be an `or` condition.

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

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`

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)

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])

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 = []

Contributor

You don't need to define this.

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

valglad Jul 6, 2018 • edited

Contributor

You don't need to define `h_isomorphism` here.

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.

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))

valglad Jul 6, 2018 • edited

Contributor

This can be `.invert(images)`.

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

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:

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.

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.

Contributor

"the same"

Contributor

 This is mostly good now - there are some typos and redundant lines but once that's fixed, it should be good to merge.
``` Remove redundant lines and fix documentation ```
``` 77cb87f ```
Contributor