
    Lg                    X   d dl mZ d dlZd dlZd dlm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 d dlmZmZ d d	lmZmZmZmZmZmZmZ d dlmZmZ d d
lmZmZ d Zd Z ddZ!d Z"ddZ#	 ddZ$d Z%d Z&ddZ' G d de      Z(e(jR                  Z*dde*e*e*e*e*e*fdZ+d Z, G d d      Z-y)    )annotationsN)Iterable)Enum)Any)configcoreutils)	GraphNode)normalize_tokentokenize)flattenget_dependencies
ishashableistaskreverse_dictsubstoposort)GraphKeyc                T   t        |t        t        f      s|g}t               }t               }i }t        t        t	        |                  }|rWg }|D ]K  }t        | |d      }| |   ||<   |||<   |D ])  }	|	|vs|j                  |	       |j                  |	       + M |}|rW||fS )a<  Return new dask with only the tasks required to calculate keys.

    In other words, remove unnecessary tasks from dask.
    ``keys`` may be a single key or list of keys.

    Examples
    --------
    >>> def inc(x):
    ...     return x + 1

    >>> def add(x, y):
    ...     return x + y

    >>> d = {'x': 1, 'y': (inc, 'x'), 'out': (add, 'x', 10)}
    >>> dsk, dependencies = cull(d, 'out')
    >>> dsk                                                     # doctest: +ELLIPSIS
    {'out': (<function add at ...>, 'x', 10), 'x': 1}
    >>> dependencies                                            # doctest: +ELLIPSIS
    {'out': ['x'], 'x': []}

    Returns
    -------
    dsk: culled dask graph
    dependencies: Dict mapping {key: [deps]}.  Useful side effect to accelerate
        other optimizations, notably fuse.
    Tas_list)
isinstancelistsetdictr   r   addappend)
dskkeysseendependenciesoutworknew_workkdependencies_kds
             1lib/python3.12/site-packages/dask/optimization.pycullr*      s    6 dT3K(v5D6L
CGDM"#D
A-c1dCNVCF,LO#D=HHQKOOA& $	        c                   t        | d         }|t        u rM| ddd   D cg c]  }t        j                  |       }}|j	                  | d          dj                  |      S |t        u rt        | d         dkD  rpt        | d   d   t              rZ| ddd   D cg c]  }t        j                  |       }}|j	                  | d   d          dj                  |      f| d   dd z   S yc c}w c c}w )zCreate new keys for fused tasksr   N-   )	typestrr	   	key_splitr   jointuplelenr   )r    typxnamess       r)   !default_fused_linear_keys_renamerr9   L   s    
tAw-C
cz-1%1R%[9[#[9T!Wxx	#d1g,*z$q'!*c/J-1%1R%[9[#[9T!WQZ !DGABK// : :s   C.C3c           	        |7t        |t              s't        |t              s|g}t        t        |            }|| D ci c]  }|t	        | |d       }}i }t               }| D ]k  }||   }t        |      dkD  }	|D ]Q  }
||
|v r|j                  |
       |
|v r||
= |j                  |
       4|	r|j                  |
       H|
|vsM|||
<   S m g }t        t        t        |j                                     }|r|j                         \  }
}|
|g}||v r*|j                  |      }||= |j                  |       ||v r*|j                          |
|v r*|j                  |
      }
||
= |j                  |
       |
|v r*|j                  |       |r|j                         D ci c]  \  }}|t        |       }}}|du rt        }n	|du rd}n|}i }t               }t               }d}|D ]  }| ||      }|duxr
 || vxr ||v}|j                         }
| |
   }|rm|j                         }||   j!                  |j                  |
             ||   j#                  |
       t%        | |   |
|      }|j                  |
       |}
|rm|j                  |
       |r*||<   |||
<   ||
   ||<   |h||
<   |j                  |
       |||
