ó
¦–Õ\c           @   s€   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 „  Z
 d „  Z d S(	   iÿÿÿÿNi   (   t   baset   utils(   t   unpack_collections(   t   HighLevelGraph(   t	   blockwisec            sq  | j  d d
 ƒ } | j  d d
 ƒ } | j  d d
 ƒ } | j  d d
 ƒ ‰  | j  d i  ƒ } | j  d t ƒ } t t | ƒ ƒ t | ƒ k rÐ t d g  t j | ƒ j ƒ  D] \ }	 }
 |
 d k r¦ |	 ^ q¦ ƒ ‚ n  t | ƒ d	 „  | d d
 d … Dƒ t | p d ƒ } | rt d | ƒ ‚ n  d d l	 m
 } m } m } | d
 k rVt d ƒ ‚ n  | rq| | Œ  \ } } n’ g  t j d | ƒ D]$ \ } } | d
 k	 r„| | f ^ q„} | rêt | d d „  ƒ\ } ‰ t t ˆ | j ƒ ƒ } n i  } | d
 d
 d … } x? | j ƒ  D]1 \ }	 }
 t |
 t ƒ s7|
 f }
 n  |
 | |	 <qWt t | | d d
 d … ƒ ƒ } xc | D][ \ } ‰ t | d ƒ rnt ˆ d ƒ rn| j t ˆ ƒ k rnt d ˆ | j f ƒ ‚ qnqnWd „  | Dƒ } g  } g  } g  } xw | D]o \ } ‰ ˆ d
 k r<| | ƒ } t | ƒ \ } } | j | ƒ n | j | ƒ | j } | j | ˆ f ƒ qöWi  } xO | j ƒ  D]A \ }	 }
 | |
 ƒ }
 t |
 ƒ \ }
 } | j | ƒ |
 | |	 <q|W| sd | påt j |  ƒ j d ƒ t j |  | | | |  f } n  t  |  | | d | d | d | | | Ž} t! j" | | d | | ƒ} g  | D] } | | ^ qT} ˆ  rOxÜ t# | ƒ D]Ë \ } ‰ ˆ ˆ  k r}t$ ˆ  ˆ ƒ rÉt t% ˆ  ˆ | | ƒ ƒ | | <qHt ˆ  ˆ t& j' ƒ r	t ‡  ‡ f d †  | | Dƒ ƒ | | <qHt ˆ  ˆ t t f ƒ r9t ˆ  ˆ ƒ | | <qHt( d ƒ ‚ q}q}Wn  t | ƒ } | | | | d | ƒS(   sÀ   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
        Sequence like (x, 'ij', y, 'jk', z, 'i')
    **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

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

    >>> z = blockwise(operator.add, 'ij', x, 'ij', y, 'ij', dtype='f8')  # z = x + y  # doctest: +SKIP

    Outer product multiplying x by y, two 1-d vectors

    >>> z = blockwise(operator.mul, 'ij', x, 'i', y, 'j', dtype='f8')  # doctest: +SKIP

    z = x.T

    >>> z = blockwise(np.transpose, 'ji', x, 'ij', dtype=x.dtype)  # doctest: +SKIP

    The transpose case above is illustrative because it does same 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')  # doctest: +SKIP

    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 x by y, two 1-d vectors

    >>> def sequence_dot(x_blocks, y_blocks):
    ...     result = 0
    ...     for x, y in zip(x_blocks, y_blocks):
    ...         result += x.dot(y)
    ...     return result

    >>> z = blockwise(sequence_dot, '', x, 'i', y, 'i', dtype='f8')  # doctest: +SKIP

    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(x):
    ...     return x[:, None] * np.ones((1, 5))

    >>> z = blockwise(f, 'az', x, 'a', new_axes={'z': 5}, dtype=x.dtype)  # doctest: +SKIP

    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', x, 'a', new_axes={'z': (5, 5)}, dtype=x.dtype)  # doctest: +SKIP

    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)  # doctest: +SKIP

    Include literals by indexing with None

    >>> y = blockwise(add, 'ij', x, 'ij', 1234, None, dtype=x.dtype)  # doctest: +SKIP
    t   namet   tokent   dtypet   adjust_chunkst   new_axest   align_arrayss-   Repeated elements not allowed in output indexi   c         S   s/   h  |  ]% } | d  k	 r | D] } | ’ q q S(   N(   t   None(   t   .0t   argt   a(    (    s3   lib/python2.7/site-packages/dask/array/blockwise.pys	   <setcomp>|   s   	 Ni   s   Unknown dimension(   t   Arrayt   unify_chunkst   normalize_args"   Must specify dtype of output arrayt   keyc         S   s   t  |  d ƒ S(   Ni   (   t   len(   t   ai(    (    s3   lib/python2.7/site-packages/dask/array/blockwise.pyt   <lambda>‹   t    t   ndimt   __len__s1   Index string %s does not match array dimension %dc         S   s1   i  |  ]' \ } } | d  k	 r | j | j “ q S(   N(   R   t	   numblocksR   (   R   R   t   ind(    (    s3   lib/python2.7/site-packages/dask/array/blockwise.pys
   <dictcomp>œ   s   	 s   %s-%st   _R   t   dependenciesc         3   s   |  ] } ˆ  ˆ Vq d  S(   N(    (   R   R   (   R   R   (    s3   lib/python2.7/site-packages/dask/array/blockwise.pys	   <genexpr>Æ   s    s4   adjust_chunks values must be callable, int, or tuple(    ()   t   popR   t   TrueR   t   sett
   ValueErrort   toolzt   frequenciest   itemst   coreR   R   R   t	   partitiont   maxt   dictt   zipt   chunkst
   isinstancet   tuplet   listt   hasattrR   R   t   extendt   appendR   R   t   funcnamet   stripR    t   tokenizet   core_blockwiseR   t   from_collectionst	   enumeratet   callablet   mapt   numberst   Integralt   NotImplementedError(   t   funct   out_indt   argst   kwargst   outR   R   R	   R
   t   kt   vt   newR   R   R   t   chunksst   arraysR   t   it   argindsR   R   R   t
   argindsstrt   collectionst   kwargs2t   graphR)   (    (   R   R   s3   lib/python2.7/site-packages/dask/array/blockwise.pyR      sŽ    d@7="3	"$*c          O   s   t  j d ƒ t |  | Ž  S(   Ns.   The da.atop function has moved to da.blockwise(   t   warningst   warnR   (   R=   R>   (    (    s3   lib/python2.7/site-packages/dask/array/blockwise.pyt   atopÑ   s    (   R8   RK   R!   R   R    R   t   delayedR   t   highlevelgraphR   R   R3   RM   (    (    (    s3   lib/python2.7/site-packages/dask/array/blockwise.pyt   <module>   s   	Å