a
    Sic                     @   s   d Z ddlmZ ddlZddlmZ g dZdZe	g dZ
d	d
 eee
D ZdddZdd Zdd Zdd ZdddZdS )z:
Contains helper functions for opt_einsum testing scripts
    )OrderedDictN   )
get_symbol)build_viewscompute_size_by_dictfind_contraction
flop_countZabcdefghijklmopqABC)            r   r
   r	      r   r   r
   r	   r      r   r
   r	   r
   r   c                 C   s   i | ]\}}||qS  r   ).0csr   r   N/var/www/html/django/DPS/env/lib/python3.9/site-packages/opt_einsum/helpers.py
<dictcomp>       r   c                    sV    du rt  g }| dd d}|D ](} fdd|D }|tjj|  q(|S )a  
    Builds random numpy arrays for testing.

    Parameters
    ----------
    string : list of str
        List of tensor strings to build
    dimension_dict : dictionary
        Dictionary of index _sizes

    Returns
    -------
    ret : list of np.ndarry's
        The resulting views.

    Examples
    --------
    >>> view = build_views(['abbc'], {'a': 2, 'b':3, 'c':5})
    >>> view[0].shape
    (2, 3, 3, 5)

    Nz->r   ,c                    s   g | ]} | qS r   r   )r   xdimension_dictr   r   
<listcomp>0   r   zbuild_views.<locals>.<listcomp>)_default_dim_dictsplitappendnprandomrand)stringr   viewstermstermdimsr   r   r   r      s    r   c                 C   s   d}| D ]}||| 9 }q|S )a  
    Computes the product of the elements in indices based on the dictionary
    idx_dict.

    Parameters
    ----------
    indices : iterable
        Indices to base the product on.
    idx_dict : dictionary
        Dictionary of index _sizes

    Returns
    -------
    ret : int
        The resulting product.

    Examples
    --------
    >>> compute_size_by_dict('abbc', {'a': 2, 'b':3, 'c':5})
    90

    r   r   )indicesidx_dictretir   r   r   r   5   s    r   c                    s\   t |  fddt| ddD }tj| }|j  }||@ }|| } | | ||fS )a  
    Finds the contraction for a given set of input and output sets.

    Parameters
    ----------
    positions : iterable
        Integer positions of terms used in the contraction.
    input_sets : list
        List of sets that represent the lhs side of the einsum subscript
    output_set : set
        Set that represents the rhs side of the overall einsum subscript

    Returns
    -------
    new_result : set
        The indices of the resulting contraction
    remaining : list
        List of sets that have not been contracted, the new set is appended to
        the end of this list
    idx_removed : set
        Indices removed from the entire contraction
    idx_contraction : set
        The indices used in the current contraction

    Examples
    --------

    # A simple dot product test case
    >>> pos = (0, 1)
    >>> isets = [set('ab'), set('bc')]
    >>> oset = set('ac')
    >>> find_contraction(pos, isets, oset)
    ({'a', 'c'}, [{'a', 'c'}], {'b'}, {'a', 'b', 'c'})

    # A more complex case with additional terms in the contraction
    >>> pos = (0, 2)
    >>> isets = [set('abd'), set('ac'), set('bdc')]
    >>> oset = set('ac')
    >>> find_contraction(pos, isets, oset)
    ({'a', 'c'}, [{'a', 'c'}, {'a', 'c'}], {'b', 'd'}, {'a', 'b', 'c', 'd'})
    c                 3   s   | ]}  |V  qd S N)popr   r)   	remainingr   r   	<genexpr>~   r   z#find_contraction.<locals>.<genexpr>T)reverse)listsortedsetunionr   )	positions
input_sets
output_setinputsidx_contract
idx_remain
new_resultidx_removedr   r-   r   r   R   s    +