<    | j                         D ]  \  }}||vs|||<    |rn|j                         D ]I  \  }}||z  D ]<  }||   }|j#                  |       |j                  |       t%        ||   ||      ||<   > K |||z
  D ]  }||= ||= 
 ||fS c c}w c c}}w )a  Return new dask graph with linear sequence of tasks fused together.

    If specified, the keys in ``keys`` keyword argument are *not* fused.
    Supply ``dependencies`` from output of ``cull`` if available to avoid
    recomputing dependencies.

    **This function is mostly superseded by ``fuse``**

    Parameters
    ----------
    dsk: dict
    keys: list
    dependencies: dict, optional
        {key: [list-of-keys]}.  Must be a list to provide count of each key
        This optional input often comes from ``cull``
    rename_keys: bool or func, optional
        Whether to rename fused keys with ``default_fused_linear_keys_renamer``
        or not.  Renaming fused keys can keep the graph more understandable
        and comprehensive, but it comes at the cost of additional processing.
        If False, then the top-most key will be used.  For advanced usage, a
        func is also accepted, ``new_key = rename_keys(fused_key_list)``.

    Examples
    --------
    >>> def inc(x):
    ...     return x + 1

    >>> def add(x, y):
    ...     return x + y

    >>> d = {'a': 1, 'b': (inc, 'a'), 'c': (inc, 'b')}
    >>> dsk, dependencies = fuse(d)
    >>> dsk # doctest: +SKIP
    {'a-b-c': (inc, (inc, 1)), 'c': 'a-b-c'}
    >>> dsk, dependencies = fuse(d, rename_keys=False)
    >>> dsk # doctest: +ELLIPSIS
    {'c': (<function inc at ...>, (<function inc at ...>, 1))}
    >>> dsk, dependencies = fuse(d, keys=['b'], rename_keys=False)
    >>> dsk  # doctest: +ELLIPSIS
    {'b': (<function inc at ...>, 1), 'c': (<function inc at ...>, 'b')}

    Returns
    -------
    dsk: output graph with keys fused
    dependencies: dict mapping dependencies after fusion.  Useful side effect
        to accelerate other downstream optimizations.
    NTr   r/   F)r   r   r   r   r   r5   r   r   mapreverseditemspopitempopr   reverser9   updateremover   )r   r    r"   rename_keysr&   child2parent	unfusibleparentdepshas_many_childrenchildchainsparent2childchainvkey_renamerrvfusedaliases
