
    ,Vh3                        d Z ddlZddlmZmZmZmZmZmZ ddl	m
Z
mZ g dZdZdedefd	Zd
edefdZdedefdZdededee   fdZd
edefdZdedefdZdedefdZdee   dee   dedefdZeeeeeefZdedefdZdedefdZdee   deeef   defdZdee   deeeed f   f   fd!Z d#dededeeeee
   f   fd"Z!y)$zBA functionally equivalent parser of the numpy.einsum input parser.    N)AnyDictIteratorListSequenceTuple)	ArrayTypeTensorShapeType)is_valid_einsum_charhas_valid_einsum_chars_only
get_symbol	get_shapegen_unused_symbolsconvert_to_valid_einsum_charsalpha_canonicalizefind_output_strfind_output_shapepossibly_convert_to_numpyparse_einsum_input4abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZxreturnc                     | t         v xs | dv S )u   Check if the character ``x`` is valid for numpy einsum.

    **Examples:**

    ```python
    is_valid_einsum_char("a")
    #> True

    is_valid_einsum_char("Ǵ")
    #> False
    ```
    z,->.)_einsum_symbols_base)r   s    A/home/dcms/DCMS/lib/python3.12/site-packages/opt_einsum/parser.pyr   r      s     %%71;7    
einsum_strc                 4    t        t        t        |             S )u   Check if ``einsum_str`` contains only valid characters for numpy einsum.

    **Examples:**

    ```python
    has_valid_einsum_chars_only("abAZ")
    #> True

    has_valid_einsum_chars_only("Över")
    #> False
    ```
    )allmapr   )r   s    r   r   r   )   s     s'455r   ic                 `    | dk  r	t         |    S | dk\  rt        | dz         S t        | dz         S )u<  Get the symbol corresponding to int ``i`` - runs through the usual 52
    letters before resorting to unicode characters, starting at ``chr(192)`` and skipping surrogates.

    **Examples:**

    ```python
    get_symbol(2)
    #> 'c'

    get_symbol(200)
    #> 'Ŕ'

    get_symbol(20000)
    #> '京'
    ```
    4   i   i      )r   chr)r!   s    r   r   r   9   s9    " 	2v#A&&	
e1t8}1s7|r   usednc              #   h   K   dx}}||k  r%t        |      }|dz  }|| v r| |dz  }||k  r$yyw)zGenerate ``n`` symbols that are not already in ``used``.

    **Examples:**
    ```python
    list(oe.parser.gen_unused_symbols("abd", 2))
    #> ['c', 'e']
    ```
    r      N)r   )r&   r'   r!   cntss        r   r   r   S   sK      KA
'qM	Q9q 's   -22c                     t        t        |       t        d      z
        }t        |      D ci c]  \  }}|t        |       c}}dj	                  fd| D              S c c}}w )u  Convert the str ``einsum_str`` to contain only the alphabetic characters
    valid for numpy einsum. If there are too many symbols, let the backend
    throw an error.

    Examples:
    --------
    >>> oe.parser.convert_to_valid_einsum_chars("Ĥěļļö")
    'cbdda'
    z,-> c              3   B   K   | ]  }j                  ||        y wNget).0r   replacers     r   	<genexpr>z0convert_to_valid_einsum_chars.<locals>.<genexpr>r   s     :!8<<1%:   )sortedset	enumerater   join)r   symbolsr!   r   r3   s       @r   r   r   f   sY     S_s5z12G-6w-?@TQ:a= @H77:z::: As   A$equationc                     i | D ]#  }|dv r|vst        t                    |<   % dj                  fd| D              S )u   Alpha convert an equation in an order-independent canonical way.

    Examples:
    --------
    >>> oe.parser.alpha_canonicalize("dcba")
    'abcd'

    >>> oe.parser.alpha_canonicalize("Ĥěļļö")
    'abccd'
    z.,->r-   c              3   B   K   | ]  }j                  ||        y wr/   r0   )r2   r   renames     r   r4   z%alpha_canonicalize.<locals>.<genexpr>   s     66::a#6r5   )r   lenr9   )r;   namer>   s     @r   r   r   u   sT      F 36>v%c&k2F4L	3
 776X666r   
