
    Cd&              	          d dl mZ d dlZd dlZd dlZd dlmZmZ d dl	m
Z d dlmZ d dlmZ dddddddddd	Z
d
 Zd dlmZ dS )    )annotationsN)baseutils)	blockwise)unpack_collections)HighLevelGraphT)nametokendtypeadjust_chunksnew_axesalign_arraysconcatenatemetac               	    |}|pi }t          t          |                    t          |          k    r>t          dd t          j        |                                          D                       t          |          d |
ddd         D             z
  t          |pd          z
  }|rt          d|          d	d
lm}m} |r	 ||
 \  }n~d t          j	        d|
          D             }i |D ]O\  } t          |j                   D ]4\  }}|vs&t          |          t          |                   k    r||<   5P|
ddd         }|                                D ]"\  }}t          |t                    s|f}||<   #t          ||
ddd                   }i }g }g }g }|D ]\  }  3 ||          }t          |          \  }}|                    |           n|t!          |d          rAt!           d          r1|j        t                     k    rt          d |j        fz            |j        ||j        <   |                    |           |j        }|                    | f           i }|                                D ]<\  }} ||          }t          |          \  }}|                    |           |||<   =|sPd                    |p&t-          j        |                               d          t3          j        | |||fi |          }t7          | ||g|R ||||d|}t9          j        ||||z             }fd|D             }rZt=          |          D ]I\  }  v r>t?                              r-t          tA                    ||                             ||<   Mt                    tB          j"                  r&t           fd||         D                       ||<   t                    t          tF          f          rt                              t          ||                   k    r?t          d| dt          ||                    dt                               d          t                              ||<   :tI          d          Kt          |          }|	d	dl%m&}  || |g|
ddd         R i |}	tO          ||||	|          S )a<  Tensor operation: Generalized inner and outer products

    A broad class of blocked algorithms and patterns can be specified with a
    concise multi-index notation.  The ``blockwise`` function applies an in-memory
    function across multiple blocks of multiple inputs in a variety of ways.
    Many dask.array operations are special cases of blockwise including
    elementwise, broadcasting, reductions, tensordot, and transpose.

    Parameters
    ----------
    func : callable
        Function to apply to individual tuples of blocks
    out_ind : iterable
        Block pattern of the output, something like 'ijk' or (1, 2, 3)
    *args : sequence of Array, index pairs
        You may also pass literal arguments, accompanied by None index
        e.g. (x, 'ij', y, 'jk', z, 'i', some_literal, None)
    **kwargs : dict
        Extra keyword arguments to pass to function
    dtype : np.dtype
        Datatype of resulting array.
    concatenate : bool, keyword only
        If true concatenate arrays along dummy indices, else provide lists
    adjust_chunks : dict
        Dictionary mapping index to function to be applied to chunk sizes
    new_axes : dict, keyword only
        New indexes and their dimension lengths
    align_arrays: bool
        Whether or not to align chunks along equally sized dimensions when
        multiple arrays are provided.  This allows for larger chunks in some
        arrays to be broken into smaller ones that match chunk sizes in other
        arrays such that they are compatible for block function mapping. If
        this is false, then an error will be thrown if arrays do not already
        have the same number of blocks in each dimension.

    Examples
    --------
    2D embarrassingly parallel operation from two arrays, x, and y.

    >>> import operator, numpy as np, dask.array as da
    >>> x = da.from_array([[1, 2],
    ...                    [3, 4]], chunks=(1, 2))
    >>> y = da.from_array([[10, 20],
    ...                    [0, 0]])
    >>> z = blockwise(operator.add, 'ij', x, 'ij', y, 'ij', dtype='f8')
    >>> z.compute()
    array([[11, 22],
           [ 3,  4]])

    Outer product multiplying a by b, two 1-d vectors

    >>> a = da.from_array([0, 1, 2], chunks=1)
    >>> b = da.from_array([10, 50, 100], chunks=1)
    >>> z = blockwise(np.outer, 'ij', a, 'i', b, 'j', dtype='f8')
    >>> z.compute()
    array([[  0,   0,   0],
           [ 10,  50, 100],
           [ 20, 100, 200]])

    z = x.T

    >>> z = blockwise(np.transpose, 'ji', x, 'ij', dtype=x.dtype)
    >>> z.compute()
    array([[1, 3],
           [2, 4]])

    The transpose case above is illustrative because it does transposition
    both on each in-memory block by calling ``np.transpose`` and on the order
    of the blocks themselves, by switching the order of the index ``ij -> ji``.

    We can compose these same patterns with more variables and more complex
    in-memory functions

    z = X + Y.T

    >>> z = blockwise(lambda x, y: x + y.T, 'ij', x, 'ij', y, 'ji', dtype='f8')
    >>> z.compute()
    array([[11,  2],
           [23,  4]])

    Any index, like ``i`` missing from the output index is interpreted as a
    contraction (note that this differs from Einstein convention; repeated
    indices do not imply contraction.)  In the case of a contraction the passed
    function should expect an iterable of blocks on any array that holds that
    index.  To receive arrays concatenated along contracted dimensions instead
    pass ``concatenate=True``.

    Inner product multiplying a by b, two 1-d vectors

    >>> def sequence_dot(a_blocks, b_blocks):
    ...     result = 0
    ...     for a, b in zip(a_blocks, b_blocks):
    ...         result += a.dot(b)
    ...     return result

    >>> z = blockwise(sequence_dot, '', a, 'i', b, 'i', dtype='f8')
    >>> z.compute()
    250

    Add new single-chunk dimensions with the ``new_axes=`` keyword, including
    the length of the new dimension.  New dimensions will always be in a single
    chunk.

    >>> def f(a):
    ...     return a[:, None] * np.ones((1, 5))

    >>> z = blockwise(f, 'az', a, 'a', new_axes={'z': 5}, dtype=a.dtype)

    New dimensions can also be multi-chunk by specifying a tuple of chunk
    sizes.  This has limited utility as is (because the chunks are all the
    same), but the resulting graph can be modified to achieve more useful
    results (see ``da.map_blocks``).

    >>> z = blockwise(f, 'az', a, 'a', new_axes={'z': (5, 5)}, dtype=x.dtype)
    >>> z.chunks
    ((1, 1, 1), (5, 5))

    If the applied function changes the size of each chunk you can specify this
    with a ``adjust_chunks={...}`` dictionary holding a function for each index
    that modifies the dimension size in that index.

    >>> def double(x):
    ...     return np.concatenate([x, x])

    >>> y = blockwise(double, 'ij', x, 'ij',
    ...               adjust_chunks={'i': lambda n: 2 * n}, dtype=x.dtype)
    >>> y.chunks
    ((2, 2), (2,))

    Include literals by indexing with None

    >>> z = blockwise(operator.add, 'ij', x, 'ij', 1234, None, dtype=x.dtype)
    >>> z.compute()
    array([[1235, 1236],
           [1237, 1238]])
    z-Repeated elements not allowed in output indexc                $    g | ]\  }}|d k    |S )    ).0kvs      4lib/python3.11/site-packages/dask/array/blockwise.py
