a
    <b+                     @   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   l/Users/vegardjervell/Documents/master/model/venv/lib/python3.9/site-packages/sympy/combinatorics/testutil.py	<setcomp>        z"_cmp_perm_lists.<locals>.<setcomp>c                 S   s   h | ]}t |qS r   r   r   r   r   r   r   !   r   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 }|s||D ]}||r\|t	
| q\n|D ]}||r|| q|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>B   r   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   r   z<_naive_list_centralizer.<locals>.<lambda>.<locals>.<genexpr>)allr   r   gensr   r   <lambda>C   r   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    
r6   Nc                 C   s:   |du 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   )r2   argZcentrZ
centr_listZcentr_list_naiver   r   r   _verify_centralizer}   s
    
r8   c           	      C   s   ddl m} |d u r| |}t }t|dr6|j}n t|drF|}nt|drV|g}|  D ]}|D ]}|||A  qfq^|t|}|	|S )Nr   r   r   __getitem__r"   )
r#   r   Znormal_closuresetr%   r   r'   addr&   Zis_subgroup)	r2   r7   closurer   Z
conjugatesZ
subgr_genselr   Znaive_closurer   r   r   _verify_normal_closure   s    



r>   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rd}|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 ot 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   r.   c                 S   s   g | ]}t |qS r   r   r   r   r   r   r     r   z&canonicalize_naive.<locals>.<listcomp>Tr   r   N)r#   r   sympy.combinatorics.tensor_canr?   r@   r$   rA   r/   r0   r(   
isinstanceintextendr&   generater"   r:   r   r;   sort)gdummiessymvr   r?   r@   rA   v1r4   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    '
 
rZ   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 }
qqg }|	D ]}|
| qt||ksJ |||d g7 }|d }t|tt|ks4J t|}dgt|	d d  }|	D ]}|t|  d7  < qVg }tt|D ]2}
||
 }|r||
\}}|	|||df q|  tt|}|||dg|R  }|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 )Nr.   )r0   r   r   r   r   r    >  r   z#graph_certificate.<locals>.<lambda>T)keyreversec                 S   s   g | ]}|d  qS rC   r   r   r   r   r   r   ?  r   z%graph_certificate.<locals>.<listcomp>c                 S   s   g | ]}g qS r   r   )r	   r4   r   r   r   r   J  r   r.   rB   )r$   r[   rF   r\   r]   r&   itemsrK   r0   r(   rI   sortedr/   r   r_   )Zgrr[   r\   r]   r`   ZpvertZnum_indicesrO   ZneighZverticesr4   v2rL   rQ   Zvlennr3   r   rM   Zcanr   r   r   graph_certificate  sL    #rd   )F)N)N)Zsympy.combinatoricsr   Zsympy.combinatorics.utilr   Zrmulr   r)   r6   r8   r>   rZ   rd   r   r   r   r   <module>   s   
0)
$
)N