ó
~9­\c           @  sç   d  d l  m Z m Z d  d l Z d  d l m Z m Z m Z d  d l m	 Z	 d  d l
 m Z d  d l m Z d  d l m Z d  d l m Z d	 e f d
 „  ƒ  YZ g  e d „ Z d „  Z d „  Z d „  Z e d „ Z d „  Z d S(   iÿÿÿÿ(   t   print_functiont   divisionN(   t   FpGroupt
   FpSubgroupt   simplify_presentation(   t	   FreeGroup(   t   PermutationGroup(   t   igcd(   t   totient(   t   St   GroupHomomorphismc           B  s•   e  Z d  Z d „  Z d „  Z d „  Z d „  Z d „  Z d „  Z d „  Z	 d „  Z
 d	 „  Z d
 „  Z d „  Z d „  Z d „  Z d „  Z d „  Z RS(   sÖ   
    A class representing group homomorphisms. Instantiate using `homomorphism()`.

    References
    ==========

    .. [1] Holt, D., Eick, B. and O'Brien, E. (2005). Handbook of computational group theory.

    c         C  s:   | |  _  | |  _ | |  _ d  |  _ d  |  _ d  |  _ d  S(   N(   t   domaint   codomaint   imagest   Nonet	   _inversest   _kernelt   _image(   t   selfR   R   R   (    (    s@   lib/python2.7/site-packages/sympy/combinatorics/homomorphisms.pyt   __init__   s    					c   
      C  sG  |  j  ƒ  } i  } xL t |  j j ƒ  ƒ D]5 } |  j | } | | k pM | j s( | | | <q( q( Wt |  j t ƒ r | j } n	 | j	 } x¸ | D]° } | | k s | j r° q n  |  j
 j } t |  j t ƒ rë | j | d d d … } n | } xA | D]9 }	 |	 | k r| | |	 } qø | | |	 d d } qø W| | | <q W| S(   sÚ   
        Return a dictionary with `{gen: inverse}` where `gen` is a rewriting
        generator of `codomain` (e.g. strong generator for permutation groups)
        and `inverse` is an element of its preimage

        Niÿÿÿÿ(   t   imaget   listR   t   keyst   is_identityt
   isinstanceR   R   t   strong_genst
   generatorsR   t   identityt   _strong_gens_slp(
   R   R   t   inversest   kt   vt   genst   gt   wt   partst   s(    (    s@   lib/python2.7/site-packages/sympy/combinatorics/homomorphisms.pyt   _invs   s.    		c   
      C  su  d d l  m } d d l m } t | | | f ƒ rBt |  j t ƒ r\ |  j j | ƒ } n  |  j d k r} |  j
 ƒ  |  _ n  |  j ƒ  } |  j j } t |  j t ƒ rÆ | j | ƒ d d d … } n | } xo t t | ƒ ƒ D][ } | | } | j rþ qß n  | |  j k r!| |  j | } qß | |  j | d d } qß W| St | t ƒ rqg  | D] }	 |  j |	 ƒ ^ qXSd S(   s¥  
        Return an element of the preimage of `g` or of each element
        of `g` if `g` is a list.
        NOTE: If the codomain is an FpGroup, the inverse for equal
        elements might not always be the same unless the FpGroup's
        rewriting system is confluent. However, making a system
        confluent can be time-consuming. If it's important, try
        `self.codomain.make_confluent()` first.

        iÿÿÿÿ(   t   Permutation(   t   FreeGroupElementN(   t   sympy.combinatoricsR&   t   sympy.combinatorics.free_groupsR'   R   R   R   t   reduceR   R   R%   R   R   R   R   t   generator_productt   ranget   lenR   R   t   invert(
   R   R!   R&   R'   R   R"   R    t   iR$   t   e(    (    s@   lib/python2.7/site-packages/sympy/combinatorics/homomorphisms.pyR.   @   s,    
	c         C  s(   |  j  d k r! |  j ƒ  |  _  n  |  j  S(   s0   
        Compute the kernel of `self`.

        N(   R   R   t   _compute_kernel(   R   (    (    s@   lib/python2.7/site-packages/sympy/combinatorics/homomorphisms.pyt   kernelj   s    c   	      C  s*  d d l  m } |  j } | j ƒ  } | | j k rC t d ƒ ‚ n  g  } t | t ƒ rj t | j ƒ } n t	 | | d t
 ƒ} |  j ƒ  j ƒ  } x’ | j ƒ  | | k r%| j ƒ  } | |  j |  | ƒ ƒ d } | | k r” | j | ƒ t | t ƒ r
t | ƒ } q"t	 | | d t
 ƒ} q” q” W| S(   Niÿÿÿÿ(   R	   s9   Kernel computation is not implemented for infinite groupst   normal(   t   sympyR	   R   t   ordert   Infinityt   NotImplementedErrorR   R   R   R   t   TrueR   t   randomR.   t   append(	   R   R	   t   Gt   G_orderR    t   KR/   t   rR   (    (    s@   lib/python2.7/site-packages/sympy/combinatorics/homomorphisms.pyR1   s   s(    	c         C  ss   |  j  d k rl t t |  j j ƒ  ƒ ƒ } t |  j t ƒ rT |  j j	 | ƒ |  _  ql t
 |  j | ƒ |  _  n  |  j  S(   s/   
        Compute the image of `self`.

        N(   R   R   R   t   setR   t   valuesR   R   R   t   subgroupR   (   R   R@   (    (    s@   lib/python2.7/site-packages/sympy/combinatorics/homomorphisms.pyR   ‹   s    c   
      C  s\  | |  j  k rS t | t t f ƒ rD g  | D] } |  j | ƒ ^ q+ St d ƒ ‚ n  | j rf |  j j S|  j	 } |  j j } t |  j  t
 ƒ rï |  j  j | d t ƒ} x° | D]< } | |  j	 k rÒ | | | } q¬ | | d d | } q¬ Wni d } x` | j D]U \ } }	 |	 d k  r(| | d } n
 | | } | | | |	 } | t |	 ƒ 7} qÿ W| S(   s*   
        Apply `self` to `elem`.

        s1   The supplied element doesn't belong to the domaint   originaliÿÿÿÿi    (   R   R   R   t   tuplet   _applyt
   ValueErrorR   R   R   R   R   R+   R8   t
   array_formt   abs(
   R   t   elemR0   R   t   valueR    R!   R/   t   _t   p(    (    s@   lib/python2.7/site-packages/sympy/combinatorics/homomorphisms.pyRD   ˜   s,     	
	
c         C  s   |  j  | ƒ S(   N(   RD   (   R   RH   (    (    s@   lib/python2.7/site-packages/sympy/combinatorics/homomorphisms.pyt   __call__¸   s    c         C  s   |  j  ƒ  j ƒ  d k S(   s9   
        Check if the homomorphism is injective

        i   (   R2   R5   (   R   (    (    s@   lib/python2.7/site-packages/sympy/combinatorics/homomorphisms.pyt   is_injective»   s    c         C  sa   d d l  m } |  j ƒ  j ƒ  } |  j j ƒ  } | | j k rS | | j k rS d S| | k Sd S(   s:   
        Check if the homomorphism is surjective

        iÿÿÿÿ(   R	   N(   R4   R	   R   R5   R   R6   R   (   R   R	   t   imt   oth(    (    s@   lib/python2.7/site-packages/sympy/combinatorics/homomorphisms.pyt   is_surjectiveÂ   s    c         C  s   |  j  ƒ  o |  j ƒ  S(   s5   
        Check if `self` is an isomorphism.

        (   RM   RP   (   R   (    (    s@   lib/python2.7/site-packages/sympy/combinatorics/homomorphisms.pyt   is_isomorphismÏ   s    c         C  s   |  j  ƒ  j ƒ  d k S(   ss   
        Check is `self` is a trivial homomorphism, i.e. all elements
        are mapped to the identity.

        i   (   R   R5   (   R   (    (    s@   lib/python2.7/site-packages/sympy/combinatorics/homomorphisms.pyt
   is_trivialÖ   s    c           sY   ˆ  j  ƒ  j ˆ j ƒ s' t d ƒ ‚ n  ‡  ‡ f d †  ˆ  j Dƒ } t ˆ  j ˆ j | ƒ S(   s°   
        Return the composition of `self` and `other`, i.e.
        the homomorphism phi such that for all g in the domain
        of `other`, phi(g) = self(other(g))

        s?   The image of `other` must be a subgroup of the domain of `self`c           s%   i  |  ] } ˆ ˆ  | ƒ ƒ | “ q S(    (    (   t   .0R!   (   t   otherR   (    s@   lib/python2.7/site-packages/sympy/combinatorics/homomorphisms.pys
   <dictcomp>è   s   	 (   R   t   is_subgroupR   RE   R   R
   R   (   R   RT   R   (    (   RT   R   s@   lib/python2.7/site-packages/sympy/combinatorics/homomorphisms.pyt   composeÞ   s    c           sd   t  | t ƒ s# | j ˆ  j ƒ r2 t d ƒ ‚ n  | } ‡  f d †  | j Dƒ } t | ˆ  j | ƒ S(   sh   
        Return the restriction of the homomorphism to the subgroup `H`
        of the domain.

        s'   Given H is not a subgroup of the domainc           s   i  |  ] } ˆ  | ƒ | “ q S(    (    (   RS   R!   (   R   (    s@   lib/python2.7/site-packages/sympy/combinatorics/homomorphisms.pys
   <dictcomp>ô   s   	 (   R   R   RU   R   RE   R   R
   R   (   R   t   HR   R   (    (   R   s@   lib/python2.7/site-packages/sympy/combinatorics/homomorphisms.pyt   restrict_toë   s
    #c         C  sØ   | j  |  j ƒ  ƒ s$ t d ƒ ‚ n  g  } t |  j ƒ  j ƒ } x’ | j D]‡ } |  j | ƒ } | | k r† | j | ƒ t | ƒ } n  xG |  j ƒ  j D]6 } | | | k r– | j | | ƒ t | ƒ } q– q– WqI W| S(   s„   
        Return the subgroup of the domain that is the inverse image
        of the subgroup `H` of the homomorphism image

        s&   Given H is not a subgroup of the image(	   RU   R   RE   R   R   R   R.   R:   R2   (   R   RW   R    t   Pt   ht   h_iR   (    (    s@   lib/python2.7/site-packages/sympy/combinatorics/homomorphisms.pyt   invert_subgroup÷   s    (   t   __name__t
   __module__t   __doc__R   R%   R.   R2   R1   R   RD   RL   RM   RP   RQ   RR   RV   RX   R\   (    (    (    s@   lib/python2.7/site-packages/sympy/combinatorics/homomorphisms.pyR
   
   s    			#	*					 							c         C  s¤  t  |  t t t f ƒ s' t d ƒ ‚ n  t  | t t t f ƒ sN t d ƒ ‚ n  |  j } t g  | D] } | | k ^ qa ƒ r‹ t d ƒ ‚ n  t g  | D] } | | k ^ q• ƒ r¿ t d ƒ ‚ n  | rì t | ƒ t | ƒ k rì t d ƒ ‚ n  t	 | ƒ } t	 | ƒ } | j
 | j g t | ƒ t | ƒ ƒ | j
 g  | D] } | | k r8| ^ q8ƒ t t | | ƒ ƒ } | r”t |  | | ƒ r”t d ƒ ‚ n  t |  | | ƒ S(   sy  
    Create (if possible) a group homomorphism from the group `domain`
    to the group `codomain` defined by the images of the domain's
    generators `gens`. `gens` and `images` can be either lists or tuples
    of equal sizes. If `gens` is a proper subset of the group's generators,
    the unspecified generators will be mapped to the identity. If the
    images are not specified, a trivial homomorphism will be created.

    If the given images of the generators do not define a homomorphism,
    an exception is raised.

    If `check` is `False`, don't check whether the given images actually
    define a homomorphism.

    s   The domain must be a groups   The codomain must be a groupsC   The supplied generators must be a subset of the domain's generatorss+   The images must be elements of the codomains>   The number of images must be equal to the number of generatorss-   The given images do not define a homomorphism(   R   R   R   R   t	   TypeErrorR   t   anyRE   R-   R   t   extendR   t   dictt   zipt   _check_homomorphismR
   (   R   R   R    R   t   checkR   R!   (    (    s@   lib/python2.7/site-packages/sympy/combinatorics/homomorphisms.pyt   homomorphism  s&    	%%',c           s  t  ˆ  d ƒ r ˆ  j } n ˆ  j ƒ  j ‰ ˆ  j ƒ  j } | j ‰ ‡  ‡ ‡ ‡ f d †  } x¦ | D]ž } t | t ƒ ræ | j | | ƒ ˆ ƒ } | d  k rõ | j	 ƒ  } | j | | ƒ ˆ ƒ } | d  k rã | rã t
 d ƒ ‚ qã qõ n | | ƒ j } | sa t Sqa Wt S(   Nt   relatorsc           sÞ   |  j  r ˆ Sˆ } |  j } d } d } x« | t |  ƒ k  rÕ | | d } t ˆ  t ƒ rw ˆ  j ˆ j |  | ƒ } n
 |  | } | ˆ k r¢ | ˆ | | } n | ˆ | d | } | t | ƒ 7} | d 7} q+ W| Sd  S(   Ni    i   iÿÿÿÿ(   R   RF   R-   R   R   R   t   indexRG   (   R>   R"   t   r_arrR/   t   jt   powerR$   (   R   R    R   R   (    s@   lib/python2.7/site-packages/sympy/combinatorics/homomorphisms.pyR   =  s"    			
sÖ   Can't determine if the images define a homomorphism. Try increasing the maximum number of rewriting rules (group._rewriting_system.set_max(new_value); the current value is stored in group._rewriting_system.maxeqns)(   t   hasattrRh   t   presentationR   R   R   R   t   equalsR   t   make_confluentt   RuntimeErrorR   t   FalseR8   (   R   R   R   t   relsR   R>   R$   t   success(    (   R   R    R   R   s@   lib/python2.7/site-packages/sympy/combinatorics/homomorphisms.pyRe   5  s$    	c           sÕ   d d l  m ‰  d d l m } | t ˆ ƒ ƒ } | j ‰ t ˆ ƒ ‰ ‡  ‡ ‡ f d †  |  j Dƒ } |  j d ˆ ƒ t	 |  | | ƒ } t |  j
 ƒ t ˆ ƒ k r¼ |  j
 t ˆ ƒ | _ n t |  j g ƒ | _ | S(   s‘   
    Return the homomorphism induced by the action of the permutation
    group `group` on the set `omega` that is closed under the action.

    iÿÿÿÿ(   R&   (   t   SymmetricGroupc      	     sC   i  |  ]9 } ˆ ˆ  g  ˆ D] } ˆ j  | | Aƒ ^ q ƒ | “ q S(    (   Ri   (   RS   R!   t   o(   R&   R   t   omega(    s@   lib/python2.7/site-packages/sympy/combinatorics/homomorphisms.pys
   <dictcomp>|  s   	 t   base(   R(   R&   t    sympy.combinatorics.named_groupsRu   R-   R   R   R   t   _schreier_simsR
   t   basic_stabilizersR   R   (   t   groupRw   Ru   R   R   RW   (    (   R&   R   Rw   s@   lib/python2.7/site-packages/sympy/combinatorics/homomorphisms.pyt   orbit_homomorphismq  s    	c   	        s	  d d l  m ‰  d d l m } t | ƒ } d } g  ‰ d g | ‰ xH t | ƒ D]: } | | | k rR ˆ j | ƒ | ˆ | <| d 7} qR qR Wx& t | ƒ D] } ˆ | | ˆ | <q W| | ƒ } t | ƒ ‰ ‡  ‡ ‡ ‡ f d †  |  j Dƒ } t	 |  | | ƒ } | S(   sZ  
    Return the homomorphism induced by the action of the permutation
    group `group` on the block system `blocks`. The latter should be
    of the same form as returned by the `minimal_block` method for
    permutation groups, namely a list of length `group.degree` where
    the i-th entry is a representative of the block i belongs to.

    iÿÿÿÿ(   R&   (   Ru   i    i   c           s>   i  |  ]4 } ˆ  g  ˆ D] } ˆ ˆ | | A^ q ƒ | “ q S(    (    (   RS   R!   R/   (   R&   t   bR   RK   (    s@   lib/python2.7/site-packages/sympy/combinatorics/homomorphisms.pys
   <dictcomp>¥  s   	 N(
   R(   R&   Ry   Ru   R-   R   R,   R:   R   R
   (	   R|   t   blocksRu   t   nt   mR/   R   R   RW   (    (   R&   R~   R   RK   s@   lib/python2.7/site-packages/sympy/combinatorics/homomorphisms.pyt   block_homomorphism…  s$    	
"c         C  s½  t  |  t t f ƒ s$ t d ƒ ‚ n  t  | t t f ƒ sH t d ƒ ‚ n  t  |  t ƒ rÚ t  | t ƒ rÚ t |  ƒ }  t | ƒ } |  j | j k rÚ |  j j ƒ  | j j ƒ  k rÚ | s¸ t St t	 |  | |  j | j ƒ f Sn  | } |  j
 ƒ  } | j
 ƒ  } | t j k rt d ƒ ‚ n  t  | t ƒ rX| t j k rCt d ƒ ‚ n  | j ƒ  \ } } n  | | k sv|  j | j k rŠ| s€t St d f S| s¸| } t | t | ƒ ƒ d k r¸t Sn  t |  j ƒ } xß t j | t | ƒ ƒ D]Å }	 t |	 ƒ }
 |
 j | j g t |  j ƒ t |
 ƒ ƒ t t | |
 ƒ ƒ } t |  | | ƒ ràt  | t ƒ rd| j |
 ƒ }
 n  t	 |  | |  j |
 d t ƒ} | j ƒ  r¥| s˜t St | f SqàqàW| s³t St d f S(   sÏ  
    Compute an isomorphism between 2 given groups.

    Parameters
    ==========

        G (a finite `FpGroup` or a `PermutationGroup`) -- First group
        H (a finite `FpGroup` or a `PermutationGroup`) -- Second group
        isomorphism (boolean) -- This is used to avoid the computation of homomorphism
                                 when the user only wants to check if there exists
                                 an isomorphism between the groups.

    Returns
    =======

    If isomorphism = False -- Returns a boolean.
    If isomorphism = True  -- Returns a boolean and an isomorphism between `G` and `H`.

    Examples
    ========

    >>> from sympy.combinatorics import Permutation
    >>> Permutation.print_cyclic = True
    >>> from sympy.combinatorics.perm_groups import PermutationGroup
    >>> from sympy.combinatorics.free_groups import free_group
    >>> from sympy.combinatorics.fp_groups import FpGroup
    >>> from sympy.combinatorics.homomorphisms import homomorphism, group_isomorphism
    >>> from sympy.combinatorics.named_groups import DihedralGroup, AlternatingGroup

    >>> D = DihedralGroup(8)
    >>> p = Permutation(0, 1, 2, 3, 4, 5, 6, 7)
    >>> P = PermutationGroup(p)
    >>> group_isomorphism(D, P)
    (False, None)

    >>> F, a, b = free_group("a, b")
    >>> G = FpGroup(F, [a**3, b**3, (a*b)**2])
    >>> H = AlternatingGroup(4)
    >>> (check, T) = group_isomorphism(G, H)
    >>> check
    True
    >>> T(b*a*b**-1*a**-1*b**-1)
    (0 2 3)

    Notes
    =====

    Uses the approach suggested by Robert Tarjan to compute the isomorphism between two groups.
    First, the generators of `G` are mapped to the elements of `H` and
    we check if the mapping induces an isomorphism.

    s2   The group must be a PermutationGroup or an FpGroups<   Isomorphism methods are not implemented for infinite groups.i   Rf   N(   R   R   R   R`   R   R   Rh   t   sortR8   Rg   R5   R	   R6   R7   t   _to_perm_groupt
   is_abelianRr   R   R   R   R   t	   itertoolst   permutationsR-   Rb   R   Rc   Rd   Re   R.   RQ   (   R;   RW   t   isomorphismt   _Ht   g_ordert   h_ordert   h_isomorphismR€   R    t   subsetR   t   _imagest   T(    (    s@   lib/python2.7/site-packages/sympy/combinatorics/homomorphisms.pyt   group_isomorphism©  sX    50"
*c         C  s   t  |  | d t ƒS(   s  
    Check if the groups are isomorphic to each other

    Parameters
    ==========

        G (a finite `FpGroup` or a `PermutationGroup`) -- First group
        H (a finite `FpGroup` or a `PermutationGroup`) -- Second group

    Returns
    =======

    boolean
    Rˆ   (   R   Rr   (   R;   RW   (    (    s@   lib/python2.7/site-packages/sympy/combinatorics/homomorphisms.pyt   is_isomorphic  s    (   t
   __future__R    R   R†   t   sympy.combinatorics.fp_groupsR   R   R   R)   R   t   sympy.combinatorics.perm_groupsR   t   sympy.core.numbersR   t   sympy.ntheory.factor_R   R4   R	   t   objectR
   R8   Rg   Re   R}   R‚   R   R‘   (    (    (    s@   lib/python2.7/site-packages/sympy/combinatorics/homomorphisms.pyt   <module>   s   ÿ )	<		$q