<listcomp>zblockwise.<locals>.<listcomp>   s!    GGG41aQQ    c                     h | ]}||D ]}|S Nr   )r   argas      r   	<setcomp>zblockwise.<locals>.<setcomp>   s#    
C
C
Ccosoo!1oooor   r   N   r   zUnknown dimensionr   )normalize_argunify_chunksc                     g | ]\  }}|||fS r   r   )r   r   is      r   r   zblockwise.<locals>.<listcomp>   s!    RRRfq!AMAq6MMMr   ndim__len__z1Index string %s does not match array dimension %dz{}-{}_)	numblocksdependenciesr   r   )r)   c                     g | ]
}|         S r   r   )r   r$   chunksss     r   r   zblockwise.<locals>.<listcomp>  s    ***Qgaj***r   c              3  (   K   | ]}         V  d S r   r   )r   r'   r   inds     r   	<genexpr>zblockwise.<locals>.<genexpr>  s(      %L%LQmC&8%L%L%L%L%L%Lr   z
Dimension z has z& blocks, adjust_chunks specified with z blocksz4adjust_chunks values must be callable, int, or tuple)compute_meta)r   r   )(lenset
ValueErrortoolzfrequenciesitemsdask.array.corer!   r"   	partitionzipchunks
isinstancetupler   extendhasattrr%   r(   r	   appendformatr   funcnamestripr   tokenizecore_blockwiser   from_collections	enumeratecallablemapnumbersIntegrallistNotImplementedErrordask.array.utilsr/   new_da_object)!funcout_indr	   r
   r   r   r   r   r   r   argskwargsoutnewr!   r"   arraysargindsr   cr$   r   r   r(   r)   
argindsstrcollectionskwargs2graphr9   r/   r+   r-   s!        `                         @@r   r   r      s4   l C~2H 3w<<CLL((;GG5,W55;;==GGG
 
 	

 	G
C
CQTT

C
C
C	D
hn"

	 
  3,c222;;;;;;;; &,-RR4(@(@RRR
   	# 	#HCCJ,, # #1G##s1vvGAJ'?'?!"GAJ# ccc    1!U## 	A

&$qt!t*%%GILF J & &S;-$$C1#66C,,,, V$$C++ HC(( GCHo&   #&-IchMM#(C3*%%%% G  1M!+A..;K(((

  
nn4U^D))//44M$UEEfEE
 

 
 
	
 

 !
 
 
 
E +U,!6  E +***'***F (( 	 	FAsm##M#.//  %c-*<fQi&H&H I IF1IIc 2G4DEE  %%L%L%L%L%L&)%L%L%L L LF1IIc 2UDMBB 
=-..#fQi..@@(O O OVAY O O.1-2D.E.EO O O   !&mC&8 9 9F1II-N   $  6]]F|111111|D%>$sss)>>>v>>V$eDDDDr   c                 B    t          j        d           t          | i |S )Nz.The da.atop function has moved to da.blockwise)warningswarnr   )rP   rQ   s     r   atopr^   "  s&    MBCCCd%f%%%r   )rM   )
__future__r   rH   r\   tlzr3   daskr   r   dask.blockwiser   rC   dask.delayedr   dask.highlevelgraphr   r^   r6   rM   r   r   r   <module>re      s    " " " " " "               6 6 6 6 6 6 + + + + + + . . . . . . 


	QE QE QE QE QEh& & &
 * ) ) ) ) ) ) )r   