B
    [*                 @   s|   d dl mZmZ d dlmZ 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 )    )print_functiondivision)range)_distribute_gens_by_base)Permutationc             C   s   dd | D dd |D kS )aN  
    Compare two lists of permutations as sets.

    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   ;lib/python3.7/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   r   !   s    r   )firstsecondr   r   r   _cmp_perm_lists
   s    r   Fc                s   ddl m} ddlm  t|drt| jdd}dd |jD  fd	d
}g }|sxF|D ]}||r^|t	
| q^W n x|D ]}||r|| qW |S t|drt| |||S t|drt| ||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>?   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>@   s    z<_naive_list_centralizer.<locals>.<lambda>.<locals>.<genexpr>)all)r   )r   gens)r   r   <lambda>@   s    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   r#   $   s&    




r#   c             C   sr   ddl m} t||}| }xBtt|D ]2}||| }| | krLdS ||| }q(W | dkrndS dS )a  
    Verify the correctness of a base and strong generating set.

    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   r   lenorderZ
stabilizer)groupbaser   r   Zstrong_gens_distrZcurrent_stabilizeri	candidater   r   r   _verify_bsgsQ   s    
r/   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

    NT)r   )Zcentralizerr    r!   r#   r   )r+   argZcentrZ
centr_listZcentr_list_naiver   r   r   _verify_centralizerw   s
    
r1   c       	      C   s   ddl m} |d kr| |}t }t|dr6|j}n t|drF|}nt|drV|g}x,|  D ] }x|D ]}|||A  qjW q`W |t|}|	|S )Nr   )r   r   __getitem__r   )
r   r   Znormal_closuresetr   r   r!   addr    Zis_subgroup)	r+   r0   Zclosurer   Z
conjugatesZ
subgr_gensZelr   Znaive_closurer   r   r   _verify_normal_closure   s    




r5   c                s  ddl m} ddlm}m} ddlm m} g }x<tt	|D ],}	||	 \}
}}}|
|
|g g| |f q>W || \}}}||||d }t|trd}|g}|g}nt	|}g }x.t|D ]"}	||||	 ||	 |d  qW ||}| fdd|D }t|jd	d
}| j} t }xH|jd	d
D ]8}|| |}x&|D ]}t|||}|| q@W q,W t|}|  d| }xB|D ]:}|dd |dd kr|d |d krdS |}qW t|d S )a  
    Canonicalize tensor formed by tensors of the different types

    g  permutation representing the tensor
    dummies  list of dummy indices
    msym symmetry of the metric

    v is 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 ot tensors of type `i`

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

    Return 0 if the tensor is zero, else return 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, PermutationGroup
    >>> 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)r   _af_rmul   r(   c                s   g | ]} |qS r   r   )r	   r   )r   r   r   r      s    z&canonicalize_naive.<locals>.<listcomp>T)r   )r   N)r   r   sympy.combinatorics.tensor_canr6   r7   r   r   r8   r   r)   r"   
isinstanceintextendr    Zgenerater   r3   r   r4   sort)gdummiesZsymvr   r6   r7   r8   Zv1r-   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    
"



rM   c             C   s  ddl m} ddlm}m} t|  }|jdd dd dd	 |D }||}d}x|D ]\}}|t|7 }qZW d
d	 |D }	d}
x^|D ]V\}}xL|D ]D}|| || k r|	||  	|
 |	||  	|
d  |
d7 }
qW qW g }x|	D ]}|
| qW t||kst|||d g7 }|d }t|tt|ksDtt|}dgt|	d d  }x"|	D ]}|t|  d7  < qhW g }xBtt|D ]2}
||
 }|r||
\}}|	|||df qW |  tt|}|||df| }|S )a  
    Return a certificate for the graph

    gr adjacency list

    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 )Nr(   )r)   )r   r   r   r   r   *  s    z#graph_certificate.<locals>.<lambda>T)keyreversec             S   s   g | ]}|d  qS )r   r   )r	   r   r   r   r   r   +  s    z%graph_certificate.<locals>.<listcomp>c             S   s   g | ]}g qS r   r   )r	   r-   r   r   r   r   6  s    r(   r9   )r   rN   r<   rO   rP   r    itemsr@   r)   r"   r?   AssertionErrorsortedr   r   rR   )ZgrrN   rO   rP   rS   ZpvertZnum_indicesrC   ZneighZverticesr-   Zv2rA   rD   Zvlennr,   r   rB   Zcanr   r   r   graph_certificate
  sL    


rW   )F)N)N)Z
__future__r   r   Zsympy.core.compatibilityr   Zsympy.combinatorics.utilr   Zsympy.combinatoricsr   Zrmulr   r#   r/   r1   r5   rM   rW   r   r   r   r   <module>   s   
-&
$
)F