is_renamednew_keyvalkeyold_keys                           r)   fuse_linearrW   [   s   ` 
4 5$%6D74=!KNO3a+CDAA3O LIF#IMEETMe$,& 'e$"e$i'&,U#   FHl&8&8&:;<L
$,,.v$!%%f-FV$LL  $ 	|# $$U+EU#LL |# 	e  +7*<*<*>?*>$!QAs1vI*>L?d7		! 
BEEeGJ"!%(Gt#Ps(:Pwb?P  		%jYY[F ''(8(8(?@ ''.s6{E3/CIIeE  			%BwKBuI$0$7L!#*)LKKBuI/ 0 IIKSeBsG   %++-IC'>W+G$!r#w93	 * . ~sG % & |q PH @s    M+)M0c                    | 
t               S t        | t               r| S t        | t        t         f      s| g} t        |       S N)r   r   r   )r7   s    r)   	_flat_setrZ      s;    yu	As	D#;'Cq6Mr+   c                    r]t        t        t        j                                     t              r-j                         D ci c]  \  }}|t        |       c}}t        |      } D ci c]  }|t         |       c}|r)|j                   fd j                         D               t        |D ci c]  }| v s| |    c}      }i }|D ]5  } |   }	||   z  D ]  }
|
|v r||
   }n |
   }t        |	|
|      }	  |	||<   7 |j                         } j                         D ],  \  }}	||vs||   z  D ]  }t        |	|||         }	 |	||<   . |S c c}}w c c}w c c}w )a  Return new dask with the given keys inlined with their values.

    Inlines all constants if ``inline_constants`` keyword is True. Note that
    the constant keys will remain in the graph, to remove them follow
    ``inline`` with ``cull``.

    Examples
    --------
    >>> def inc(x):
    ...     return x + 1

    >>> def add(x, y):
    ...     return x + y

    >>> d = {'x': 1, 'y': (inc, 'x'), 'z': (add, 'x', 'y')}
    >>> inline(d)       # doctest: +ELLIPSIS
    {'x': 1, 'y': (<function inc at ...>, 1), 'z': (<function add at ...>, 1, 'y')}

    >>> inline(d, keys='y') # doctest: +ELLIPSIS
    {'x': 1, 'y': (<function inc at ...>, 1), 'z': (<function add at ...>, 1, (<function inc at ...>, 1))}

    >>> inline(d, keys='y', inline_constants=False) # doctest: +ELLIPSIS
    {'x': 1, 'y': (<function inc at ...>, 'x'), 'z': (<function add at ...>, 'x', (<function inc at ...>, 'x'))}
    c              3  f   K   | ](  \  }}t        |      r|v s|   st        |      s| * y wrY   )r   r   ).0r&   rM   r"   r   s      r)   	<genexpr>zinline.<locals>.<genexpr>  s7      
#11!s(LOFSTI #s   .1)r"   )r   nextitervaluesr   r=   r   rZ   r   rA   r   r   copy)r   r    inline_constantsr"   r&   rM   replaceorderkeysubsrU   rT   depreplacedsk2items   `  `          r)   inlinerj      s   2 
4\-@-@-B(C#DdK.:.@.@.BC.Bda3q6	.BCT?D=@AS+C33SA 
		
 	
  -DqAHCFD-LL G#h,s++Cg~!#,c(sC)C ,   <<>DIIKSd?|C003gdm4 1DI	  
 KK D
 B 	.s   E&3E,>	E1E1c                D   	 s S t              t              | D ci c]  }|t         |       }}t        |      		 fd} j                         D cg c]  \  }} |||      s| }}}|rt	         |||       |D ]  } |=   S c c}w c c}}w )a  Inline cheap functions into larger operations

    Examples
    --------
    >>> inc = lambda x: x + 1
    >>> add = lambda x, y: x + y
    >>> double = lambda x: x * 2
    >>> dsk = {'out': (add, 'i', 'd'),  # doctest: +SKIP
    ...        'i': (inc, 'x'),
    ...        'd': (double, 'y'),
    ...        'x': 1, 'y': 1}
    >>> inline_functions(dsk, [], [inc])  # doctest: +SKIP
    {'out': (add, (inc, 'x'), 'd'),
     'd': (double, 'y'),
     'x': 1, 'y': 1}

    Protect output keys.  In the example below ``i`` is not inlined because it
    is marked as an output key.

    >>> inline_functions(dsk, ['i', 'out'], [inc, double])  # doctest: +SKIP
    {'out': (add, 'i', (double, 'y')),
     'i': (inc, 'x'),
     'x': 1, 'y': 1}
    c                    t        |t              sHt        |      r=| vr9|    r4	 t        |      j	                        rt        fd|    D              syyy# t        $ r Y yw xY w)Nc              3  D   K   | ]  }t        |   t                y wrY   r   r
   )r]   r(   r   s     r)   r^   z6inline_functions.<locals>.inlinable.<locals>.<genexpr>f  s!      K;JaJs1vy1?    TF)r   r
   r   functions_ofissubsetany	TypeError)rU   task
dependentsr   fast_functionsoutputs     r)   	inlinablez#inline_functions.<locals>.inlinable^  sw    4+t6!3%..~>s K;Ec?K H     s   1A 	A'&A')rc   r"   )r   r   r   r=   rj   )
r   rw   rv   rc   r"   r&   rx   rM   r    ru   s
   ```      @r)   inline_functionsry   8  s    6 
[F(N=@AS+C33SAl+J  ))+9+$!Q1aA+D9(8|
 AA J7 B& :s   B!B3Bc                P    t        | d      r| j                  } t        | d      r| S )Nfunc)hasattrr{   )r{   s    r)   unwrap_partialr}   y  s&    
