ó
¦–Õ\c           @   s6  d  d l  Z  d  d l Z y d  d l Z Wn e k
 rG d  d l Z n Xd d l m Z m 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
 d „ Z d „  Z d e f d „  ƒ  YZ d „  Z d „  Z d d „ Z d d „ Z d „  Z d „  Z d d f d d „ Z d S(   iÿÿÿÿNi   (   t   coret   utils(   t   applyt   Mapping(   t   to_task_dask(   t   HighLevelGraph(   t   SubgraphCallablec            s›   t  |  t ƒ r) ‡  f d †  |  j ƒ  Dƒ St |  ƒ t t t f k rp t |  ƒ g  |  D] } t | ˆ  ƒ ^ qT ƒ Sy ˆ  |  SWn t t	 f k
 r– |  SXd S(   sË    Create a new task with the values substituted

    This is like dask.core.subs, but takes a dict of many substitutions to
    perform simultaneously.  It is not as concerned with micro performance.
    c            s(   i  |  ] \ } } t  | ˆ  ƒ | “ q S(    (   t   subs(   t   .0t   kt   v(   t   substitution(    s-   lib/python2.7/site-packages/dask/blockwise.pys
   <dictcomp>   s   	 N(
   t
   isinstancet   dictt   itemst   typet   tuplet   listt   setR   t   KeyErrort	   TypeError(   t   taskR   t   x(    (   R   s-   lib/python2.7/site-packages/dask/blockwise.pyR      s    ,c         C   s=   |  d k r |  St g  |  D] } | j | | ƒ ^ q ƒ Sd S(   s>    A simple subs function that works both on tuples and strings N(   t   NoneR   t   get(   t   indR   t   c(    (    s-   lib/python2.7/site-packages/dask/blockwise.pyt
   index_subs    s    t   _c         C   s   | d |  S(   Ns   %d(    (   t   it   prefix(    (    s-   lib/python2.7/site-packages/dask/blockwise.pyt   blockwise_token(   s    c            s;  | j  d ƒ } | j  d d ƒ } | j  d i  ƒ } | j  d g  ƒ } t | ƒ } d „  | d d d … Dƒ t | ƒ B}	 d	 „  t t |	 ƒ ƒ Dƒ ‰  t t | ƒ ˆ  ƒ } g  | d d d … D]$ }
 |
 d k	 rÛ t |
 ƒ n |
 ^ q½ | d d d … <g  | d d d … D] }
 t |
 ˆ  ƒ ^ q| d d d … <‡  f d
 †  | j ƒ  Dƒ } t t	 j
 d | ƒ ƒ } t g  | D] \ } } | ^ qnƒ } t g  | D] \ } } | ^ q“ƒ } d „  | Dƒ } | rDt d „  t t | ƒ t | ƒ t | ƒ ƒ Dƒ ƒ } t t | | ƒ ƒ ‰  | t | ƒ } | d t | ƒ } t | ˆ  ƒ } n  g  t | | ƒ D] \ } } | | f ^ qT} t t t t t | ƒ ƒ ƒ ƒ } | s°i |  f | | 6} n` t | ƒ } | rÖ| t | ƒ  } n  t t t t | j ƒ  ƒ ƒ f } i t |  | | f | 6} t | | | | d | d | d | ƒ} | S(   sú    Create a Blockwise symbolic mutable mapping

    This is like the ``make_blockwise_graph`` function, but rather than construct a dict, it
    returns a symbolic Blockwise object.

    See Also
    --------
    make_blockwise_graph
    Blockwise
    t	   numblockst   concatenatet   new_axest   dependenciesc         S   s/   h  |  ]% } | d  k	 r | D] } | ’ q q S(   N(   R   (   R   t   iiR   (    (    s-   lib/python2.7/site-packages/dask/blockwise.pys	   <setcomp>@   s   	 i   Ni   c         S   s(   i  |  ] \ } } t  | d  ƒ | “ q S(   t   .(   R   (   R   R   R	   (    (    s-   lib/python2.7/site-packages/dask/blockwise.pys
   <dictcomp>C   s   	c            s/   i  |  ]% \ } } | t  | f ˆ  ƒ d  “ q S(   i    (   R   (   R   R	   R
   (   t   sub(    s-   lib/python2.7/site-packages/dask/blockwise.pys
   <dictcomp>J   s   	 c         S   s)   h  |  ] } | j  ƒ  D] } | ’ q q S(    (   t   __dask_layers__(   R   R   t   n(    (    s-   lib/python2.7/site-packages/dask/blockwise.pys	   <setcomp>T   s   	 c         s   s   |  ] } t  | ƒ Vq d  S(   N(   R   (   R   R   (    (    s-   lib/python2.7/site-packages/dask/blockwise.pys	   <genexpr>W   s    (   N(   t   popR   R   R   t	   enumeratet   sortedR   R   R   t   toolzt	   partitiont   ranget   lenR   t   zipR   t   mapR   R   t	   Blockwise(   t   funct   outputt   output_indicest   arrind_pairst   kwargsR    R!   R"   R#   t   unique_indicest   at   argpairst   nameR   t   inputst   indext   inputs_indicest   new_keyst
   new_tokensR	   R
   t   indicest   keyst   subgrapht   _keyst   kwargs2(    (   R&   s-   lib/python2.7/site-packages/dask/blockwise.pyt	   blockwise,   sJ    H9%%5.!!R2   c           B   sP   e  Z d  Z d d d „ Z e d „  ƒ Z d „  Z d „  Z d „  Z	 d „  Z
 RS(   s£   Tensor Operation

    This is a lazily constructed mapping for tensor operation graphs.
    This defines a dictionary using an operation and an indexing pattern.
    It is built for many operations like elementwise, transpose, tensordot, and
    so on.  We choose to keep these as symbolic mappings rather than raw
    dictionaries because we are able to fuse them during optimization,
    sometimes resulting in much lower overhead.

    Parameters
    ----------
    output: str
        The name of the output collection.  Used in keynames
    output_indices: tuple
        The output indices, like ``('i', 'j', 'k')`` used to determine the
        structure of the block computations
    dsk: dict
        A small graph to apply per-output-block.  May include keys from the
        input indices.
    indices: Tuple[str, Tuple[str, str]]
        An ordered mapping from input key name, like ``'x'``
        to input indices, like ``('i', 'j')``
        Or includes literals, which have ``None`` for an index value
    numblocks: Dict[key, Sequence[int]]
        Number of blocks along each dimension for each input
    concatenate: boolean
        Whether or not to pass contracted dimensions as a list of inputs or a
        single input to the block function
    new_axes: Dict
        New index dimensions that may have been created, and their extent

    See Also
    --------
    dask.blockwise.blockwise
    dask.array.blockwise
    c         C   s_   | |  _  t | ƒ |  _ | |  _ t d „  | Dƒ ƒ |  _ | |  _ | |  _ | pU i  |  _ d  S(   Nc         s   s9   |  ]/ \ } } | | d  k	 r* t | ƒ n | f Vq d  S(   N(   R   R   (   R   R;   R   (    (    s-   lib/python2.7/site-packages/dask/blockwise.pys	   <genexpr>š   s   (   R4   R   R5   t   dskRA   R    R!   R"   (   t   selfR4   R5   RG   RA   R    R!   R"   (    (    s-   lib/python2.7/site-packages/dask/blockwise.pyt   __init__•   s    					c         C   s¤   t  |  d ƒ r |  j St t t t t |  j ƒ ƒ ƒ ƒ } t |  j	 |  j
 | ƒ } t | |  j
 |  j d |  j d |  j d |  j t t j |  j ƒ ƒ Œ|  _ |  j S(   Nt   _cached_dictR"   R    R!   (   t   hasattrRJ   R   R1   R   R.   R/   RA   R   RG   R4   t   make_blockwise_graphR5   R"   R    R!   R   R,   t   concat(   RH   RB   R3   (    (    s-   lib/python2.7/site-packages/dask/blockwise.pyt   _dict    s    $			$c         C   s   |  j  | S(   N(   RN   (   RH   t   key(    (    s-   lib/python2.7/site-packages/dask/blockwise.pyt   __getitem__²   s    c         C   s   t  |  j ƒ S(   N(   t   iterRN   (   RH   (    (    s-   lib/python2.7/site-packages/dask/blockwise.pyt   __iter__µ   s    c         C   s%   t  t j t |  j ƒ  j ƒ  ƒ ƒ ƒ S(   N(   t   intt   npt   prodR   t   _out_numblockst   values(   RH   (    (    s-   lib/python2.7/site-packages/dask/blockwise.pyt   __len__¸   s    c            s–   i  } d „  ˆ  j  Dƒ } x` ˆ  j j ƒ  D]O \ } } x@ t | | | ƒ D]+ \ } } t | j | d ƒ | ƒ | | <qI Wq) W‡  f d †  | j ƒ  Dƒ S(   Nc         S   s+   i  |  ]! \ } } | d  k	 r | | “ q S(   N(   R   (   R   R	   R
   (    (    s-   lib/python2.7/site-packages/dask/blockwise.pys
   <dictcomp>½   s   	 i    c            s.   i  |  ]$ \ } } | ˆ  j  k r | | “ q S(    (   R5   (   R   R	   R
   (   RH   (    s-   lib/python2.7/site-packages/dask/blockwise.pys
   <dictcomp>Â   s   	 (   RA   R    R   R0   t   maxR   (   RH   t   dRA   R	   R
   R9   t   b(    (   RH   s-   lib/python2.7/site-packages/dask/blockwise.pyRV   »   s     'N(   t   __name__t
   __module__t   __doc__R   RI   t   propertyRN   RP   RR   RX   RV   (    (    (    s-   lib/python2.7/site-packages/dask/blockwise.pyR2   p   s   $
			c   #         s|  | j  d ƒ } | j  d d ƒ } | j  d i  ƒ } t t j d | ƒ ƒ } | t k rj d d l m } n  t | ƒ d „  | Dƒ k sŒ t	 ‚ d „  | Dƒ }	 |	 t | ƒ }
 t
 | | ƒ ‰  x? | j ƒ  D]1 \ } } t | t ƒ rï t | ƒ n d	 ˆ  | <qÈ Wt t j g  | D] } t ˆ  | ƒ ^ qŒ  ƒ } g  | D] } t t | | ƒ ƒ ^ q6} t ‡  f d
 †  |
 Dƒ ƒ } i  } g  } x| D]ÿ } g  } xã | D]Û \ } } | d k rÁ| j | ƒ q™t | f | | | ƒ } t d „  | | Dƒ ƒ r	t | | | ƒ } n | } | rgt | t ƒ rgg  t | ƒ D] \ } } | | k r1| ^ q1} | | | f } n  | j | ƒ q™W| j | ƒ q†W| s±g  | D] } t | ƒ ^ q–} n  g  | D] } | f | ^ q¸} | r<t | ƒ \ } }  |  r| j t j |  ƒ ƒ | }! n | }! g  | D] } t |  | |! f ^ q}" n  g  | D] } |  f | ^ qC}" | j t t | |" ƒ ƒ ƒ | S(   s   Tensor operation

    Applies a function, ``func``, across blocks from many different input
    collections.  We arrange the pattern with which those blocks interact with
    sets of matching indices.  E.g.::

        make_blockwise_graph(func, 'z', 'i', 'x', 'i', 'y', 'i')

    yield an embarrassingly parallel communication pattern and is read as

        $$ z_i = func(x_i, y_i) $$

    More complex patterns may emerge, including multiple indices::

        make_blockwise_graph(func, 'z', 'ij', 'x', 'ij', 'y', 'ji')

        $$ z_{ij} = func(x_{ij}, y_{ji}) $$

    Indices missing in the output but present in the inputs results in many
    inputs being sent to one function (see examples).

    Examples
    --------

    Simple embarrassing map operation

    >>> inc = lambda x: x + 1
    >>> make_blockwise_graph(inc, 'z', 'ij', 'x', 'ij', numblocks={'x': (2, 2)})  # doctest: +SKIP
    {('z', 0, 0): (inc, ('x', 0, 0)),
     ('z', 0, 1): (inc, ('x', 0, 1)),
     ('z', 1, 0): (inc, ('x', 1, 0)),
     ('z', 1, 1): (inc, ('x', 1, 1))}

    Simple operation on two datasets

    >>> add = lambda x, y: x + y
    >>> make_blockwise_graph(add, 'z', 'ij', 'x', 'ij', 'y', 'ij', numblocks={'x': (2, 2),
    ...                                                      'y': (2, 2)})  # doctest: +SKIP
    {('z', 0, 0): (add, ('x', 0, 0), ('y', 0, 0)),
     ('z', 0, 1): (add, ('x', 0, 1), ('y', 0, 1)),
     ('z', 1, 0): (add, ('x', 1, 0), ('y', 1, 0)),
     ('z', 1, 1): (add, ('x', 1, 1), ('y', 1, 1))}

    Operation that flips one of the datasets

    >>> addT = lambda x, y: x + y.T  # Transpose each chunk
    >>> #                                        z_ij ~ x_ij y_ji
    >>> #               ..         ..         .. notice swap
    >>> make_blockwise_graph(addT, 'z', 'ij', 'x', 'ij', 'y', 'ji', numblocks={'x': (2, 2),
    ...                                                       'y': (2, 2)})  # doctest: +SKIP
    {('z', 0, 0): (add, ('x', 0, 0), ('y', 0, 0)),
     ('z', 0, 1): (add, ('x', 0, 1), ('y', 1, 0)),
     ('z', 1, 0): (add, ('x', 1, 0), ('y', 0, 1)),
     ('z', 1, 1): (add, ('x', 1, 1), ('y', 1, 1))}

    Dot product with contraction over ``j`` index.  Yields list arguments

    >>> make_blockwise_graph(dotmany, 'z', 'ik', 'x', 'ij', 'y', 'jk', numblocks={'x': (2, 2),
    ...                                                          'y': (2, 2)})  # doctest: +SKIP
    {('z', 0, 0): (dotmany, [('x', 0, 0), ('x', 0, 1)],
                            [('y', 0, 0), ('y', 1, 0)]),
     ('z', 0, 1): (dotmany, [('x', 0, 0), ('x', 0, 1)],
                            [('y', 0, 1), ('y', 1, 1)]),
     ('z', 1, 0): (dotmany, [('x', 1, 0), ('x', 1, 1)],
                            [('y', 0, 0), ('y', 1, 0)]),
     ('z', 1, 1): (dotmany, [('x', 1, 0), ('x', 1, 1)],
                            [('y', 0, 1), ('y', 1, 1)])}

    Pass ``concatenate=True`` to concatenate arrays ahead of time

    >>> make_blockwise_graph(f, 'z', 'i', 'x', 'ij', 'y', 'ij', concatenate=True,
    ...     numblocks={'x': (2, 2), 'y': (2, 2,)})  # doctest: +SKIP
    {('z', 0): (f, (concatenate_axes, [('x', 0, 0), ('x', 0, 1)], (1,)),
                   (concatenate_axes, [('y', 0, 0), ('y', 0, 1)], (1,)))
     ('z', 1): (f, (concatenate_axes, [('x', 1, 0), ('x', 1, 1)], (1,)),
                   (concatenate_axes, [('y', 1, 0), ('y', 1, 1)], (1,)))}

    Supports Broadcasting rules

    >>> make_blockwise_graph(add, 'z', 'ij', 'x', 'ij', 'y', 'ij', numblocks={'x': (1, 2),
    ...                                                      'y': (2, 2)})  # doctest: +SKIP
    {('z', 0, 0): (add, ('x', 0, 0), ('y', 0, 0)),
     ('z', 0, 1): (add, ('x', 0, 1), ('y', 0, 1)),
     ('z', 1, 0): (add, ('x', 0, 0), ('y', 1, 0)),
     ('z', 1, 1): (add, ('x', 0, 1), ('y', 1, 1))}

    Support keyword arguments with apply

    >>> def f(a, b=0): return a + b
    >>> make_blockwise_graph(f, 'z', 'i', 'x', 'i', numblocks={'x': (2,)}, b=10)  # doctest: +SKIP
    {('z', 0): (apply, f, [('x', 0)], {'b': 10}),
     ('z', 1): (apply, f, [('x', 1)], {'b': 10})}

    Include literals by indexing with ``None``

    >>> make_blockwise_graph(add, 'z', 'i', 'x', 'i', 100, None,  numblocks={'x': (2,)})  # doctest: +SKIP
    {('z', 0): (add, ('x', 0), 100),
     ('z', 1): (add, ('x', 1), 100)}


    See Also
    --------
    dask.array.blockwise
    dask.blockwise.blockwise
    R    R!   R"   i   iÿÿÿÿ(   t   concatenate_axesc         S   s(   h  |  ] \ } } | d  k	 r | ’ q S(   N(   R   (   R   R;   R   (    (    s-   lib/python2.7/site-packages/dask/blockwise.pys	   <setcomp>7  s   	 c         S   s/   h  |  ]% \ } } | r | D] } | ’ q q S(    (    (   R   R   R   R   (    (    s-   lib/python2.7/site-packages/dask/blockwise.pys	   <setcomp>9  s   	 i   c         3   s+   |  ]! } | t  t ˆ  | ƒ ƒ f Vq d  S(   N(   R   R.   (   R   R   (   t   dims(    s-   lib/python2.7/site-packages/dask/blockwise.pys	   <genexpr>G  s    c         s   s   |  ] } | d  k Vq d S(   i   N(    (   R   t   nb(    (    s-   lib/python2.7/site-packages/dask/blockwise.pys	   <genexpr>T  s    N(   R)   R   R   R,   R-   t   Truet   dask.array.coreR`   R   t   AssertionErrort   broadcast_dimensionsR   R   R   R/   t	   itertoolst   productR.   R   R0   t   appendt
   lol_tuplest   anyt   zero_broadcast_dimensionsR*   R   t   updateR   t   ensure_dictR   (#   R3   R4   t   out_indicesR6   R7   R    R!   R"   R:   t   all_indicest   dummy_indicesR	   R
   R   t   keytupst   tupt   keydictst   dummiesRG   t   valtupst   kdt   argst   argR   t   tupst   tups2R(   t   axest   vtt   ktRB   R   t   dsk2RE   t   vals(    (   Ra   s-   lib/python2.7/site-packages/dask/blockwise.pyRL   Å   sX    j")2(1" 	( c         C   s}   | s
 |  S| d | k r@ t  |  | | d f | d | | ƒ Sg  | | d D]& } t  |  | f | d | | ƒ ^ qO Sd S(   sD   List of list of tuple keys

    Parameters
    ----------

    head : tuple
        The known tuple so far
    ind : Iterable
        An iterable of indices not yet covered
    values : dict
        Known values for non-dummy indices
    dummies : dict
        Ranges of values for dummy indices

    Examples
    --------

    >>> lol_tuples(('x',), 'ij', {'i': 1, 'j': 0}, {})
    ('x', 1, 0)

    >>> lol_tuples(('x',), 'ij', {'i': 1}, {'j': range(3)})
    [('x', 1, 0), ('x', 1, 1), ('x', 1, 2)]

    >>> lol_tuples(('x',), 'ij', {'i': 1}, {'j': range(3)})
    [('x', 1, 0), ('x', 1, 1), ('x', 1, 2)]

    >>> lol_tuples(('x',), 'ijk', {'i': 1}, {'j': [0, 1, 2], 'k': [0, 1]}) # doctest: +NORMALIZE_WHITESPACE
    [[('x', 1, 0, 0), ('x', 1, 0, 1)],
     [('x', 1, 1, 0), ('x', 1, 1, 1)],
     [('x', 1, 2, 0), ('x', 1, 2, 1)]]
    i    i   N(   Rj   (   t   headR   RW   Ru   R
   (    (    s-   lib/python2.7/site-packages/dask/blockwise.pyRj   u  s     &c         C   sG   t  |  d | ƒ} x. | j |  j k rB | }  t  |  d | ƒ} q W| S(   sà   High level optimization of stacked Blockwise layers

    For operations that have multiple Blockwise operations one after the other, like
    ``x.T + 123`` we can fuse these into a single Blockwise operation.  This happens
    before any actual tasks are generated, and so can reduce overhead.

    This finds groups of Blockwise operations that can be safely fused, and then
    passes them to ``rewrite_blockwise`` for rewriting.

    Parameters
    ----------
    full_graph: HighLevelGraph
    keys: Iterable
        The keys of all outputs of all collections.
        Used to make sure that we don't fuse a layer needed by an output

    Returns
    -------
    HighLevelGraph

    See Also
    --------
    rewrite_blockwise
    RB   (   t   _optimize_blockwiseR#   (   t   graphRB   t   out(    (    s-   lib/python2.7/site-packages/dask/blockwise.pyt   optimize_blockwisež  s
    c            sö  d „  | Dƒ } |  j  } t j |  j ƒ ‰ ‡ f d †  |  j  Dƒ } t | ƒ } i  } i  } t ƒ  } x| rè| j ƒ  }	 |	 | k sh |	 | k r˜ qh n  | j |	 ƒ t | |	 t	 ƒ rŸ|	 h }
 t |
 ƒ } xˆ| rW| j ƒ  ‰  ˆ  | k r| j
 ˆ  ƒ qÐ n  t | ˆ  t	 ƒ s'| j
 ˆ  ƒ qÐ n  ˆ  |	 k rRˆ  | k rR| j
 ˆ  ƒ qÐ n  | ˆ  j | |	 j k r| j
 ˆ  ƒ qÐ n  t ‡  f d †  | |	 j Dƒ ƒ d k r»| j
 ˆ  ƒ qÐ n  |
 j ˆ  ƒ x‰ |  j j ˆ  d ƒ D]r } t | ˆ  j ƒ } d „  | ˆ  j Dƒ } t ˆ | ƒ d k rC| j | ƒ rC| j | ƒ qÞ| j
 | ƒ qÞWqÐ Wt g  |
 D] } | | ^ qbƒ } | | |	 <d „  | j Dƒ | |	 <qh | |	 | |	 <|  j j |	 t ƒ  ƒ | |	 <| j |  j j |	 d ƒ ƒ qh Wt | | ƒ S(	   Nc         S   s2   h  |  ]( } t  | ƒ t k r( | d  n | ’ q S(   i    (   R   R   (   R   R	   (    (    s-   lib/python2.7/site-packages/dask/blockwise.pys	   <setcomp>¿  s   	 c            s%   h  |  ] } ˆ  j  | ƒ s | ’ q S(    (   R   (   R   R	   (   t
   dependents(    s-   lib/python2.7/site-packages/dask/blockwise.pys	   <setcomp>Â  s   	 c         3   s-   |  ]# \ } } | d  k	 r | ˆ  k Vq d  S(   N(   R   (   R   R	   R   (   t   dep(    s-   lib/python2.7/site-packages/dask/blockwise.pys	   <genexpr>â  s    i   c         S   s/   h  |  ]% \ } } | r | D] } | ’ q q S(    (    (   R   R   R   R   (    (    s-   lib/python2.7/site-packages/dask/blockwise.pys	   <setcomp>í  s   	 c         S   s(   h  |  ] \ } } | d  k	 r | ’ q S(   N(   R   (   R   R	   R
   (    (    s-   lib/python2.7/site-packages/dask/blockwise.pys	   <setcomp>÷  s   	 (    (    (   t   dictsR    t   reverse_dictR#   R   R   R)   t   addR   R2   Ri   R!   t   sumRA   R   R5   R/   t
   issupersett   rewrite_blockwiset   extendR   (   t
   full_graphRB   t   keept   layerst   rootst   stackR„   R#   t   seent   layert   blockwise_layerst   depsRZ   R5   t   input_indicest   lt	   new_layer(    (   R‡   R†   s-   lib/python2.7/site-packages/dask/blockwise.pyR‚   ¾  s^    					)%#
 c            s±  d „  ˆ Dƒ ‰ ‡ f d †  ˆ j  ƒ  Dƒ } t j | ƒ } d „  t j ƒ  Dƒ } g  | j ƒ  D] \ } } | s^ | ^ q^ \ } t ˆ | j ƒ } ˆ | j } ˆ | j	 }	 t
 ˆ | j ƒ }
 t } xR| rt } x?t | ƒ D]1\ ‰ \ ‰  } | d k rqá n  ˆ  ˆ k rqá n  t } ‡  ‡ f d †  |
 j ƒ  Dƒ }
 | j ˆ ƒ \ } } d „  t ˆ d t | ƒ d ƒ Dƒ ‰ t |
 ˆ ƒ }
 ˆ ˆ  j } t
 t ˆ ˆ  j | ƒ ƒ ‰ ‡  ‡ f d †  | Dƒ } t
 t | | ƒ ƒ } ˆ j | ƒ g  | D]! \ } } | t | ˆ ƒ f ^ qò} x/ ˆ ˆ  j j ƒ  D] \ } } | | ˆ | <q-Wi  ‰ x› t | ƒ D] \ ‰ } y | | k } Wn t t f k
 r™t } n X| rÂt | j | ƒ ƒ ˆ t ˆ ƒ <q^t t | ƒ ƒ ˆ t ˆ ƒ <| j | ƒ q^Wt ˆ ˆ  j ˆ ƒ } |
 j | ƒ qá WqÈ Wg  | D]3 \ } } | t | t ƒ rKt | ƒ n | f ^ q!} g  } i  } i  ‰ x‡ t | ƒ D]y \ ‰ } | d d k	 r²| | k r²| | ˆ ˆ <qy| d d k	 rÕt | ƒ | | <n  t | ƒ ˆ ˆ <| j | ƒ qyWd „  ˆ j ƒ  Dƒ ‰ ‡ f d	 †  |
 j ƒ  Dƒ }
 d
 „  | Dƒ ‰ t j  g  ˆ j  ƒ  D] } | j! ^ qKƒ } ‡ f d †  | j ƒ  Dƒ } t" | ˆ | j |
 | d | d | d |	 ƒ} | S(   s¨   Rewrite a stack of Blockwise expressions into a single blockwise expression

    Given a set of Blockwise layers, combine them into a single layer.  The provided
    layers are expected to fit well together.  That job is handled by
    ``optimize_blockwise``

    Parameters
    ----------
    inputs : List[Blockwise]

    Returns
    -------
    blockwise: Blockwise

    See Also
    --------
    optimize_blockwise
    c         S   s   i  |  ] } | | j  “ q S(    (   R4   (   R   t   inp(    (    s-   lib/python2.7/site-packages/dask/blockwise.pys
   <dictcomp>  s   	 c            s/   i  |  ]% } ‡  f d  †  | j  Dƒ | j “ q S(   c            s4   h  |  ]* \ } } | d  k	 r | ˆ  k r | ’ q S(   N(   R   (   R   RZ   R
   (   R<   (    s-   lib/python2.7/site-packages/dask/blockwise.pys	   <setcomp>  s   	 	(   RA   R4   (   R   R›   (   R<   (    s-   lib/python2.7/site-packages/dask/blockwise.pys
   <dictcomp>  s   	c         s   s8   |  ]. } d  D]! } | | r( t  | ƒ n d Vq q d S(   t   ABCDEFGHIJKLMNOPQRSTUVWXYZt    N(   t   str(   R   RZ   R   (    (    s-   lib/python2.7/site-packages/dask/blockwise.pys	   <genexpr>  s   c            s5   i  |  ]+ \ } } t  | i ˆ  t ˆ ƒ 6ƒ | “ q S(    (   R   R   (   R   R	   R
   (   R‡   R   (    s-   lib/python2.7/site-packages/dask/blockwise.pys
   <dictcomp>2  s   	 c         S   s)   i  |  ] } t  | d  ƒ t  | ƒ “ q S(   i   (   R   (   R   R   (    (    s-   lib/python2.7/site-packages/dask/blockwise.pys
   <dictcomp>7  s   	 i   c            sH   h  |  ]> \ } } | d  k	 r | D] } | ˆ ˆ  j k r" | ’ q" q S(   N(   R   R5   (   R   R   t   jR   (   R‡   R<   (    s-   lib/python2.7/site-packages/dask/blockwise.pys	   <setcomp>>  s   	 	
c         S   s+   i  |  ]! \ } } t  | ƒ t  | ƒ “ q S(    (   R   (   R   R	   R
   (    (    s-   lib/python2.7/site-packages/dask/blockwise.pys
   <dictcomp>m  s   	 c            s(   i  |  ] \ } } t  | ˆ  ƒ | “ q S(    (   R   (   R   R	   R
   (   R&   (    s-   lib/python2.7/site-packages/dask/blockwise.pys
   <dictcomp>n  s   	 c         S   s(   h  |  ] \ } } | d  k	 r | ’ q S(   N(   R   (   R   R	   R
   (    (    s-   lib/python2.7/site-packages/dask/blockwise.pys	   <setcomp>p  s   	 c            s7   i  |  ]- \ } } | d  k s* | ˆ  k r | | “ q S(   N(   R   (   R   R	   R
   (   t   indices_check(    s-   lib/python2.7/site-packages/dask/blockwise.pys
   <dictcomp>r  s   	 	R    R"   R!   N(#   RW   R    R‰   Rg   t   countR   R   RA   R"   R!   R   RG   Rc   t   FalseR*   R   R)   R.   R/   R   R0   R5   Rm   R   t
   ValueErrorR   R   R=   Ri   R   R   R,   t   mergeR    R2   (   R<   R#   R†   t   new_index_iterR	   R
   t   rootRA   R"   R!   RG   t   changedR   R   t   current_dep_indicest   new_indicest
   contractedt   extraR   RŸ   R=   t   containst   new_dskR9   R[   R”   R›   R    R„   (    (   R‡   R   R    R<   R&   s-   lib/python2.7/site-packages/dask/blockwise.pyR      s€    .	'. 
"=+c            s   ‡  f d †  } t  j | |  ƒ S(   s	  

    >>> lol = [('x', 1, 0), ('x', 1, 1), ('x', 1, 2)]
    >>> nblocks = (4, 1, 2)  # note singleton dimension in second place
    >>> lol = [[('x', 1, 0, 0), ('x', 1, 0, 1)],
    ...        [('x', 1, 1, 0), ('x', 1, 1, 1)],
    ...        [('x', 1, 2, 0), ('x', 1, 2, 1)]]

    >>> zero_broadcast_dimensions(lol, nblocks)  # doctest: +NORMALIZE_WHITESPACE
    [[('x', 1, 0, 0), ('x', 1, 0, 1)],
     [('x', 1, 0, 0), ('x', 1, 0, 1)],
     [('x', 1, 0, 0), ('x', 1, 0, 1)]]

    See Also
    --------
    lol_tuples
    c            s,   |  d f t  d „  t |  d ˆ  ƒ Dƒ ƒ S(   Ni    c         s   s-   |  ]# \ } } | d  k r! d n | Vq d S(   i   i    N(    (   R   R   RZ   (    (    s-   lib/python2.7/site-packages/dask/blockwise.pys	   <genexpr>  s    i   (   R   R0   (   t   t(   t   nblocks(    s-   lib/python2.7/site-packages/dask/blockwise.pyt   <lambda>  R   (   R   t   homogeneous_deepmap(   t   lolR¯   t   f(    (   R¯   s-   lib/python2.7/site-packages/dask/blockwise.pyRl   {  s    c            sI  g  |  D]$ \ } } | d k	 r | | f ^ q } t j g  t j t j | t j | j ƒ  ƒ D]' \ \ } } \ } }	 t | |	 ƒ ^ q\ ƒ }
 t j d |
 ƒ } t d „  | j ƒ  Dƒ ƒ } t ‡  f d †  | j ƒ  Dƒ ƒ } | rò t j	 | | ƒ S| r6t
 t t | j ƒ  ƒ ƒ t
 d g ƒ k r6t d | ƒ ‚ n  t j	 t j | ƒ S(   sÃ   Find block dimensions from arguments

    Parameters
    ----------
    argpairs: iterable
        name, ijk index pairs
    numblocks: dict
        maps {name: number of blocks}
    sentinels: iterable (optional)
        values for singleton dimensions
    consolidate: func (optional)
        use this to reduce each set of common blocks into a smaller set

    Examples
    --------
    >>> argpairs = [('x', 'ij'), ('y', 'ji')]
    >>> numblocks = {'x': (2, 3), 'y': (3, 2)}
    >>> broadcast_dimensions(argpairs, numblocks)
    {'i': 2, 'j': 3}

    Supports numpy broadcasting rules

    >>> argpairs = [('x', 'ij'), ('y', 'ij')]
    >>> numblocks = {'x': (2, 1), 'y': (1, 3)}
    >>> broadcast_dimensions(argpairs, numblocks)
    {'i': 2, 'j': 3}

    Works in other contexts too

    >>> argpairs = [('x', 'ij'), ('y', 'ij')]
    >>> d = {'x': ('Hello', 1), 'y': (1, (2, 3))}
    >>> broadcast_dimensions(argpairs, d)
    {'i': 'Hello', 'j': (2, 3)}
    i    c         s   s@   |  ]6 \ } } | t  g  | D] \ } } | ^ q ƒ f Vq d  S(   N(   R   (   R   R	   R
   R   RZ   (    (    s-   lib/python2.7/site-packages/dask/blockwise.pys	   <genexpr>»  s    c         3   sC   |  ]9 \ } } | t  | ƒ d  k r4 | t ˆ  ƒ n | f Vq d S(   i   N(   R/   R   (   R   R	   R
   (   t	   sentinels(    s-   lib/python2.7/site-packages/dask/blockwise.pys	   <genexpr>½  s    i   s   Shapes do not align %sN(   R   R,   RM   t   joint   firstR   R0   t   groupbyR   t   valmapR   R1   R/   RW   R£   (   R:   R    R´   t   consolidateR9   R   t	   argpairs2R   t   indsRa   t   Lt   gt   g2(    (   R´   s-   lib/python2.7/site-packages/dask/blockwise.pyRf   ‘  s    %1	R"1(    (    (   i   (   Rg   t   numpyRT   t   cytoolzR,   t   ImportErrorR   R    R   t   compatibilityR   R   t   delayedR   t   highlevelgraphR   t   optimizationR   R   R   R   RF   R2   RL   Rj   R…   R‚   R   Rl   R   Rf   (    (    (    s-   lib/python2.7/site-packages/dask/blockwise.pyt   <module>   s.   			DU	°	) B	{		