
    gI                         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dS )    N)FpGroup
FpSubgroupsimplify_presentation)	FreeGroup)PermutationGroup)igcd)totient)Sc                   l    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dS )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                 Z    || _         || _        || _        d | _        d | _        d | _        d S N)domaincodomainimages	_inverses_kernel_image)selfr   r   r   s       ]/var/www/html/ai-engine/env/lib/python3.11/site-packages/sympy/combinatorics/homomorphisms.py__init__zGroupHomomorphism.__init__   s0         c                    |                                  }i }t          | j                                                  D ]}| j        |         }||v s|j        s|||<    t          | j        t                    r|j        }n|j	        }|D ]x}||v s|j        r| j
        j        }t          | j        t                    r|j        |         ddd         }n|}|D ]#}	|	|v r|||	         z  }|||	dz           dz  z  }$|||<   y|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   s9    

dk&&(()) 	  	 AAAMM} "dm%566 	$$DD#D 	 	AH}}}$A$-)9:: .q1$$B$7 . .==(1+AA(1b5/2--AAHQKKr   c                     ddl m} ddlm} t	          |||f          rt	           j        t                    r j                            |          } j         	                                 _         
                                } j        j        }t	           j        t                    r|                    |          ddd         }n|}t          t!          |                    D ]B}||         }|j        r| j        v r| j        |         z  },| j        |dz           dz  z  }C|S t	          |t$                    r fd|D             S dS )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   c                 :    g | ]}                     |          S  )invert.0er   s     r   
<listcomp>z,GroupHomomorphism.invert.<locals>.<listcomp>k   s#    ...qDKKNN...r   )sympy.combinatoricsr/   sympy.combinatorics.free_groupsr0   r   r   r   reducer   r,   r   r   r"   r   generator_productrangelenr   r   )	r   r(   r/   r0   r   r)   r'   ir+   s	   `        r   r3   zGroupHomomorphism.invert?   s~    	433333DDDDDDa+'7899 	/$-11 ,M((++~%!%JJLLE$A$-)9:: ..q11$$B$7 3t99%% 4 4G= &&$.++AA$.B/33AAH4   	/....A....	/ 	/r   c                 P    | j         |                                 | _         | j         S )z0
        Compute the kernel of `self`.

        )r   _compute_kernelr   s    r   kernelzGroupHomomorphism.kernelm   s'    
 <//11DL|r   c                    | j         }|                                }|t          j        u rt	          d          g }t          |t                    rt          |j                  }nt          ||d          }| 	                                                                }|                                |z  |k    r|
                                }||                      | |                    dz  z  }||vrL|                    |           t          |t                    rt          |          }nt          ||d          }|                                |z  |k    |S )Nz9Kernel computation is not implemented for infinite groupsT)normalr   )r   orderr
   InfinityNotImplementedErrorr   r   r"   r   r   randomr3   append)r   GG_orderr'   Kr>   rr%   s           r   r@   z!GroupHomomorphism._compute_kernelv   sF   K''))aj  %KM M Ma)** 	1 ,,AA1d4000AJJLL  ggiikW$$

A$++dd1gg&&**AzzAa!122 9(..AA"1d4888A ggiikW$$ r   c                 ,   | j         t          t          | j                                                            }t          | j        t                    r | j                            |          | _         nt          | j        |          | _         | j         S )z/
        Compute the image of `self`.

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

        c                 :    g | ]}                     |          S r2   _applyr4   s     r   r7   z,GroupHomomorphism._apply.<locals>.<listcomp>   s#    5551A555r   z2The supplied element does not belong to the domainT)originalr   r   )r   r   r   tuple
ValueErrorr   r   r"   r   r   r;   
array_formabs)	r   elemr   valuer'   r(   r>   _ps	   `        r   rU   zGroupHomomorphism._apply   sU   
 t{""$u.. 655555555QRRR 	 =))[FM*E$+'788  {44TD4II 8 8ADK'' &q	% &q"ur 1% 7	8  O    DAq1uu GRK G!&)Q,.EQKAAr   c                 ,    |                      |          S r   rT   )r   r[   s     r   __call__zGroupHomomorphism.__call__   s    {{4   r   c                 V    |                                                                  dk    S )z9
        Check if the homomorphism is injective

           )rB   rE   rA   s    r   is_injectivezGroupHomomorphism.is_injective   s#    
 {{}}""$$))r   c                     |                                                                  }| j                                        }|t          j        u r|t          j        u rdS ||k    S )z:
        Check if the homomorphism is surjective

        N)r   rE   r   r
   rF   )r   imoths      r   is_surjectivezGroupHomomorphism.is_surjective   sX    
 ZZ\\!!m!!##qz 1 149r   c                 R    |                                  o|                                 S )z5
        Check if `self` is an isomorphism.

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

        rb   )r   rE   rA   s    r   
