
    Cd&2                       d dl mZ d dlmZ d dlmZ d dlmZ d dlm	Z	 d dl
Zd dlmZ d dlmZ d d	lmZmZmZ d d
lmZmZ d dlmZmZ d dlmZ d dlmZmZmZ d dl m!Z! eeeefZ"eefZ#ddefdfdZ$d Z%ddZ&d Z'd Z(d Z)d Z*dS )    )annotations)Callable)zip_longest)Integral)AnyN)config)getitem)gettergetter_inlinegetter_nofancy)
fuse_rootsoptimize_blockwise)flattenreverse_dict)HighLevelGraph)SubgraphCallablefuseinline_functions)ensure_dictTc                   t          |t          t          f          s|g}t          t          |                    }t          | t                    s$t	          j        t          |           | d          } t          | |          } t          | |          } | 	                    t          |                    } t          j        d          du r| S |                                 }t          |           } ||}t          | |          }t          | ||z   |pg z   ||          \  } }|rt!          | |||          } t#          |           S )	zOptimize 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
     )dependencies)keyszoptimization.fuse.activeFN)rename_keys)r   fast_functions)
isinstancelistsetr   r   from_collectionsidr   r   cullr   getget_all_dependenciesr   	hold_keysr   r   optimize_slices)	dskr   	fuse_keysr   inline_functions_fast_functionsrename_fused_keyskwargsr   holds	            7lib/python3.11/site-packages/dask/array/optimization.pyoptimizer-      sc    dT3K(( vDc>** M-bggsLLL
St
,
,
,C
St
$
$
$C
((3t99

C z,--66
++--L
c

C !*8'S,''DtyB'%	  C ' 
%:	
 
 
 3    c                   t          |          }d |                                 D             }t          |          }|D ]}||         }|D ]}| |         }t          |          r	 t	          ||                   dk    rZt          t          ||                             }	| |	         }
t          |
          s|
| v r|	}nnt	          ||                   dk    Zn# t          t          f$ r Y nw xY 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                R    h | ]$\  }}t          |          t          t          fv"|%S r   )typetuplestr).0kvs      r,   	<setcomp>zhold_keys.<locals>.<setcomp>^   s0    EEE$!Qa)D)DA)D)D)Dr.      )
r   itemsr   _is_getter_tasklennextiter
IndexError	TypeErrorappend)r&   r   
dependentsdatar$   datdepsdeptasknew_depnew_tasks              r,   r$   r$   T   s>    l++JEE#))++EEEDT

I & &# 	& 	&Cs8D
 t$$ &jo..!33"&tJsO'<'<"="=#&w< +844 "C")CC! jo..!33 #I.   D  %%%'	&( s   %A3CC-,C-return3tuple[Callable, Any, Any, bool, bool | None] | Nonec                0   t          |           t          urdS | d         }d}|t          v r|}nt          |t                    rt          |j                  dk    rst          t          |j        	                                                    }t          |          t          u r*t          |          dk    r|d         t          v r|d         }|dS t          |           }|dk    r|| d         | d         |t          udfS |dk    r|g| dd         R S dS )a  Check if a value in a Dask graph looks like a getter.

    1. Is it a tuple with the first element a known getter.
    2. Is it a SubgraphCallable with a single element in its
       dsk which is a known getter.

    If a getter is found, it returns a tuple with (getter, array, index, asarray, lock).
    Otherwise it returns ``None``.

    TODO: the second check is a hack to allow for slice fusion between tasks produced
    from blockwise layers and slicing operations. Once slicing operations have
    HighLevelGraph layers which can talk to Blockwise layers this check *should* be
    removed, and we should not have to introspect SubgraphCallables.
    Nr   r8            )r1   r2   GETTERSr   r   r;   r&   r<   r=   valuesr	   )valuefirstr"   r6   lengths        r,   r:   r:   z   s   " E{{%t!HEC 
E+	,	, UY11D1Dei&&(())**77eA

qtwA$C
{tZZF{{E!HeAh7(:D@@	1U122Y4r.   c                j   t           t          j        f|                                 } |                                 D ]\  }}t          |          x}r|\  }}}}}t          |          x}	r7|	\  }
}}}}|r||urn't          |          t          u t          |          t          u k    rnt          |          t          u re||z   }t          |          t          |          k    rt          d |D                       rn|
t          u rt          fd|D                       rn~n,|
t          u r#t          |          v st          |          v rnQ	 t          ||          }|
t          u rt          n|
}n# t          $ r Y n!w xY w|||}}}||z  }t          |          x}	7|t          vrat          |          t           u r|j        s|j        |j        /t          |          t          u r t)          d |D                       r|| |<   |t*          u s|r|s
|||f| |<   |||||f| |<   | S )zOptimize 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
    c              3     K   | ]}|d u V  	d S Nr   )r4   is     r,   	<genexpr>z"optimize_slices.<locals>.<genexpr>   s&      ;W;W!AI;W;W;W;W;W;Wr.   c              3  8   K   | ]}t          |          V  d S rV   )r   )r4   rW   fancy_ind_typess     r,   rX   z"optimize_slices.<locals>.<genexpr>   s>       4 4;<