r   c                 C   s,   t | |}td|d }|r$|d7 }|| S )a  
    Computes the number of FLOPS in the contraction.

    Parameters
    ----------
    idx_contraction : iterable
        The indices involved in the contraction
    inner : bool
        Does this contraction require an inner product?
    num_terms : int
        The number of terms in a contraction
    size_dictionary : dict
        The size of each of the indices in idx_contraction

    Returns
    -------
    flop_count : int
        The total number of FLOPS required for the contraction.

    Examples
    --------

    >>> flop_count('abc', False, 1, {'a': 2, 'b':3, 'c':5})
    90

    >>> flop_count('abc', True, 2, {'a': 2, 'b':3, 'c':5})
    270

    r   )r   max)idx_contractioninner	num_termssize_dictionaryoverall_size	op_factorr   r   r   r      s
    
r   r	   	   Fc                    sx  |durt j| | | d  }dd t| D }	g t fddt|D fdd}
tt jt|
 D ]\\}}|| k r|	|  |7  < q|t jd	| }||	| v rt jd	| }q|	|  |7  < q||r&t	|}t j d
 |< t| D ]}|	|  |7  < q|7 d
t jdd
|	}fdd|	D }||f}|rt|f7 }|S )a  Generate a random contraction and shapes.

    Parameters
    ----------
    n : int
        Number of array arguments.
    reg : int
        'Regularity' of the contraction graph. This essentially determines how
        many indices each tensor shares with others on average.
    n_out : int, optional
        Number of output indices (i.e. the number of non-contracted indices).
        Defaults to 0, i.e., a contraction resulting in a scalar.
    d_min : int, optional
        Minimum dimension size.
    d_max : int, optional
        Maximum dimension size.
    seed: int, optional
        If not None, seed numpy's random generator with this.
    global_dim : bool, optional
        Add a global, 'broadcast', dimension to every operand.
    return_size_dict : bool, optional
        Return the mapping of indices to sizes.

    Returns
    -------
    eq : str
        The equation string.
    shapes : list[tuple[int]]
        The array shapes.
    size_dict : dict[str, int]
        The dict of index sizes, only returned if ``return_size_dict=True``.

    Examples
    --------
    >>> eq, shapes = rand_equation(n=10, reg=4, n_out=5, seed=42)
    >>> eq
    'oyeqn,tmaq,skpo,vg,hxui,n,fwxmr,hitplcj,kudlgfv,rywjsb->cebda'

    >>> shapes
    [(9, 5, 4, 5, 4),
     (4, 4, 8, 5),
     (9, 4, 6, 9),
     (6, 6),
     (6, 9, 7, 8),
     (4,),
     (9, 3, 9, 4, 9),
     (6, 8, 4, 6, 8, 6, 3),
     (4, 7, 8, 8, 6, 9, 6),
     (9, 5, 3, 3, 9, 5)]
    Nr	   c                 S   s   g | ]}d qS ) r   )r   _r   r   r   r      r   z!rand_equation.<locals>.<listcomp>c                 3   s(   | ] }t |tj d  fV  qdS )r   N)r   r   r   randintr,   )d_maxd_minr   r   r/      r   z rand_equation.<locals>.<genexpr>c                  3   s<   t D ].\} }|  k r*| |V  q|V  |V  qd S r*   )	enumerater   )r)   ix)n_outoutput	size_dictr   r   gen   s    
zrand_equation.<locals>.genr   r   rE   z{}->{}r   c                    s"   g | ]}t  fd d|D qS )c                 3   s   | ]} | V  qd S r*   r   )r   rK   rN   r   r   r/     r   z+rand_equation.<locals>.<listcomp>.<genexpr>)tuple)r   oprP   r   r   r     r   )r   r   seedranger   rJ   permutationr1   rG   r   joinformat)nregrL   rI   rH   rS   Z
global_dimZreturn_size_dictZnum_indsr8   rO   r)   rK   whereZgdimeqshapesr(   r   )rH   rI   rL   rM   rN   r   rand_equation   s6    4
r]   )N)r   r	   rD   NFF)__doc__collectionsr   numpyr   parserr   __all__Z_valid_charsarrayZ_sizeszipr   r   r   r   r   r]   r   r   r   r   <module>   s   
#7'