
    wgI                         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  G d d	      Zdd
Zd Zd Zd ZddZd Zy)    N)FpGroup
FpSubgroupsimplify_presentation)	FreeGroup)PermutationGroup)igcd)totient)Sc                   j    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d Zy)GroupHomomorphismz
    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                 X    || _         || _        || _        d | _        d | _        d | _        y N)domaincodomainimages	_inverses_kernel_image)selfr   r   r   s       f/home/mcse/projects/flask/flask-venv/lib/python3.12/site-packages/sympy/combinatorics/homomorphisms.py__init__zGroupHomomorphism.__init__   s,         c                 :   | j                         }i }t        | j                  j                               D ](  }| j                  |   }||v r|j                  r$|||<   * t        | j                  t              r|j                  }n|j                  }|D ]  }||v s|j                  r| j                  j                  }t        | j                  t              r|j                  |   ddd   }n|}|D ]  }	|	|v r	|||	   z  }|||	dz     dz  z  } |||<    |S )z
        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

        N)imagelistr   keysis_identity
isinstancer   r   strong_gens
generatorsr   identity_strong_gens_slp)
r   r   inverseskvgensgwpartsss
             r   _invszGroupHomomorphism._invs   s'    

dkk&&() 	 AAAM}}		 
 dmm%56$$D##D 	AH}$$A$--)9:..q1$B$7 .=(1+A(1b5/2--A	.
 HQK	 r   c                    ddl m} ddlm} t	        |||f      rt	        | j
                  t              r| j
                  j                  |      }| j                  | j                         | _        | j                         }| j                  j                  }t	        | j
                  t              r|j                  |      ddd   }n|}t        t!        |            D ]M  }||   }|j"                  r|| j                  v r|| j                  |   z  }6|| j                  |dz     dz  z  }O |S t	        |t$              r|D 	cg c]  }	| j'                  |	       c}	S yc c}	w )a  
        Return an element of the preimage of ``g`` or of each element
        of ``g`` if ``g`` is a list.

        Explanation
        ===========

        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.

        r   Permutation)FreeGroupElementNr   )sympy.combinatoricsr/   sympy.combinatorics.free_groupsr0   r   r   r   reducer   r,   r   r   r"   r   generator_productrangelenr   r   invert)
r   r(   r/   r0   r   r)   r'   ir+   es
             r   r7   zGroupHomomorphism.invert?   s4    	4Da+'789$--1MM((+~~%!%JJLE$$A$--)9:..q1$B$7 3t9% 4G==&$..++A$..B/33A4 H4 ,-.qDKKN.. !.s   E"c                 \    | j                   | j                         | _         | j                   S )z0
        Compute the kernel of `self`.

        )r   _compute_kernelr   s    r   kernelzGroupHomomorphism.kernelm   s(    
 <<//1DL||r   c                 R   | j                   }|j                         }|t        j                  u rt	        d      g }t        |t              rt        |j                        }nt        ||d      }| j                         j                         }|j                         |z  |k7  r|j                         }|| j                   | |            dz  z  }||vr;|j                  |       t        |t              rt        |      }nt        ||d      }|j                         |z  |k7  r|S )Nz9Kernel computation is not implemented for infinite groupsT)normalr   )r   orderr
   InfinityNotImplementedErrorr   r   r"   r   r   randomr7   append)r   GG_orderr'   Kr8   rr%   s           r   r;   z!GroupHomomorphism._compute_kernelv   s    KK'')ajj %KM Ma)* ,A1d40AJJL ggikW$
A$++d1g&**AzAa!12(.A"1d48A ggikW$ r   c                 L   | j                   t        t        | j                  j	                                     }t        | j                  t              r,| j                  j                  |      | _         | j                   S t        | j                  |      | _         | j                   S )z/
        Compute the image of `self`.

        )
r   r   setr   valuesr   r   r   subgroupr   )r   rK   s     r   r   zGroupHomomorphism.image   sy    
 ;;#dkk00234F$--)9:"mm44V< {{ )?{{r   c                    || j                   vr@t        |t        t        f      r|D cg c]  }| j	                  |       c}S t        d      |j                  r| j                  j                  S | j                  }| j                  j                  }t        | j                   t              rK| j                   j                  |d      }|D ]'  }|| j                  v r	||   |z  }||dz     dz  |z  }) |S d}|j                  D ]1  \  }}	|	dk  r	||   dz  }n||   }|||   |	z  z  }|t        |	      z  }3 |S c c}w )z*
        Apply `self` to `elem`.

        z2The supplied element does not belong to the domainT)originalr   r   )r   r   r   tuple_apply
