U
    ZÊ¹j†+  ã                   @   s`   d dl mZ d dlmZ ejZdd„ Zddd„Zdd	„ Zddd„Zddd„Z	dd„ Z
dd„ Zd
S )é    ©ÚPermutation)Ú_distribute_gens_by_basec                 C   s   dd„ | D ƒdd„ |D ƒkS )ao  
    Compare two lists of permutations as sets.

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

    This is used for testing purposes. Since the array form of a
    permutation is currently a list, Permutation is not hashable
    and cannot be put into a set.

    Examples
    ========

    >>> from sympy.combinatorics.permutations import Permutation
    >>> from sympy.combinatorics.testutil import _cmp_perm_lists
    >>> a = Permutation([0, 2, 3, 4, 1])
    >>> b = Permutation([1, 2, 0, 4, 3])
    >>> c = Permutation([3, 4, 0, 1, 2])
    >>> ls1 = [a, b, c]
    >>> ls2 = [b, c, a]
    >>> _cmp_perm_lists(ls1, ls2)
    True

    c                 S   s   h | ]}t |ƒ’qS © ©Útuple©Ú.0Úar   r   ú[/var/www/html/bwave/python/venv/lib/python3.8/site-packages/sympy/combinatorics/testutil.pyÚ	<setcomp>    s     z"_cmp_perm_lists.<locals>.<setcomp>c                 S   s   h | ]}t |ƒ’qS r   r   r   r   r   r   r   !   s     r   )ÚfirstÚsecondr   r   r   Ú_cmp_perm_lists   s    ÿr   Fc                    sÖ   ddl m} ddlm‰  t|dƒrœt| jdd�ƒ}dd„ |jD ƒ‰‡ ‡fd	d
„}g }|s||D ]}||ƒr\| t	 
|¡¡ q\n|D ]}||ƒr€| |¡ q€|S t|dƒr¶t| ||ƒ|ƒS t|dƒrÒt| ||gƒ|ƒS d S )Nr   ©ÚPermutationGroup)Ú_af_commutes_withÚ
generatorsT©Úafc                 S   s   g | ]
}|j ‘qS r   )Z_array_form©r	   Úxr   r   r   Ú
<listcomp>B   s     z+_naive_list_centralizer.<locals>.<listcomp>c                    s   t ‡‡ fdd„ˆD ƒƒS )Nc                 3   s   | ]}ˆ ˆ|ƒV  qd S ©Nr   ©r	   Úgen)r   r   r   r   Ú	<genexpr>C   s     z<_naive_list_centralizer.<locals>.<lambda>.<locals>.<genexpr>)Úall©r   ©r   Úgensr   r   Ú<lambda>C   ó    z)_naive_list_centralizer.<locals>.<lambda>ÚgetitemÚ
array_form)Úsympy.combinatorics.perm_groupsr   Ú sympy.combinatorics.permutationsr   ÚhasattrÚlistÚgenerate_diminor   Úappendr   Z_af_newÚ_naive_list_centralizer)ÚselfÚotherr   r   ÚelementsZcommutes_with_gensZcentralizer_listÚelementr   r   r   r+   $   s&    


r+   c                 C   sp   ddl m} t||ƒ}| }tt|ƒƒD ]4}||| ƒ}| ¡ | ¡ krL dS | || ¡}q&| ¡ dkrldS dS )aÏ  
    Verify the correctness of a base and strong generating set.

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

    This is a naive implementation using the definition of a base and a strong
    generating set relative to it. There are other procedures for
    verifying a base and strong generating set, but this one will
    serve for more robust testing.

    Examples
    ========

    >>> from sympy.combinatorics.named_groups import AlternatingGroup
    >>> from sympy.combinatorics.testutil import _verify_bsgs
    >>> A = AlternatingGroup(4)
    >>> A.schreier_sims()
    >>> _verify_bsgs(A, A.base, A.strong_gens)
    True

    See Also
    ========

    sympy.combinatorics.perm_groups.PermutationGroup.schreier_sims

    r   r   Fé   T)r%   r   r   ÚrangeÚlenÚorderZ
stabilizer)ÚgroupÚbaser    r   Zstrong_gens_distrZcurrent_stabilizerÚiÚ	candidater   r   r   Ú_verify_bsgsT   s    
r8   Nc                 C   s:   |dkr|   |¡}t|jdd�ƒ}t| |dd�}t||ƒS )a3  
    Verify the centralizer of a group/set/element inside another group.

    This is used for testing ``.centralizer()`` from
    ``sympy.combinatorics.perm_groups``

    Examples
    ========

    >>> from sympy.combinatorics.named_groups import (SymmetricGroup,
    ... AlternatingGroup)
    >>> from sympy.combinatorics.perm_groups import PermutationGroup
    >>> from sympy.combinatorics.permutations import Permutation
    >>> from sympy.combinatorics.testutil import _verify_centralizer
    >>> S = SymmetricGroup(5)
    >>> A = AlternatingGroup(5)
    >>> centr = PermutationGroup([Permutation([0, 1, 2, 3, 4])])
    >>> _verify_centralizer(S, A, centr)
    True

    See Also
    ========

    _naive_list_centralizer,
    sympy.combinatorics.perm_groups.PermutationGroup.centralizer,
    _cmp_perm_lists

    NTr   )Zcentralizerr(   r)   r+   r   )r4   ÚargZcentrZ
centr_listZcentr_list_naiver   r   r   Ú_verify_centralizer}   s
    
r:   c                    s’   ddl m} |d kr|  |¡}tƒ }t|dƒr6|j}n t|dƒrF|}nt|dƒrV|g}|  ¡ D ]‰ | ‡ fdd„|D ƒ¡ q^|t|ƒƒ}| 	|¡S )Nr   r   r   Ú__getitem__r$   c                 3   s   | ]}|ˆ A V  qd S r   r   r   ©Úelr   r   r   Ä   s     z)_verify_normal_closure.<locals>.<genexpr>)
r%   r   Znormal_closureÚsetr'   r   r)   Úupdater(   Zis_subgroup)r4   r9   Úclosurer   Z
conjugatesZ
subgr_gensZnaive_closurer   r<   r   Ú_verify_normal_closure¡   s    



rA   c                 G   s¶  ddl m} ddlm}m} ddlm} g }tt|ƒƒD ],}	||	 \}
}}}| 	|
|g g| |f¡ q8||Ž \}}}||||d ƒ}t
|tƒr d}|g}|g}nt|ƒ}g }t|ƒD ]"}	| |||	 ||	 |d ƒ¡ q´||ƒ}|dd„ |D ƒƒ}t|jd	d
�ƒ}| j} tƒ }|jd	d
�D ]4}|| |ƒ}|D ]}t|||ƒƒ}| |¡ �q,�qt|ƒ}| ¡  d| }|D ]<}|dd… |dd… k�r¢|d |d k�r¢ dS |}�qlt|d ƒS )au  
    Canonicalize tensor formed by tensors of the different types.

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

    sym_i symmetry under exchange of two component tensors of type `i`
          None  no symmetry
          0     commuting
          1     anticommuting

    Parameters
    ==========

    g : Permutation representing the tensor.
    dummies : List of dummy indices.
    msym : Symmetry of the metric.
    v : A list of (base_i, gens_i, n_i, sym_i) for tensors of type `i`.
        base_i, gens_i BSGS for tensors of this type
        n_i  number of tensors of type `i`

    Returns
    =======

    Returns 0 if the tensor is zero, else returns the array form of
    the permutation representing the canonical form of the tensor.

    Examples
    ========

    >>> from sympy.combinatorics.testutil import canonicalize_naive
    >>> from sympy.combinatorics.tensor_can import get_symmetric_group_sgs
    >>> from sympy.combinatorics import Permutation
    >>> g = Permutation([1, 3, 2, 0, 4, 5])
    >>> base2, gens2 = get_symmetric_group_sgs(2)
    >>> canonicalize_naive(g, [2, 3], 0, (base2, gens2, 2, 0))
    [0, 2, 1, 3, 4, 5]
    r   r   )Úgens_productsÚ	dummy_sgs)Ú_af_rmulé   r0   c                 S   s   g | ]}t |ƒ‘qS r   r   r   r   r   r   r     s     z&canonicalize_naive.<locals>.<listcomp>Tr   ©r   Néþÿÿÿéÿÿÿÿ)r%   r   Úsympy.combinatorics.tensor_canrB   rC   r&   rD   r1   r2   r*   Ú
isinstanceÚintÚextendr(   Úgenerater$   r>   r   ÚaddÚsort)ÚgÚdummiesÚsymÚvr   rB   rC   rD   Zv1r6   Zbase_iZgens_iZn_iZsym_iÚsizeZsbaseZsgensZdgensZ	num_typesÚSÚDZdlistÚstÚsÚhÚdÚqr
   Úprevr   r   r   Úcanonicalize_naiveÉ   sH    '
 
r]   c                 C   sà  ddl m} ddlm}m} t|  ¡ ƒ}|jdd„ dd� dd	„ |D ƒ}||ƒ}d}|D ]\}}|t|ƒ7 }qXd
d	„ |D ƒ}	d}
|D ]R\}}|D ]D}|| || k r�|	||   	|
¡ |	||   	|
d ¡ |
d7 }
q�q„g }|	D ]}| 
|¡ qàt|ƒ|k�st‚|||d g7 }|d }t|ƒtt|ƒƒk�s4t‚t|ƒ}dgt|	d ƒd  }|	D ]}|t|ƒ  d7  < �qVg }tt|ƒƒD ]2}
||
 }|�r‚||
ƒ\}}| 	|||df¡ �q‚| ¡  tt|ƒƒ}|||df|žŽ }|S )a  
    Return a certificate for the graph

    Parameters
    ==========

    gr : adjacency list

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

    The graph is assumed to be unoriented and without
    external lines.

    Associate to each vertex of the graph a symmetric tensor with
    number of indices equal to the degree of the vertex; indices
    are contracted when they correspond to the same line of the graph.
    The canonical form of the tensor gives a certificate for the graph.

    This is not an efficient algorithm to get the certificate of a graph.

    Examples
    ========

    >>> from sympy.combinatorics.testutil import graph_certificate
    >>> gr1 = {0:[1, 2, 3, 5], 1:[0, 2, 4], 2:[0, 1, 3, 4], 3:[0, 2, 4], 4:[1, 2, 3, 5], 5:[0, 4]}
    >>> gr2 = {0:[1, 5], 1:[0, 2, 3, 4], 2:[1, 3, 5], 3:[1, 2, 4, 5], 4:[1, 3, 5], 5:[0, 2, 3, 4]}
    >>> c1 = graph_certificate(gr1)
    >>> c2 = graph_certificate(gr2)
    >>> c1
    [0, 2, 4, 6, 1, 8, 10, 12, 3, 14, 16, 18, 5, 9, 15, 7, 11, 17, 13, 19, 20, 21]
    >>> c1 == c2
    True
    r   )Ú
_af_invert)Úget_symmetric_group_sgsÚcanonicalizec                 S   s   t | d ƒS )Nr0   )r2   r   r   r   r   r!   =  r"   z#graph_certificate.<locals>.<lambda>T)ÚkeyÚreversec                 S   s   g | ]}|d  ‘qS rF   r   r   r   r   r   r   >  s     z%graph_certificate.<locals>.<listcomp>c                 S   s   g | ]}g ‘qS r   r   )r	   r6   r   r   r   r   I  s     r0   rE   )r&   r^   rI   r_   r`   r(   ÚitemsrO   r2   r*   rL   ÚAssertionErrorÚsortedr1   r   rb   )Úgrr^   r_   r`   rc   ZpvertZnum_indicesrS   ZneighZverticesr6   Zv2rP   rT   ZvlenÚnr5   r    rQ   Zcanr   r   r   Úgraph_certificate  sL    #rh   )F)N)N)Zsympy.combinatoricsr   Zsympy.combinatorics.utilr   Zrmulr   r+   r8   r:   rA   r]   rh   r   r   r   r   Ú<module>   s   
0)
$
(N