B
    T\I+                 @   s   d dl mZmZmZ d dlmZ d dlZddlm	Z	m
Z
mZ ddlmZ ddlmZ dd	lmZmZ dd
lmZmZmZ ddlmZ ddlmZ d dlmZ e	e
eefZe	e
fZddefdfddZdd Zdd Z dd Z!dd Z"dd Z#dS )    )absolute_importdivisionprint_function)getitemN   )gettergetter_nofancygetter_inline   )optimize_blockwise)zip_longest)flattenreverse_dict)cullfuseinline_functions)ensure_dict)HighLevelGraph)IntegralTc             K   s   t t|}t| tr"t| |d} t| } |dk	r6|}t| |\}}t||}	t||	| |p^g  ||d\}
}|rt	|
|||d}n|
}t
|}|S )z Optimize dask for array computation

    1.  Cull tasks not necessary to evaluate keys
    2.  Remove full slicing, e.g. x[:]
    3.  Inline fast functions like getitem and np.transpose
    )keysN)Zrename_keys)dependenciesfast_functions)listr   
isinstancer   r   r   r   	hold_keysr   r   optimize_slices)dskr   Z	fuse_keysr   Zinline_functions_fast_functionsZrename_fused_keyskwargsZdsk2r   ZholdZdsk3Zdsk4Zdsk5 r   6lib/python3.7/site-packages/dask/array/optimization.pyoptimize   s     	


r    c             C   s   t |}dd |  D }t|}x|D ]}|| }x|D ]}| | }t|tkr:|r:|d tkr:yNxHt|| dkrtt|| }	| |	 }
|
d tks|
| kr|	}qfP qfW W n t	t
fk
r   Y nX || q:W q(W |S )a#   Find keys to avoid fusion

    We don't want to fuse data present in the graph because it is easier to
    serialize as a raw value.

    We don't want to fuse chains after getitem/GETTERS because we want to
    move around only small pieces of data, rather than the underlying arrays.
    c             S   s$   h | ]\}}t |ttfkr|qS r   )typetuplestr).0kvr   r   r   	<setcomp>F   s    zhold_keys.<locals>.<setcomp>r   r   )r   itemsr   r!   r"   GETTERSlennextiter
IndexError	TypeErrorappend)r   r   Z
dependentsdatar   ZdatZdepsZdepZtaskZnew_depZnew_taskr   r   r   r   <   s&    	


r   c          	      s  t tjf |  } xt|  D ]f\}}t|tkr|d tkrt|dkrt|dkrp|\}}}|t	k	}d}n|\}}}}}xht|tkr|d tkrt|dkrt|dkr|\}}	}
|t	k	}d}n|\}}	}
}}|r||k	rP t|tkt|
tkkrP t|tkrl|
| }t|t|
krFt
dd |D rFP |tkrt
 fdd|D rP n(|tkrt| kst|
 krP y t|
|}|tkrtn|}W n tk
r   P Y nX |	||  }}}||O }qW |tkrNt|tkr"|js"|jdkr"|jdksDt|tkrNtdd |D rN|| |< q|t	ksd|rt|st|||f| |< q|||||f| |< qW | S )	z Optimize slices

    1.  Fuse repeated slices, like x[5:][2:6] -> x[7:11]
    2.  Remove full slices, like         x[:] -> x

    See also:
        fuse_slice_dict
    r   )      r1   Nc             s   s   | ]}|d kV  qd S )Nr   )r$   ir   r   r   	<genexpr>   s    z"optimize_slices.<locals>.<genexpr>c             3   s   | ]}t | V  qd S )N)r   )r$   r3   )fancy_ind_typesr   r   r4      s    c             s   s6   | ].}t |tko,|j o,|jd ko,|jd kV  qd S )N)r!   slicestartstopstep)r$   sr   r   r   r4      s   )r   npZndarraycopyr(   r!   r"   r)   r*   r   anyr   
fuse_slicer	   r   NotImplementedErrorGETNOREMOVEr6   r7   r8   r9   all)r   r%   r&   getaZa_indexZ	a_asarrayZa_lockf2bZb_indexZ	b_asarrayZb_lockindicesZc_indexr   )r5   r   r   b   sb    	
$
.





r   c             C   s`   | j | j| j  }}}|dkr"d}|dkr.d}|dk sN|dk sN|dk	rT|dk rTt t|||S )zs Replace Nones in slices with integers

    >>> normalize_slice(slice(None, None, None))
    slice(0, None, 1)
    Nr   r   )r7   r8   r9   r?   r6   )r:   r7   r8   r9   r   r   r   normalize_slice   s     rG   c             C   sB   x<t | |td dD ]&\}}t|tk	rt|trtdqW d S )N)	fillvaluezCan't handle normal indexing with integers and fancy indexing if the integers and fancy indices don't align with the same dimensions.)r   r6   r!   r   r   r   r?   )ZfancyZnormalfnr   r   r   #check_for_nonfusible_fancy_indexing   s    rK   c       
         s   dkr$t |tr$|tddkr$dS t  tr6t  t |trHt|}t  trzt |trz|dk rjt  j| j  S t  trt |tr j j|j  }|jdk	r j j|j  }nd} jdk	r|dk	rt j|}n j} j|j }|dkrd}t|||S t |t	r0 fdd|D S t  t	rTt |ttfrT | S t  t
rrt |t
sr|f}t  t
rt |t
rtdd  D }tdd |D }|r|rtd	n"|rt | n|rt|  d}t	 }xtt D ]~}	t  |	 ts |t|kr2| |	  qx&|| dkrX|d |d7 }q4W |t |	 ||  |d7 }qW x*|t|k r|||  |d7 }qW t
|S t dS )
a   Fuse stacked slices together

    Fuse a pair of repeated slices into a single slice:

    >>> fuse_slice(slice(1000, 2000), slice(10, 15))
    slice(1010, 1015, None)

    This also works for tuples of slices

    >>> fuse_slice((slice(100, 200), slice(100, 200, 10)),
    ...            (slice(10, 15), [5, 2]))
    (slice(110, 115, None), [150, 120])

    And a variety of other interesting cases

    >>> fuse_slice(slice(1000, 2000), 10)  # integers
    1010

    >>> fuse_slice(slice(1000, 2000, 5), slice(10, 20, 2))
    slice(1050, 1100, 10)

    >>> fuse_slice(slice(1000, 2000, 5), [1, 2, 3])  # lists
    [1005, 1010, 1015]

    >>> fuse_slice(None, slice(None, None))  # doctest: +SKIP
    None
    Nr   r   c                s   g | ]}t  |qS r   )r>   )r$   Zbb)rC   r   r   
<listcomp>  s    zfuse_slice.<locals>.<listcomp>c             s   s   | ]}t |tV  qd S )N)r   r   )r$   itemr   r   r   r4     s    zfuse_slice.<locals>.<genexpr>c             s   s   | ]}t |tV  qd S )N)r   r   )r$   rM   r   r   r   r4     s    z#Can't handle multiple list indexing)r   r6   rG   r   r?   r7   r9   r8   minr   r"   r=   rK   ranger*   r/   r>   )
rC   rE   r7   r8   r9   Za_has_listsZb_has_listsjresultr3   r   )rC   r   r>      sl     







r>   )$Z
__future__r   r   r   operatorr   Znumpyr;   Zcorer   r   r	   Z	blockwiser   Zcompatibilityr   r   r   optimizationr   r   r   Zutilsr   Zhighlevelgraphr   Znumbersr   r)   r@   r    r   r   rG   rK   r>   r   r   r   r   <module>   s&   "&K