ValueErrorr   r   r"   r   r   r4   
array_formabs)
r   elemr9   r   valuer'   r(   r8   _ps
             r   rP   zGroupHomomorphism._apply   sH   
 t{{"$u.0451A55QRR==)))[[FMM**E$++'78{{44TD4I 8ADKK' &q	% &q"ur 1% 7	8   OO  DAq1u GRK G!&)Q,.EQKA  / 6s   D<c                 $    | j                  |      S r   )rP   )r   rT   s     r   __call__zGroupHomomorphism.__call__   s    {{4  r   c                 D    | j                         j                         dk(  S )z9
        Check if the homomorphism is injective

           )r=   r@   r<   s    r   is_injectivezGroupHomomorphism.is_injective   s    
 {{}""$))r   c                     | j                         j                         }| j                  j                         }|t        j                  u r|t        j                  u ry||k(  S )z:
        Check if the homomorphism is surjective

        N)r   r@   r   r
   rA   )r   imoths      r   is_surjectivezGroupHomomorphism.is_surjective   sN    
 ZZ\!mm!!#qzz 19r   c                 F    | j                         xr | j                         S )z5
        Check if `self` is an isomorphism.

        )r\   r`   r<   s    r   is_isomorphismz GroupHomomorphism.is_isomorphism   s!    
   ";t'9'9';;r   c                 D    | j                         j                         dk(  S )zs
        Check is `self` is a trivial homomorphism, i.e. all elements
        are mapped to the identity.

        r[   )r   r@   r<   s    r   
is_trivialzGroupHomomorphism.is_trivial   s     zz|!!#q((r   c           	         |j                         j                  | j                        st        d      |j                  D ci c]  }| |  ||             }}t        |j                  | j                  |      S c c}w )z
        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))

        z?The image of `other` must be a subgroup of the domain of `self`)r   is_subgroupr   rQ   r   r   r   )r   otherr(   r   s       r   composezGroupHomomorphism.compose   sn     {{}((5 + , ,-2\\:!T%(^#:: t}}fEE ;s   A<c                     t        |t              r|j                  | j                        st	        d      |}|j
                  D ci c]  }| | |       }}t        || j                  |      S c c}w )zh
        Return the restriction of the homomorphism to the subgroup `H`
        of the domain.

        z'Given H is not a subgroup of the domain)r   r   rf   r   rQ   r!   r   r   )r   Hr   r(   r   s        r   restrict_tozGroupHomomorphism.restrict_to   sf     !-.ammDKK6PFGG&'ll3!T!W*33 ?? 4s   A0c                    |j                  | j                               st        d      g }t        | j                         j                        }|j
                  D ]y  }| j                  |      }||vr|j                  |       t        |      }| j                         j
                  D ])  }||z  |vs|j                  ||z         t        |      }+ { |S )z
        Return the subgroup of the domain that is the inverse image
        of the subgroup ``H`` of the homomorphism image

        z&Given H is not a subgroup of the image)	rf   r   rQ   r   r"   r!   r7   rD   r=   )r   rj   r'   Phh_ir%   s          r   invert_subgroupz!GroupHomomorphism.invert_subgroup   s     }}TZZ\*EFFTZZ\223 	/A++a.C!|C $T*[[]-- /S5>KK#&(.A/	/ r   N)__name__
__module____qualname____doc__r   r,   r7   r=   r;   r   rP   rY   r\   r`   rb   rd   rh   rk   rp    r   r   r   r   	   sW    !F,/\.@!*
<)F
@r   r   c                    t        | t        t        t        f      st	        d      t        t        t        t        f      st	        d      | j
                  t        fd|D              st        d      t        fd|D              st        d      |r"t        |      t        |      k7  rt        d      t        |      }t        |      }|j                  j                  gt              t        |      z
  z         |j                  D cg c]	  }||vs| c}       t        t        ||            }|rt        | |      st        d      t        | |      S c c}w )	a  
    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``, do not check whether the given images actually
    define a homomorphism.

    zThe domain must be a groupzThe codomain must be a groupc              3   &   K   | ]  }|v  
 y wr   ru   ).0r(   r!   s     r   	<genexpr>zhomomorphism.<locals>.<genexpr>#  s     -1qJ-   zCThe supplied generators must be a subset of the domain's generatorsc              3   &   K   | ]  }|v  
 y wr   ru   )rx   r(   r   s     r   ry   zhomomorphism.<locals>.<genexpr>%  s     -qH}-rz   z+The images must be elements of the codomainz>The number of images must be equal to the number of generatorsz-The given images do not define a homomorphism)r   r   r   r   	TypeErrorr!   allrQ   r6   r   extendr"   dictzip_check_homomorphismr   )r   r   r'   r   checkr(   r!   s    `    @r   homomorphismr     s4     f/)DE455h!17I FG677""J---^__-f--FGG#f+T*YZZ:D&\F