is_trivialzGroupHomomorphism.is_trivial   s#     zz||!!##q((r   c                                                                            j                  st          d           fdj        D             }t          j         j        |          S )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`c                 :    i | ]}|  |                    S r2   r2   )r5   r(   otherr   s     r   
<dictcomp>z-GroupHomomorphism.compose.<locals>.<dictcomp>   s+    :::!TT%%((^^:::r   )r   is_subgroupr   rX   r   r   r   )r   rn   r   s   `` r   composezGroupHomomorphism.compose   sq     {{}}((55 	, + , , ,:::::U\::: t}fEEEr   c                      t          |t                    r|                     j                  st	          d          |} fd|j        D             }t          | j        |          S )zh
        Return the restriction of the homomorphism to the subgroup `H`
        of the domain.

        z'Given H is not a subgroup of the domainc                 (    i | ]}| |          S r2   r2   )r5   r(   r   s     r   ro   z1GroupHomomorphism.restrict_to.<locals>.<dictcomp>   s#    333!TT!WW333r   )r   r   rp   r   rX   r!   r   r   )r   Hr   r   s   `   r   restrict_tozGroupHomomorphism.restrict_to   sr     !-.. 	HammDK6P6P 	HFGGG3333al333 ???r   c                    |                     |                                           st          d          g }t          |                                 j                  }|j        D ]}|                     |          }||vr$|                    |           t          |          }|                                 j        D ]0}||z  |vr'|                    ||z             t          |          }1|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)	rp   r   rX   r   r"   r!   r3   rI   rB   )r   rt   r'   Phh_ir%   s          r   invert_subgroupz!GroupHomomorphism.invert_subgroup   s     }}TZZ\\** 	GEFFFTZZ\\233 	/ 	/A++a..C!||C   $T**[[]]- / /S5>>KK#&&&(..A/ r   N)__name__
__module____qualname____doc__r   r,   r3   rB   r@   r   rU   r`   rc   rg   ri   rk   rq   ru   rz   r2   r   r   r   r   	   s          ! ! !F,/ ,/ ,/\    .    @! ! !* * *
 
 
< < <) ) )F F F
@ 
@ 
@    r   r   r2   Tc                 x   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                    k    rt          d          t                    t          |          }|
                    j        gt                    t          |          z
  z             
                    fdD                        t          t          |                    }|r t          | |          st          d	          t          | |          S )
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 V  	d S r   r2   )r5   r(   r!   s     r   	<genexpr>zhomomorphism.<locals>.<genexpr>#  s'      --1qJ------r   zCThe supplied generators must be a subset of the domain's generatorsc              3       K   | ]}|v V  	d S r   r2   )r5   r(   r   s     r   r   zhomomorphism.<locals>.<genexpr>%  s'      --qH}------r   z+The images must be elements of the codomainz>The number of images must be equal to the number of generatorsc                     g | ]}|v|	S r2   r2   )r5   r(   r'   s     r   r7   z homomorphism.<locals>.<listcomp>/  s    888q!4-----r   z-The given images do not define a homomorphism)r   r   r   r   	TypeErrorr!   allrX   r=   r   extendr"   dictzip_check_homomorphismr   )r   r   r'   r   checkr!   s    ``  @r   homomorphismr     s     f/)DEE 64555h!17I FGG 86777"J--------- `^___----f----- HFGGG [#f++T**YZZZ::D&\\F
MM8$%s:s6{{'BCDDDKK8888J888999#d6""##F J(6BB JHIIIVXv666r   c                    t          | d          r| n|                                 }|j        }|j        }d |D             }t	          t          || j                            |j        fd}|D ]}t          |t                    rh|	                     ||                    }	|	F|
                                }
|	                     ||                    }	|	|
st          d          n ||          j        }	|	s dS dS )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.

    relatorsc                 (    g | ]}|j         d          S )r   )ext_rep)r5   r(   s     r   r7   z'_check_homomorphism.<locals>.<listcomp>F  s    ***qy|***r   c                 R    }| j         D ]\  }}|         }||         |z  z  }|S r   )rY   )rM   r)   symbolpowerr(   r"   r   symbols_to_domain_generatorss        r   r   z#_check_homomorphism.<locals>._imageJ  sA    \ 	" 	"MFE,V4AE!!AAr   NzCan'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!   r   r   r"   r   r   equalsmake_confluentRuntimeErrorr   )r   r   r   presrelsr'   symbolsr   rM   r+   successr"   r   s     `        @@r   r   r   6  sO    VZ00K66f6I6I6K6KD=D?D**T***G#'GV5F(G(G#H#H  H         h(( 	&q		844Ay #1133OOFF1IIx889W9& (+ , , , q		%A 	55	4r   c                    ddl m ddlm}  |t	                              }|j        t                    fd| j        D             }|                                t          | ||          }t	          | j
                  t	                    k    r | j
        t	                             |_        nt          | j        g          |_        |S )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.   SymmetricGroupc                 J    i | ] fd D                       z  S )c                 @    g | ]}                     |z            S r2   )index)r5   or(   omegas     r   r7   z1orbit_homomorphism.<locals>.<dictcomp>.<listcomp>r  s)    &G&G&GAu{{1Q3'7'7&G&G&Gr   r2   )r5   r(   r/   r"   r   s    @r   ro   z&orbit_homomorphism.<locals>.<dictcomp>r  sC    cccQa++&G&G&G&G&G&G&G&GHHHcccr   )base)r8   r/    sympy.combinatorics.named_groupsr   r=   r"   r   r!   _schreier_simsr   basic_stabilizersr   r   )groupr   r   r   r   rt   r/   r"   s    `    @@r   orbit_homomorphismr   g  s     0/////??????~c%jj))H HKKEccccccRWRbcccF	e$$$%622A
5"##c%jj00+CJJ7		$en%566	Hr   c                   	
 ddl m	 ddlm} t	          |          }d}g dg|z  