$
yy $
Kr+   c                   t               }| g}t        t        h}|rjg }|D ]^  } t        |       |v st	        |       r2|j                  t        | d                |j                  | dd        N|j                  |        ` |}|rj|S )a1  Set of functions contained within nested task

    Examples
    --------
    >>> inc = lambda x: x + 1
    >>> add = lambda x, y: x + y
    >>> mul = lambda x, y: x * y
    >>> task = (add, (mul, 1, 2), (inc, 3))  # doctest: +SKIP
    >>> functions_of(task)  # doctest: +SKIP
    set([add, mul, inc])
    r   r/   N)r   r   r4   r0   r   r   r}   extend)rt   funcsr$   sequence_typesr%   s        r)   rp   rp     s     EE6DE]N
DDz^+$<IInT!W56OODH-OOD)    Lr+   c                   t        |       }t        |      }t        |      }rdz  fd}|t        u r}t	        j
                  |      }|D ch c]  }t	        j
                  |       }}|j                  |       t        |      }|j                  |       dj                  |      }	 ||	      S |t        u rt        |      dkD  rt        |d   t              rt	        j
                  |      }|D ch c]  }t	        j
                  |       }}|j                  |       t        |      }|j                  |d          dj                  |      }	 ||	      f|dd z   S yyyc c}w c c}w )zCreate new keys for ``fuse`` tasks.

    The optional parameter `max_fused_key_length` is used to limit the maximum string length for each renamed key.
    If this parameter is set to `None`, there is no limit.
       c                \    r(t        |       kD  rt        |       dd d }| d   d| } | S )Nr7      r.   )r5   hash)key_name	name_hashmax_fused_key_lengths     r)   _enforce_max_key_limitz:default_fused_keys_renamer.<locals>._enforce_max_key_limit  sF    CM4H$H>!,bq1I"#8$89:!I;GHr+   r.   r   r/   N)r<   r_   r0   r1   r	   r2   discardsortedr   r3   r4   r5   r   )
r    r   it	first_keyr6   r   
first_namer&   r8   concatenated_names
    `        r)   default_fused_keys_renamerr     sN    
$BRI
y/C! cz__Y/
-/0R#R0j!uYHHUO%&788	#i.1,IaL#1N__Y/
-/0R#R0j!uYq\"HHUO&'89;imKK 2O, 1 1s   E'6E,c                      e Zd ZdZddZy)Defaultr   c                     y)Nz	<default> selfs    r)   __repr__zDefault.__repr__  s    r+   Nreturnr1   )__name__
__module____qualname__tokenr   r   r+   r)   r   r     s    Er+   r   c	                x    t        j                  d      du r |fS |7t        |t              s't        |t              s|g}t        t        |            }|t        u rt        j                  d      }|t        usJ |t        u rt        j                  d      }|t        usJ |t        u rt        j                  d      }|t        usJ ||dz  }|t        u rt        j                  d      }|t        usJ |d|t        j                  |d	z         z  z   }|t        u rt        j                  d
      }|t        usJ |d}|r|s |fS |t        u rt        j                  d      }|t        usJ |du rt        }	n|du rd}	nt        |      st        d      |}	|	du}| D 
ci c]  }
|
t         |
d       }}
nA|j                         D 
ci c]&  \  }
}|
t        |t              r|nt         |
d      ( }}
}i }|j                         D ]9  \  }
}|D ]!  }||vr|
g||<   ||   j                  |
       # t        |      ||