MM8$$%s:s6{'BCDKKJ8q!4-89#d6"#F(6BHIIVXv66 9s   	E' E'c                    t        | d      r| n| j                         }|j                  }|j                  }|D cg c]  }|j                  d    }}t        t        || j                              |j                  fd}|D ]y  }	t        |t              rQ|j                   ||	            }
|
I|j                         }|j                   ||	            }
|
|st        d       ||	      j                  }
|
ry y yc c}w )a]  
    Check that a given mapping of generators to images defines a homomorphism.

    Parameters
    ==========
    domain : PermutationGroup, FpGroup, FreeGroup
    codomain : PermutationGroup, FpGroup, FreeGroup
    images : dict
        The set of keys must be equal to domain.generators.
        The values must be elements of the codomain.

    relatorsr   c                 T    }| j                   D ]  \  }}|   }||   |z  z  } |S r   )rR   )rH   r)   symbolpowerr(   r"   r   symbols_to_domain_generatorss        r   r   z#_check_homomorphism.<locals>._imageJ  sC    \\ 	"MFE,V4AE!!A	" r   zCan'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)FT)hasattrpresentationr   r!   ext_repr   r   r"   r   r   equalsmake_confluentRuntimeErrorr   )r   r   r   presrelsr'   r(   symbolsr   rH   r+   successr"   r   s     `         @@r   r   r   6  s    VZ06f6I6I6KD==D??D%)*qyy|*G*#'GV5F5F(G#H   H  h(q	84Ay #113OOF1Ix89W& (+ , , q	%%A'( ? +s   Dc                    ddl m} ddlm}  |t	        |            }|j
                  }t        |      }| j                  D ci c].  }|| ||D cg c]  }|j                  ||z         c}      z  0 }}}| j                  |       t        | ||      }	t	        | j                        t	        |      kD  r| j                  t	        |         |	_        |	S t        | j
                  g      |	_        |	S c c}w c c}}w )z
    Return the homomorphism induced by the action of the permutation
    group ``group`` on the set ``omega`` that is closed under the action.

    r   r.   SymmetricGroup)base)r1   r/    sympy.combinatorics.named_groupsr   r6   r"   r   r!   index_schreier_simsr   basic_stabilizersr   r   )
groupomegar/   r   r   r"   r(   or   rj   s
             r   orbit_homomorphismr   g  s     0?c%j)H  HKERWRbRbcQa+&GAu{{1Q3'7&GHHHcFc	e$%62A
5""#c%j0++CJ7	 H %enn%56	H 'Hcs   C;C6,C;6C;c                    ddl m} ddlm} t	        |      }d}g }dg|z  }t        |      D ]&  }||   |k(  s|j                  |       |||<   |dz  }( t        |      D ]  }|||      ||<     ||      }	t        |      }
| j                  D ci c]"  }| ||
D cg c]  }|||   |z      c}      $ }}}t        | |	|      }|S c c}w c c}}w )ab  
    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.

    r   r.   r   Nr[   )	r1   r/   r   r   r6   r5   rD   r!   r   )r   blocksr/   r   nmrW   br8   r   r"   r(   r   rj   s                 r   block_homomorphismr   {  s     0?FA 	
A
A	qA1X !9>HHQKAaDFA	
 1X |! a HQxHEJEUEUVa:Aa!Qi:;;VFV%62AH ;Vs   CC1	CCc                 T   t        | t        t        f      st        d      t        |t        t        f      st        d      t        | t              rt        |t              rt	        |       } t	        |      }| j
                  |j
                  k(  r\| j                  j                         |j                  j                         k(  r'|sydt        | || j
                  |j
                        fS |}| j                         }|j                         }|t        j                  u rt        d      t        |t              r0|t        j                  u rt        d      |j                         \  }}||k7  s| j                  |j                  k7  r|syy|s|}t        |t!        |            dk(  ryt#        | j
                        }t%        j&                  |t)        |            D ]  }	t#        |	      }
|
j+                  |j,                  gt)        | j
                        t)        |
      z
  z         t/        t1        ||
            }t3        | ||      sot        |t              rj5                  |
      }
t        | || j
                  |
d      }|j7                         s|s yd|fc S  |syy)aE  
    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 : bool
        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 free_group, Permutation
    >>> from sympy.combinatorics.perm_groups import PermutationGroup
    >>> from sympy.combinatorics.fp_groups import FpGroup
    >>> from sympy.combinatorics.homomorphisms import 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.

    z2The group must be a PermutationGroup or an FpGroupTz<Isomorphism methods are not implemented for infinite groups.F)FNr[   )r   )r   r   r   r|   r   r!   r   sortr   r@   r
   rA   rB   _to_perm_group
is_abelianr   r	   r   	itertoolspermutationsr6   r~   r"   r   r   r   r7   rb   )rE   rj   isomorphism_Hg_orderh_orderh_isomorphismr   r'   subsetr   _imagesTs                r   group_isomorphismr     s;   p a*G45LMMa*G45LMM!W*Q"8!!$!!$ <<1<<'QZZ,=,=,?AJJCTCTCV,V,q!Q\\1<<HII 
BggiGggiG!**!"`aa!Wajj %&dee,,.M7 < GAJA% D((SY7 !fr{{mS%6s6{%BCDs4'(q"g.!W%&--f5aALL&FA!"ay ! r   c                     t        | |d      S )a  
    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
    F)r   )r   )rE   rj   s     r   is_isomorphicr     s    $ Qu55r   )ru   T)T)r   sympy.combinatorics.fp_groupsr   r   r   r2   r   sympy.combinatorics.perm_groupsr   sympy.core.intfuncr   %sympy.functions.combinatorial.numbersr	   sympy.core.singletonr
   r   r   r   r   r   r   r   ru   r   r   <module>r      sM     T T 5 < # 9 "B BH'7R/b("Hrh6r   