t          |          D ]-}||         |k    r                    |           |
|<   |dz  }.t          |          D ]}
||                  
|<    ||          }t          |          	
fd| j        D             }t          | ||          }|S )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   Nrb   c                 F    i | ] fd D                       S )c                 2    g | ]}|         z           S r2   r2   )r5   r>   br(   r^   s     r   r7   z1block_homomorphism.<locals>.<dictcomp>.<listcomp>  s%    :::Aa!Qi:::r   r2   )r5   r(   r/   r   r"   r^   s    @r   ro   z&block_homomorphism.<locals>.<dictcomp>  sA    VVVa:::::::::;;VVVr   )	r8   r/   r   r   r=   r<   rI   r!   r   )r   blocksr   nmr>   r   r   rt   r/   r   r"   r^   s            @@@@r   block_homomorphismr   {  s    0/////??????FA 	
A
A	qA1XX  !9>>HHQKKKAaDFA1XX  |!~a  HQxxHVVVVVVVUEUVVVF%622AHr   c                    t          | t          t          f          st          d          t          |t          t          f          st          d          t          | t                    rt          |t                    rt	          |           } t	          |          }| j        |j        k    rV| j                                        |j                                        k    r"|sdS dt          | || j        |j                  fS |}| 	                                }|	                                }|t          j        u rt          d          t          |t                    r4|t          j        u rt          d          |                                \  }}||k    s| j        |j        k    r|sdS dS |s%|}t          |t!          |                    dk    rdS t#          | j                  }t%          j        |t)          |                    D ]}	t#          |	          }
|
                    |j        gt)          | j                  t)          |
          z
  z             t/          t1          ||
                    }t3          | ||          rbt          |t                    r|                    |
          }
t          | || j        |
d          }|                                r|s dS d|fc S |sdS dS )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)FNrb   )r   )r   r   r   r   r   r!   r   sortr   rE   r
   rF   rG   _to_perm_group
is_abelianr   r	   r   	itertoolspermutationsr=   r   r"   r   r   r   r3   ri   )rJ   rt   isomorphism_Hg_orderh_orderh_isomorphismr   r'   subsetr   _imagesTs                r   group_isomorphismr     s   p a*G455 NLMMMa*G455 NLMMM!W J*Q"8"8 J!!$$!!$$ <1<''QZ,=,=,?,?AJCTCTCVCV,V,V t,q!Q\1<HHII 
BggiiGggiiG!*!"`aaa!W /aj  %&deee,,..M7 < < 	5}  GAJJA%%4 D(SYY77 ! !fr{mS%6%6s6{{%BCDDDs4''((q"g.. 	!!W%% 6&--f55aAL&FFFA!! !"  44ay    u=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   )rJ   rt   s     r   is_isomorphicr     s    $ Qu5555r   )r2   T)T)r   sympy.combinatorics.fp_groupsr   r   r   r9   r   sympy.combinatorics.perm_groupsr   sympy.core.intfuncr   %sympy.functions.combinatorial.numbersr	   sympy.core.singletonr
   r   r   r   r   r   r   r   r2   r   r   <module>r      s0       T T T T T T T T T T 5 5 5 5 5 5 < < < < < < # # # # # # 9 9 9 9 9 9 " " " " " "B B B B B B B BH'7 '7 '7 '7R/ / /b  (" " "Hr r r rh6 6 6 6 6r   