subscriptsc                     | j                  dd      dj                  fdt        t                    D              S )aU  Find the output string for the inputs ``subscripts`` under canonical einstein summation rules.
    That is, repeated indices are summed over by default.

    Examples:
    --------
    >>> oe.parser.find_output_str("ab,bc")
    'ac'

    >>> oe.parser.find_output_str("a,b")
    'ab'

    >>> oe.parser.find_output_str("a,a,b,b")
    ''
    ,r-   c              3   L   K   | ]  }j                  |      d k(  s|  yw)r)   N)count)r2   r+   tmp_subscriptss     r   r4   z"find_output_str.<locals>.<genexpr>   s%     Z^=Q=QRS=TXY=Y1Zs   $$)replacer9   r6   r7   )rA   rF   s    @r   r   r      s6      ''R0N77ZfS%89ZZZr   inputsshapesoutputc                 0     t         fd|D              S )aP  Find the output shape for given inputs, shapes and output string, taking
    into account broadcasting.

    Examples:
    --------
    >>> oe.parser.find_output_shape(["ab", "bc"], [(2, 3), (3, 4)], "ac")
    (2, 4)

    # Broadcasting is accounted for
    >>> oe.parser.find_output_shape(["a", "a"], [(4, ), (1, )], "a")
    (4,)
    c              3      K   | ]=  }t        d  t        D cg c]  }|j                  |       c}      D               ? yc c}w w)c              3   8   K   | ]  \  }}|d k\  s||     yw)r   N )r2   shapelocs      r   r4   z.find_output_shape.<locals>.<genexpr>.<genexpr>   s!     gJE3^aef^fU3Zgs   
N)maxzipfind)r2   cr   rH   rI   s      r   r4   z$find_output_shape.<locals>.<genexpr>   s;     xlmg#fRX>YQqvvay>Y2Zggx>Ys   AAA)tuple)rH   rI   rJ   s   `` r   r   r      s     xqwxxxr   c                 l   t        | d      r| j                  S t        | t              ryt        | t              rmg }t        | t              rPt        | t              s@|j                  t        |              | d   } t        | t              rt        | t              s@t        |      S t        d|  d      )a  Get the shape of the array-like object `x`. If `x` is not array-like, raise an error.

    Array-like objects are those that have a `shape` attribute, are sequences of BaseTypes, or are BaseTypes.
    BaseTypes are defined as `bool`, `int`, `float`, `complex`, `str`, and `bytes`.
    rO   rN   r   zCannot determine the shape of z5, can only determine the shape of array-like objects.)	hasattrrO   
isinstance
_BaseTypesr   appendr?   rU   
ValueError)r   rO   s     r   r   r      s     q'ww	Az	"	Ax	 H%jJ.GLLQ !A H%jJ.G U|9!<qrssr   c                 z    t        | d      s	 ddl}|j                  |       S | S # t        $ r t        d      w xY w)aU  Convert things without a 'shape' to ndarrays, but leave everything else.

    Examples:
    --------
    >>> oe.parser.possibly_convert_to_numpy(5)
    array(5)

    >>> oe.parser.possibly_convert_to_numpy([5, 3])
    array([5, 3])

    >>> oe.parser.possibly_convert_to_numpy(np.array([5, 3]))
    array([5, 3])

    # Any class with a shape is passed through
    >>> class Shape:
    ...     def __init__(self, shape):
    ...         self.shape = shape
    ...

    >>> myshape = Shape((5, 5))
    >>> oe.parser.possibly_convert_to_numpy(myshape)
    <__main__.Shape object at 0x10f850710>
    rO   r   Nzinumpy is required to convert non-array objects to arrays. This function will be deprecated in the future.)rW   numpyModuleNotFoundError
asanyarray)r   nps     r   r   r      sM    0 1g	 }}Q # 	%{ 	s   % :old_sub
symbol_mapc                 D    d}| D ]  }|t         u r|dz  }|||   z  } |S )a  Convert user custom subscripts list to subscript string according to `symbol_map`.

    Examples:
    --------
    >>>  oe.parser.convert_subscripts(['abc', 'def'], {'abc':'a', 'def':'b'})
    'ab'
    >>> oe.parser.convert_subscripts([Ellipsis, object], {object:'a'})
    '...a'
    r-   ...)Ellipsis)ra   rb   new_subr+   s       r   convert_subscriptsrg      s@     G %=uG z!}$G% Nr   operands.c                   
 t        |       }g }g }t        t        |       dz        D ]B  }|j                  |j	                  d             |j                  |j	                  d             D t        |      r|d   nd}	 t        t        j                  j                  |            }|j                  t               t        t        |            D ci c]  \  }}|t        |       c}}
dj                  
fd|D              }	||	dz  }	|	t!        |
      z  }	|	t#        |      fS c c}}w # t        $ r t        d      w xY w)	z5Convert 'interleaved' input to standard einsum input.   r   NziFor this input type lists must contain either Ellipsis or hashable and comparable object (e.g. int, str).rC   c              3   6   K   | ]  }t        |        y wr/   )rg   )r2   subrb   s     r   r4   z,convert_interleaved_input.<locals>.<genexpr>  s     X#,S*=Xs   ->)listranger?   rZ   popr7   	itertoolschainfrom_iterablediscardre   r8   r6   r   	TypeErrorr9   rg   rU   )rh   tmp_operandsoperand_listsubscript_list_output_list
symbol_setidxsymbolrA   rb   s             @r   convert_interleaved_inputr      sD   >LLN3x=A%& 3L,,Q/0l..q123 '*,&7,r"TK
66~FG
 	8$ BK6R\K]A^_+#vfjo-_
 XXXJd
