
    tf&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*y)    )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        | |      } | j                  t        |            } t        j                  d      du r| S | j                         }t        |       } ||}t        | |      }t        | ||z   |xs 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.activeF)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	            a/var/www/html/software/conda/envs/higlass/lib/python3.12/site-packages/dask/array/optimization.pyoptimizer-      s    dT3K(vDc>*--bgsL
St
,C
St
$C
((3t9
C zz,-6
++-L
c
C !*8'S,'DtyB'%	C '%:	
 3    c                   t        |      }| j                         D ch c]  \  }}t        |      t        t        fvs|! }}}t        |      }|D ]  }||   }|D ]w  }	| |	   }
t        |
      s	 t        ||	         dk(  rAt        t        ||	               }| |   }t        |      s|| v r|}	nnt        ||	         dk(  rA|j                  |	       y  |S c c}}w # t        t        f$ r Y .w xY w)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.
       )r   itemstypetuplestrr   _is_getter_tasklennextiter
IndexError	TypeErrorappend)r&   r   
dependentskvdatar$   datdepsdeptasknew_depnew_tasks                r,   r$   r$   T   s    l+J))+E$!Qa)DAEDET
I &# 	&Cs8D
 t$jo.!3"&tJsO'<"=#&w< +84C")C! jo.!3   %'	&&, 3 F, #I. s   CC2AC!!C32C3c                   t        |       t        ury| d   }d}|t        v r|}nt        |t              rst        |j                        dk(  r[t        t        |j                  j                                     }t        |      t        u rt        |      dkD  r|d   t        v r|d   }|yt        |       }|dk(  r|| d   | d   |t        udfS |dk(  r	|g| dd S y)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   r0            )r2   r3   GETTERSr   r   r6   r&   r7   r8   valuesr	   )valuefirstr"   r>   lengths        r,   r5   r5   z   s    " E{%!HEC 
E+	,UYY11Deii&&()*7eA
qtwA$C
{ZF{E!HeAh7(:D@@	1U12Yr.   c                   t         t        j                  f| j                         } | j	                         D ]  \  }}t        |      x}s|\  }}}}}t        |      x}	r|	\  }
}}}}|r||urnt        |      t        u t        |      t        u k7  rnt        |      t        u rL||z   }t        |      t        |      k7  rt        d |D              rnv|
t        u r8t        fd|D              r$nY|
t        u rt        |      v st        |      v rn6	 t        ||      }|
t        u rt        n|
}|||}}}||z  }t        |      x}	r|t        vr_t        |      t         u r$|j"                  s|j$                  |j&                  #t        |      t        u rt)        d |D              r|| |<   z|t*        u s|r|s
|||f| |<   |||||f| |<    | S # t        $ r Y w xY w)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  
 y wNr   ).0is     r,   	<genexpr>z"optimize_slices.<locals>.<genexpr>   s     ;W!AI;Ws   c              3  6   K   | ]  }t        |        y wrQ   )r   )rR   rS   fancy_ind_typess     r,   rT   z"optimize_slices.<locals>.<genexpr>   s      4;<
1o64s   c              3     K   | ]D  }t        |      t        u xr- |j                   xr |j                  d u xr |j                  d u  F y wrQ   )r2   slicestartstopstep)rR   ss     r,   rT   z"optimize_slices.<locals>.<genexpr>   sX      
 	 Q5( + !K+FFdN+ FFdN+s   A
A)r   npndarraycopyr1   r5   r2   r3   r6   anyr   
fuse_slicer   r
   NotImplementedErrorGETNOREMOVErX   rY   rZ   r[   allr	   )r&   r=   r>   a_taskr"   aa_index	a_asarraya_lockb_taskf2bb_index	b_asarrayb_lockindicesc_indexrV   s                    @r,   r%   r%      s    RZZ(O
((*C		 =>1$Q''6'17.CGY+A..&.4:1Aw	6fF2MU*W0FG=E)%/G7|s7|3;Ww;W8W^+ 4@G4 1 >)M_4W8X(':G %'-$7&RC &'F7Y&	9 ,A..&.> +%MU*#MM,, MU* 
 ")  AIf
 q'*Aq'9f=A{=>~ JE + s   G	G#"G#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)
    r   r0   )rY   rZ   r[   rb   rX   )r\   rY   rZ   r[   s       r,   normalize_slicers      sa     4E}|qyD1H 0TAX!##d##r.   c                    t        | |t        d             D ]2  \  }}t        |      t        ust	        |t
              s)t        d       y )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   rX   r2   r   r   r   rb   )fancynormalfns       r,   #check_for_nonfusible_fancy_indexingrz     sK     E6U4[A 17$:a#:%2 r.   c                   |  t        |t              r|t        dd      k(  ry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|D cg c]  }t        | |       c}S t        | t              rt        |t        t        f      r| |   S t        | t              rt        |t              s|f}t        | t              rDt        |t              r3t        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|	j!                  | |
          9||   |	j!                  d       |dz  }||   |	j!                  t        | |
   ||                |dz  } |t        |      k  r(|	j!                  ||          |dz  }|t        |      k  r(t        |	      S t	               c c}w )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   r0   c              3  <   K   | ]  }t        |t                y wrQ   r   r   rR   items     r,   rT   zfuse_slice.<locals>.<genexpr>Y       ?T*T40?   c              3  <   K   | ]  }t        |t                y wrQ   r}   r~   s     r,   rT   zfuse_slice.<locals>.<genexpr>Z  r   r   z#Can't handle multiple list indexing)r   rX   rs   r   rb   rY   r[   rZ   minr   ra   r3   r`   rz   ranger6   r;   )rf   rl   rY   rZ   r[   bba_has_listsb_has_listsjresultrS   s              r,   ra   ra     s   : 	yZ5)a5t3D.D !UA!UA!U
1h 7q5%''wwQVV##!U
1e 4!&&177**6677QVVaff_,DD661664(vvvv19DUD$''!T,-.b
1b!..!Tz!h->?t!UJq%$8D !U
1e 4?Q???Q??;%&KLL/15/15s1v 		A!A$)Q#a&[ad#A$,d#Q A$, MM*QqT1Q401FA		 #a&jMM!A$FA #a&j V}

I /s   M)returnz3tuple[Callable, Any, Any, bool, bool | None] | None)+
__future__r   collections.abcr   	itertoolsr   numbersr   typingr   numpyr]   daskr   dask.array.chunkr	   dask.array.corer
   r   r   dask.blockwiser   r   	dask.corer   r   dask.highlevelgraphr   dask.optimizationr   r   r   
dask.utilsr   rJ   rc   r-   r$   r5   r%   rs   rz   ra   r   r.   r,   <module>r      s    " $ !     $ A A 9 + . F F " >='
: ~& %2$46 r#L(8(VJZ$  ` r.   