<   ; t               }|j                         D ]  \  }
}t        |      d	k(  s|
|xs dvs|
 v s#t         |
   t               r7t#         |
         t$        u s$t         |
   t&        j(                  t*        f      sot-         fd|D              r|j/                  |
        |s&|r t1        d |j3                         D              r |fS  j5                         }i }g }g }|j6                  }|j.                  }|j6                  }|j8                  }|j6                  }|j                  }|j6                  }|j                  }|j:                  }|j6                  }|r |       } ||       ||v r||   d   }||v r ||        ||||   z         	 |d   }||k7  rK|||   z  } | r ||        |}|d   }|||   z  } | r |         ||||   |r|gndd	d	d	d||   |z
  f       n |        ||   }!|!|z
  }"|!|"z
  } t        |       }#|#d	k(  rG |       \  }$}%}&}'}(})}*}+t        |+      },|*|,d	z
  cxkD  rdk\  rn n|,d	z
  }*|"|+z  }"t        |"      |,k(  }-|-s|*d	z  }*|)|*z   |'z  |k  r|-s|'|k  rt         |   t               st=         |   |$|%      }.|!j9                  |$       |! ||$      z  }!||$=  ||$       |r|&j                  |       |&||<    ||$d       |r,|-r |||.|&|'|(|)|*|"f       n |||.|&|'d	z   |(|)d	z   |*|"f       ng|.||<   nj|%||$<    ||$       |r9|*t?        |d	z
        kD  rt?        |d	z
        }* ||||   |r|gndd	|(d	|*|"f       nn g }&d	}'d}(d}/d})d}*t               }+d}0||# d }1||# d= |1D ]J  \  }2}2}2}3}4}5}6}7|3d	k(  r|/d	z  }/n|3|'kD  r|3}'|(|4z  }(|)|5z  })|*|6z  }*t        |7      |0kD  rt        |7      }0|+|7z  }+L t        |+      },|*tA        |#d	z
  tC        d|,|0z
              z  }*|*|,d	z
  cxkD  rdk\  rn n|,d	z
  }*|"|+z  }"t        |"      |,k(  }-|-s|*d	z  }*|)|*z   |'z  |k  r|/|k  r|(|k  r|'|k  r|-s|'|k  rt         |   t               st-         fd| D              s |   }.t               }8|1D ]M  }9|9d   }:t=        |.|:|9d	         }.||:= |8 ||:      z  }8 ||:       |s1 ||:d       |&j;                  |9d          O |!| z  }!|!|8z  }!|r|&j                  |       |&||<   |r |||.|&|'d	z   |(|)d	z   |*|"f       ne|.||<   ni|1D ]  }9|9d	   ||9d   <    ||9d           |r?|(|kD  r|}(|*t?        |d	z
        kD  rt?        |d	z
        }* ||||   |r|gndd	|(d	|*|"f       nn
||   d   }|r|rtE        |||||       |	rC|j                         D ]0  \  };}< |	|<      }=|=|=|vs||;   ||=<   |=||;<   ||;   ||=<   |=h||;<   2 ||fS c c}
w c c}}
w )am  Fuse tasks that form reductions; more advanced than ``fuse_linear``

    This trades parallelism opportunities for faster scheduling by making tasks
    less granular.  It can replace ``fuse_linear`` in optimization passes.

    This optimization applies to all reductions--tasks that have at most one
    dependent--so it may be viewed as fusing "multiple input, single output"
    groups of tasks into a single task.  There are many parameters to fine
    tune the behavior, which are described below.  ``ave_width`` is the
    natural parameter with which to compare parallelism to granularity, so
    it should always be specified.  Reasonable values for other parameters
    will be determined using ``ave_width`` if necessary.

    Parameters
    ----------
    dsk: dict
        dask graph
    keys: list or set, optional
        Keys that must remain in the returned dask graph
    dependencies: dict, optional
        {key: [list-of-keys]}.  Must be a list to provide count of each key
        This optional input often comes from ``cull``
    ave_width: float (default 1)
        Upper limit for ``width = num_nodes / height``, a good measure of
        parallelizability.
        dask.config key: ``optimization.fuse.ave-width``
    max_width: int (default infinite)
        Don't fuse if total width is greater than this.
        dask.config key: ``optimization.fuse.max-width``
    max_height: int or None (default None)
        Don't fuse more than this many levels. Set to None to dynamically
        adjust to ``1.5 + ave_width * log(ave_width + 1)``.
        dask.config key: ``optimization.fuse.max-height``
    max_depth_new_edges: int or None (default None)
        Don't fuse if new dependencies are added after this many levels.
        Set to None to dynamically adjust to ave_width * 1.5.
        dask.config key: ``optimization.fuse.max-depth-new-edges``
    rename_keys: bool or func, optional (default True)
        Whether to rename the fused keys with ``default_fused_keys_renamer``
        or not.  Renaming fused keys can keep the graph more understandable
        and comprehensive, but it comes at the cost of additional processing.
        If False, then the top-most key will be used.  For advanced usage, a
        function to create the new name is also accepted.
        dask.config key: ``optimization.fuse.rename-keys``
    fuse_subgraphs : bool or None, optional (default None)
        Whether to fuse multiple tasks into ``SubgraphCallable`` objects.
        Set to None to let the default optimizer of individual dask collections decide.
        If no collection-specific default exists, None defaults to False.
        dask.config key: ``optimization.fuse.subgraphs``

    Returns
    -------
    dsk
        output graph with keys fused
    dependencies
        dict mapping dependencies after fusion.  Useful side effect to accelerate other
        downstream optimizations.
    zoptimization.fuse.activeFNzoptimization.fuse.ave-widthzoptimization.fuse.max-heightz%optimization.fuse.max-depth-new-edgesg      ?zoptimization.fuse.max-widthr/   zoptimization.fuse.subgraphszoptimization.fuse.rename-keysTz)rename_keys must be a boolean or callabler   r   c              3  D   K   | ]  }t        |   t                y wrY   rn   )r]   rM   r   s     r)   r^   zfuse.<locals>.<genexpr>_  s     Dt!