(jAA
u\*** ` 
A
 	

s    AD1 D+*D1 +D1 1Ec           	      0   t        |       dk(  rt        d      t        | d   t              r=| d   j	                  dd      }|r t        d | dd D              rt        d      | dd } nt        |       \  }} |r| }n| D cg c]  }t        |       }}d	|v sd
|v rK|j                  d	      dkD  xs |j                  d
      dkD  }|s|j                  d      dk7  rt        d      d|v r|j	                  dd      j	                  dd      j	                  dd      }dj                  t        |t        d |D                          }d}d|v r(|j                  d      \  }	}
|	j                  d      }d}n|j                  d      }d}t        |      D ]  \  }}d|v s|j                  d      dk7  s|j                  d      dk7  rt        d      ||   dk(  rd}n't        t        ||         d      t        |      dz
  z
  }||kD  r|}|dk  rt        d      |dk(  r|j	                  dd      ||<   |j	                  d|| d       ||<    dj                  |      }|dk(  rd}n|| d }|r|d
j	                  d|      z   z  }nEt        |      }dj                  t        t!        |      t!        |      z
              }|d|z   |z   z  }d|v r|j                  d      \  }}n|t        |      }}|D ]8  }|j                  |      dk7  rt        d| d      ||vs+t        d| d       t        |j                  d            t        |       k7  r3t        dt        |j                  d             dt        |        d      ||| fS c c}w )ay  A reproduction of einsum c side einsum parsing in python.

    Parameters:
        operands: Intakes the same inputs as `contract_path`, but NOT the keyword args. The only
            supported keyword argument is:
        shapes: Whether ``parse_einsum_input`` should assume arrays (the default) or
            array shapes have been supplied.

    Returns:
        input_strings: Parsed input strings
        output_string: Parsed output string
        operands: The operands to use in the numpy contraction

    Examples:
        The operand list is simplified to reduce printing:

        ```python
        >>> a = np.random.rand(4, 4)
        >>> b = np.random.rand(4, 4, 4)
        >>> parse_einsum_input(('...a,...a->...', a, b))
        ('za,xza', 'xz', [a, b])

        >>> parse_einsum_input((a, [Ellipsis, 0], b, [Ellipsis, 0]))
        ('za,xza', 'xz', [a, b])
        ```
    r   zNo input operands r-   c              3   4   K   | ]  }t        |d         yw)rO   N)rW   )r2   os     r   r4   z%parse_einsum_input.<locals>.<genexpr>B  s     =171g&=s   r)   Nzwshapes is set to True but given at least one operand looks like an array (at least one operand has a shape attribute). ->rn   z%Subscripts can only contain one '->'..rC   c              3   2   K   | ]  }t        |        y wr/   )r?   )r2   r   s     r   r4   z%parse_einsum_input.<locals>.<genexpr>Y  s     ;[qCF;[s   TF   rd   zInvalid Ellipses.rN   zEllipses lengths do not match.zOutput character 'z(' appeared more than once in the output.z' did not appear in the inputzNumber of einsum subscripts, z+, must be equal to the number of operands, )r?   r[   rX   strrG   anyr   r   rE   r9   r   rQ   splitr8   r   r6   r7   )rh   rI   rA   operand_shapesr   invalidr&   ellipse_indslongest	input_tmp
output_subsplit_subscriptsout_subnumrm   ellipse_countout_ellipseoutput_subscriptnormal_indsinput_subscriptschars                        r   r   r   !  s   6 8},--(1+s#a[((b1
=== F  AB<8B
H!0891)A,99 	zsj0##C(1,L*2B2B32G!2Kz''-2DEE j!!#r*223;CCD"Mww1$;[N;[8[\] :$.$4$4T$:!Iz(s3G)//4G!"23 	^HCczIIcNa'SYYu-=-B$%899 "#&",$%M$'N3,?(@!$DCST$UM 7*+G 1$$%EFF"a',/KKr,B$S),/KK|]NO?\,]$S)'	^* XX./
 a<K&xy1K$!3!3E;!GGGJ  /z:''&-=)>[AQ)Q"RSK$,{::J z-7-=-=d-C**-79T* ! W!!$'1,1$7_`aa''1$7TUVV	W !!#&'3x=8+C0@0F0Fs0K,L+M N##&x=/4
 	

 -x77c :s   N)F)"__doc__rr   typingr   r   r   r   r   r   opt_einsum.typingr	   r
   __all__r   r   boolr   r   intr   r   r   r   r   r   floatcomplexbytesrY   r   r   rg   r   r   rN   r   r   <module>r      s   H  = = 8 N 8C 8D 8 6C 6D 6 # # 4S S Xc] &;c ;c ;7 7 7([ [ [&yd3i yo1F yPS yXg y  Ce4
t t t(" " "JS	 tCH~ # ("+ "+%U3PS8_@T:U "+J~8 ~8d ~8uS#tT]E^?_ ~8r   