1o664 4 4 4 4 4r.   Nc              3  v   K   | ]4}t          |          t          u o|j         o|j        d u o|j        d u V  5d S rV   )r1   slicestartstopstep)r4   ss     r,   rX   z"optimize_slices.<locals>.<genexpr>   sm        
 	 Q5( + !K+FdN+ FdN	     r.   )r   npndarraycopyr9   r:   r1   r2   r;   anyr   
fuse_slicer   r
   NotImplementedErrorGETNOREMOVEr\   r]   r^   r_   allr	   )r&   r5   r6   a_taskr"   aa_index	a_asarraya_lockb_taskf2bb_index	b_asarrayb_lockindicesc_indexrZ   s                    @r,   r%   r%      s    RZ(O
((**C		 => =>1$Q'''6 <	>17.CGY+A...& '4:1Aw	6 fF22MMU*W0FGG==E))%/G7||s7||33;W;Ww;W;W;W8W8W3^++ 4 4 4 4@G4 4 4 1 1+ >))MM_44W8X8X('::G %'-$7$7&&RCC*   E%&F7Y&	9 ,A...& '> +%%MMU**#M +,, MMU**  
 ")     + AIf
 q'*Aq'9f=AJs   "E99
FFc                    | j         | j        | j        }}}|d}|d}|dk     s|dk     s||dk     rt                      t	          |||          S )zrReplace Nones in slices with integers

    >>> normalize_slice(slice(None, None, None))
    slice(0, None, 1)
    Nr   r8   )r]   r^   r_   rf   r\   )r`   r]   r^   r_   s       r,   normalize_slicerw      sg     4E}|qyyD1HH 0TAXX!###d###r.   c                    t          | |t          d                     D ]?\  }}t          |          t          ur$t	          |t
                    rt          d          @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   r\   r1   r   r   r   rf   )fancynormalfns       r,   #check_for_nonfusible_fancy_indexingr~     sn     E6U4[[AAA  177$:a#:#:%2   r.   c                     +t          |t                    r|t          dd          k    rdS t           t                    rt                      t          |t                    rt          |          }t           t                    r;t          |t                    r&|dk     rt	                       j        | j        z  z   S t           t                    rt          |t                    r j         j        |j        z  z   }|j         j         j        |j        z  z   }nd} j        |t           j        |          }n j        } j        |j        z  }|dk    rd}t          |||          S t          |t                    r fd|D             S t           t                    r$t          |t          t          f          r |         S t           t                    rt          |t                    s|f}t           t                    rt          |t                    rt          d  D                       }t          d |D                       }|r|rt	          d          |rt           |           n|rt          |            d}t                      }t          t                               D ]}	t           |	         t                    s|t          |          k    r|                     |	                    L||         "|                    d           |dz  }||         "|                    t!           |	         ||                              |dz  }|t          |          k     r3|                    ||                    |dz  }|t          |          k     3t          |          S t	                      )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   r8   c                0    g | ]}t          |          S r   )re   )r4   bbrj   s     r,   
<listcomp>zfuse_slice.<locals>.<listcomp>N  s#    ...b
1b!!...r.   c              3  @   K   | ]}t          |t                    V  d S rV   r   r   r4   items     r,   rX   zfuse_slice.<locals>.<genexpr>Y  ,      ??T*T400??????r.   c              3  @   K   | ]}t          |t                    V  d S rV   r   r   s     r,   rX   zfuse_slice.<locals>.<genexpr>Z  r   r.   z#Can't handle multiple list indexing)r   r\   rw   r   rf   r]   r_   r^   minr   r2   rd   r~   ranger;   r@   re   )
rj   rp   r]   r^   r_   a_has_listsb_has_listsjresultrW   s
   `         r,   re   re     s   : 	yZ5))ya5t3D3D.D.Dt !U A!U A!U $
1h 7 7 $q55%'''wQV##!U (
1e 4 4 (!&17**67QVaf_,DDD6164((vv199DUD$'''!T /....A....!T z!h->?? t!U Jq%$8$8 D !U 
1e 4 4 ??Q???????Q????? 	6; 	6%&KLLL 	6/15555 	6/1555s1vv 		 		A!A$)) Q#a&&[[ad###A$,d###Q A$, MM*QqT1Q400111FAA#a&&jjMM!A$FA #a&&jj V}}


r.   )rI   rJ   )+
__future__r   collections.abcr   	itertoolsr   numbersr   typingr   numpyra   daskr   dask.array.chunkr	   dask.array.corer
   r   r   dask.blockwiser   r   	dask.corer   r   dask.highlevelgraphr   dask.optimizationr   r   r   
dask.utilsr   rO   rg   r-   r$   r:   r%   rw   r~   re   r   r.   r,   <module>r      s   " " " " " " $ $ $ $ $ $ ! ! ! ! ! !                       $ $ $ $ $ $ A A A A A A A A A A 9 9 9 9 9 9 9 9 + + + + + + + + . . . . . . F F F F F F F F F F " " " " " " >='
: ~& %2$46  6  6  6 r# # #L( ( ( (VJ J JZ$ $ $    `  `  `  `  ` r.   