3q695tro   c              3  J   K   | ]  }t        t        |            d k7    yw)r/   N)r5   r   )r]   rM   s     r)   r^   zfuse.<locals>.<genexpr>d  s     !KNq#c!f+"2Ns   !#r   r-   c              3  D   K   | ]  }t        |   t                y wrY   rn   )r]   	child_keyr   s     r)   r^   zfuse.<locals>.<genexpr>7  s$      (19I !+3y>9 E19ro      )#r   getr   r   r   r   _defaultmathlogr   callablers   r   r=   r   r5   r
   r0   r4   numbersNumberr1   rr   r   allra   rb   r?   rB   r   r   intminmax_inplace_fuse_subgraphs)>r   r    r"   	ave_width	max_width
max_heightmax_depth_new_edgesrC   fuse_subgraphsrN   r&   rG   rM   rdepsvals	reduciblerO   fused_trees
info_stackchildren_stackdeps_popreducible_addreducible_popreducible_removefused_trees_popinfo_stack_appendinfo_stack_popchildren_stack_appendchildren_stack_extendchildren_stack_poprF   rI   childrendeps_parentedgesnum_childrenr   
child_task
child_keysheightwidth	num_nodesfudgechildren_edgesnum_children_edgesno_new_edgesrT   num_single_nodesmax_num_edgeschildren_info_
cur_height	cur_widthcur_num_nodes	cur_fudge	cur_edgeschildren_deps
child_info	cur_childroot_key
fused_keysaliass>   `                                                             r)   fuser     sT
   P zz,-6L  
4 5$%6D74=! HJJ<=	(((XZZ >?
)))h&$jj)PQ"(222"'#oHJJ<=	((()dhhy1}&===	!$ABX---JL  hjj!@A(***d0		k"CDD!T)KCFG3a#CD993G %**,
,1 Jq$'q-=c1d-SS, 	 

 E::<4A~3aa"	 
 d)Q   I;;=4IN$*"%Ss1vy1c!f&*SVgnnc=R*SDtDDMM! ! c!KELLN!KK Dy	BKJNxxHMMMMMM ''!ooO"))^^N*11*11'++
f	!6]1%F 	! 	f%i$v,67"2&E$tE{2)(3"F*2.E(4;6H  #$ "5	#.DUi/	 #$"6l#i/&."8}1$ '(	!""!&),^)<&1A5:: 2Q 6^+E#&u:1C#CL'
"U*f4	A &2E)E *3v;	 B #3v;	:F#**95#x	'::yM(3&&--f52<K/+It<)+ 1(.(+(2(.(-(1(-(-	%&!" !2(.(+(2(.
(-(1A(-(-	%&!" *-BvJ!(29(3)  %s9q='99(+IM(:-$*$&vJ0;VH$%$)$%$)$)	!" "!#JFE'($ !IE%(UN$%M$.}~$>M"L=>2 '	"!%!!%?,1,'&0%/F*!]2	*y>M9,/	NM&)3 ' *-^)<&S$q(#a1Cm1S*T E 1A5:: 2Q 6^+E#&u:1C#CL'
"U*f4	A,	9!Y."j0 &2E)E *3v;	 B$' (19( % "&k(+*7J(21I"&sIz!}"EC "9)Xi-@@M,Y7* /	4 @ * 1 1*Q- @ +8 $x/#}4&&--f52<K/)-$*$'$.$*QJ$)$-M$)$)	!" *-BvJ!*7J0:1Bz!}-,Z]; +8 *  %y0(1$s9q='99(+IM(: .$*$&vJ0;VH$%$)$%$)$)	!" "vq){  N D$[I$/$5$5$7 Hj
+E U"_xL5	$8"8nU"'X %8 t8OM
 H
s   '`1+`6c                   i }t               }| D ]k  }||   }t        |      dkD  }	|D ]Q  }
||
|v r|j                  |
       |
|v r||
= |j                  |
       4|	r|j                  |
       H|
|vsM|||
<   S m g }|j                         D ci c]  \  }}||
 }}}|r|j	                         \  }
}|
|g}||v r*|j                  |      }||= |j                  |       ||v r*|j                          |
|v r*|j                  |
      }
||
= |j                  |
       |
|v r*d}|D ]+  }|t        | |         z  }|dkD  s|j                  |        n |r|D ]  }|D ci c]  }|| |   
 }}|d   }||d      x}||<   |dd D ]  }||= | |= 
 t        |      }t        |||      f|z   | |<   |sZg }|D ]9  }|j                  |d      }|r|j                  |       )|j                  |       ; |||<    yc c}}w c c}w )zKSubroutine of fuse.

    Mutates dsk, dependencies, and fused_trees inplacer/   Nr   r-   F)r   r5   r   r=   r>   r?   r   r@   r   r4   SubgraphCallabler   )r   r    r"   r   rC   rD   rE   rF   rG   rH   rI   rJ   r&   rM   rK   rL   ntasksrU   subgraphoutkey
inkeys_setinkeyschain2subchains                           r)   r   r     sw   
 LIF#IMEETMe$,& 'e$"e$i'&,U#   F%1%7%7%9:%9TQAqD%9L:
$,,.v$!%%f-FV$LL  $ 	|# $$U+EU#LL |#
 CfSX&&Fze$	  * ',-u!As1vIu-q -9r,CC
\&)qrAQA 
 z"'&&ACfLF F&??1e4MM(+MM!$  #)K/ - ;. .s   H %Hc                      e Zd ZU dZded<   ded<   ded<   ded	<    ee      Z	 d	 	 	 	 	 	 	 ddZddZddZ	ddZ
ddZddZddZy
)r   aD  Create a callable object from a dask graph.

    Parameters
    ----------
    dsk : dict
        A dask graph
    outkey : Dask key
        The output key from the graph
    inkeys : list
        A list of keys to be used as arguments to the callable.
    name : str, optional
        The name to use for the function.
    r   r   r   r   ztuple[Key, ...]r   r1   nameNc                    || _         || _        t        |      | _        |dt	        ||| j                        z   }|| _        y )Nzsubgraph_callable-)r   r   r4   r   r   r   )r   r   r   r   r   s        r)   __init__zSubgraphCallable.__init__  s@     Fm<'(3*LLD	r+   c                    | j                   S rY   )r   r   s    r)   r   zSubgraphCallable.__repr__  s    yyr+   c                    t        |       t        |      u xra | j                  |j                  k(  xrF | j                  |j                  k(  xr+ t        | j                        t        |j                        k(  S rY   )r0   r   r   r   r   )r   others     r)   __eq__zSubgraphCallable.__eq__  sb    J$u+% 6		UZZ'6u||+6 DKK C$55		
r+   c           
     ,   t        |      t        | j                        k(  s,t        dt        | j                        t        |      fz        t        j                  | j
                  | j                  t        t        | j                  |                  S )NzExpected %d args, got %d)	r5   r   
ValueErrorr   r   r   r   r   zip)r   argss     r)   __call__zSubgraphCallable.__call__  sf    4yC,,73t{{;KSQUY:WWXXxx$++tCT4J/KLLr+   c                j    t         | j                  | j                  | j                  | j                  ffS rY   )r   r   r   r   r   r   s    r)   
__reduce__zSubgraphCallable.__reduce__  s&    $((DKKdii!PPPr+   c                l    t        | j                  t        | j                        | j                  f      S rY   )r   r   	frozensetr   r   r   s    r)   __hash__zSubgraphCallable.__hash__	  s%    T[[)DKK"8$))DEEr+   c                r    dt        | j                        | j                  | j                  | j                  fS )Nr   )r   r   r   r   r   r   s    r)   __dask_tokenize__z"SubgraphCallable.__dask_tokenize__  s0    DHH%KKKKII
 	
r+   rY   )r   r   r   r   r   zIterable[Key]r   z
str | Noner   )r   r   r   bool)r   r   r   r   )r   r4   )r   r   )r   object)r   r   r   __doc____annotations__r4   	__slots__r   r   r   r   r   r   r   r   r+   r)   r   r     su     
JK
Io&I RV"%/<DN
M
QF
r+   r   )NNT)NTN)NFN)x   ).
__future__r   r   r   collections.abcr   enumr   typingr   daskr   r   r	   dask._task_specr
   	dask.baser   r   	dask.corer   r   r   r   r   r   r   dask.tokenizedask.typingr   r   r*   r9   rW   rZ   rj   ry   r}   rp   r   r   r   r   r   r   r   r   r+   r)   <module>r     s    "   $   $ $ % /   4 "0fNb?F LP>B>"LNd  ==
 
 ~BD)N<
 <
r+   