
    Cd6                       d dl mZ d dlZd dlZd dlZd dlmZ d dlmZm	Z	m
Z
 d dlmZmZmZmZmZ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j        ZddeeeeeefdZd Z  G d d          Z!dS )    )annotationsN)Enum)configcoreutils)flattenget_dependencies
ishashableistaskreverse_dictsubstoposortc                   t          |t          t          f          s|g}t                      }t                      }i }t          t          t	          |                              }|r`g }|D ]W}t          | |d          }| |         ||<   |||<   |D ]0}	|	|vr*|                    |	           |                    |	           1X|}|`||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.11/site-packages/dask/optimization.pycullr#      s    6 dT3K(( v55D66L
CGDMM""##D
  	' 	'A-c1dCCCNVCF,LO# ' 'D==HHQKKKOOA&&&'
        c                   t          | d                   }|t          u rEd | ddd         D             }|                    | d                    d                    |          S |t          u rt          | d                   dk    r~t          | d         d         t                    r]d | ddd         D             }|                    | d         d                    d                    |          f| d         dd         z   S dS )zCreate new keys for fused tasksr   c                6    g | ]}t          j        |          S  r   	key_split.0xs     r"   
<listcomp>z5default_fused_linear_keys_renamer.<locals>.<listcomp>K   "    999##999r$   N-c                6    g | ]}t          j        |          S r'   r(   r*   s     r"   r-   z5default_fused_linear_keys_renamer.<locals>.<listcomp>O   r.   r$      )typestrr   jointuplelenr   )r   typnamess      r"   !default_fused_linear_keys_renamerr:   G   s    
tAw--C
czz99T%1R%[999T!Wxx	#d1g,,**z$q'!*c/J/J*99T%1R%[999T!WQZ   !DGABBK//tr$   Tc                    |It          |t                    s4t          |t                    s|g}t          t          |                    }| fd D             }i }t                      } D ]|}||         }t	          |          dk    }|D ]\}	||	|v r|                    |	           |	|v r||	= |                    |	           ;|r|                    |	           S|	|vr|||	<   ]}g }
t          t          t          |	                                                    }|r|
                                \  }	}|	|g}||v r1|                    |          }||= |                    |           ||v 1|                                 |	|v r1|                    |	          }	||	= |                    |	           |	|v 1|
                    |           |d |	                                D             }|du rt          }n	|du rd}n|}i }t                      }t                      }d}|
D ]}| ||          }|duo| vo||v}|                                }	 |	         }|r|                                }||                             |                    |	                     ||                             |	           t#           |         |	|          }|                    |	           |}	||                    |	           |r2|||<   |||	<   ||	         ||<   |h||	<   |                    |	           |||	<    	                                D ]\  }}||vr|||<   |r~|	                                D ]Y\  }}||z  D ]N}||         }|                    |           |                    |           t#          ||         ||          ||<   OZ|||z
  D ]}||= ||= 	||fS )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.
    Nc                6    i | ]}|t          |d           S Tr   r	   r+   r   r   s     r"   
<dictcomp>zfuse_linear.<locals>.<dictcomp>   s+    OOOa+CDAAAOOOr$   r2   c                4    i | ]\  }}|t          |          S r'   r   r+   r   vs      r"   r@   zfuse_linear.<locals>.<dictcomp>   s$    ???$!QAs1vv???r$   TF)r   r   r   r   r7   r   r   mapreverseditemspopitempopr   reverser:   updateremover   )r   r   r   rename_keyschild2parent	unfusibleparentdepshas_many_childrenchildchainsparent2childchainkey_renamerrvfusedaliases
is_renamednew_keyvalkeyold_keys   `                     r"   fuse_linearr`   V   s   ` 
4 5 5$%% 	6D74==!!OOOO3OOO LI - -F#IIM 		- 		-EETMMe$$$$,&& 'e$$$$" -e$$$$i''&,U#		- FHl&8&8&:&:;;<<L
 $,,..v$$!%%f--FV$LL    $$ 	|## $$U++EU#LL |## 	e   @?,*<*<*>*>???Ld7			! 
BEEEeeGJ  "!k%((Gt#Ps(:Pwb?P  		%j 	YY[[F ''(8(8(?(?@@@ ''...s6{E3//CIIeE  	 			% 	BwKBuI$0$7L!#*)LKKBuIIIIKK  SeBsG 
&%++-- 	: 	:IC'> : :W+G$$$!!!r#w993	:
 ~ & &sG %%|r$   c                    | t                      S t          | t                     r| S t          | t          t           f          s| g} t          |           S N)r   r   r   )r,   s    r"   	_flat_setrc      sO    yuu	As		 D#;'' Cq66Mr$   c                    r_t          t          t                                                              t                    rd                                 D             t          |          } fd D             |r4|                     fd                                 D                        t           fd|D                       }i }|D ]C} |         }||         z  D ](}||v r	||         }	n |         }	t          |||	          })|||<   D|
                                }
                                 D ]3\  }}||
vr*||         z  D ]}t          ||||                   }||
|<   4|
S )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                4    i | ]\  }}|t          |          S r'   rB   rC   s      r"   r@   zinline.<locals>.<dictcomp>  s$    CCCda3q66CCCr$   Nc                2    i | ]}|t          |          S r'   r>   r?   s     r"   r@   zinline.<locals>.<dictcomp>  &    AAA+C33AAAr$   c              3  v   K   | ]3\  }}t          |          r|v s|          t          |          /|V  4d S rb   )r
   r   )r+   r   rD   r   r   s      r"   	<genexpr>zinline.<locals>.<genexpr>  s\       
 
11
 #$s((LO(FSTII( "*(((
 
r$   c                *    i | ]}|v ||         S r'   r'   r?   s     r"   r@   zinline.<locals>.<dictcomp>  s$    ---qAHHCFHHHr$   )r   )r   nextitervaluesr   rG   rc   rK   r   r   copy)r   r   inline_constantsr   replaceorderkeysubsr^   r]   depreplacedsk2items   `  `        r"   inlinerv      s   2  D
4\-@-@-B-B(C(C#D#DdKK DCCl.@.@.B.BCCCT??DAAAASAAA 
 
 
 
 
 
		
 
 
 	
 	
 	
 ----D---L  L G  #h,s++ 	* 	*Cg~~!#,c(sC))CC <<>>DIIKK  Sd??|C00 5 53gdm44DIKr$   Fc                    s S t                    t                    | fd D             }t          |          fdfd                                 D             }|rt           |||           |D ]} |=  S )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}
    Nc                2    i | ]}|t          |          S r'   r>   r?   s     r"   r@   z$inline_functions.<locals>.<dictcomp>V  rg   r$   c                l    	 t          |                                         S # t          $ r Y dS w xY w)NF)functions_ofissubset	TypeError)rD   fast_functionss    r"   	inlinablez#inline_functions.<locals>.inlinableY  sD    	??++N;;; 	 	 	55	s   !% 
33c                f    g | ]-\  }}t          |          r|         r|v  |          +|.S r'   )r   )r+   r   rD   
dependentsr~   outputs      r"   r-   z$inline_functions.<locals>.<listcomp>_  sX       Aq!99 $A ,-F??yy||? 	
+:??r$   )ro   r   )r   r   rG   rv   )	r   r   r}   ro   r   r   r   r   r~   s	   ```    @@r"   inline_functionsr   3  s    6  
[[F((NAAAASAAAl++J         IIKK  D  (8|
 
 
  	 	AAJr$   c                T    t          | d          r| j        } t          | d          | S )Nfunc)hasattrr   )r   s    r"   unwrap_partialr   n  s4    
$

 y $

 Kr$   c                T   t                      }| g}t          t          h}|rg }|D ]}} t          |           |v rjt	          |           rF|                    t          | d                              |                    | dd                    h|                    |            ~|}||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   r2   N)r   r   r6   r3   r   r   r   extend)taskfuncsr   sequence_typesr   s        r"   rz   rz   t  s     EEE6DE]N
 	 	* 	*DDzz^++$<< *IInT!W55666OODH----OOD)))  	 Lr$   x   c                
   t          |           }t          |          }t          |          }rdz  fd}|t          u ryt	          j        |          }d |D             }|                    |           t          |          }|                    |           d	                    |          } ||          S |t          u rt          |          dk    rt          |d         t                    rt	          j        |          }d |D             }|                    |           t          |          }|                    |d                    d	                    |          } ||          f|dd         z   S dS dS dS )	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          |           k    r(t          |           dd d         }| d           d| } | S )Nr,      r0   )r7   hash)key_name	name_hashmax_fused_key_lengths     r"   _enforce_max_key_limitz:default_fused_keys_renamer.<locals>._enforce_max_key_limit  s[     	HCMM4H$H$H>>--bqb1I"#8$8#89GGIGGHr$   c                6    h | ]}t          j        |          S r'   r(   r+   r   s     r"   	<setcomp>z-default_fused_keys_renamer.<locals>.<setcomp>  "    000##000r$   r0   r   c                6    h | ]}t          j        |          S r'   r(   r   s     r"   r   z-default_fused_keys_renamer.<locals>.<setcomp>  r   r$   r2   N)rF   rk   r3   r4   r   r)   discardsortedr   r5   r6   r7   r   )	r   r   it	first_keyr8   r   
first_namer9   concatenated_names	    `       r"   default_fused_keys_renamerr     s    
$BRI
y//C "!     czz_Y//
00R000j!!!uYHHUOO%%&7888	#i..1,,IaL#1N1N,_Y//
00R000j!!!uYq\"""HHUOO&&'899;imKK 
,,,,r$   c                      e Zd ZdZddZdS )Defaultr   returnr4   c                    dS )Nz	<default>r'   selfs    r"   __repr__zDefault.__repr__  s    {r$   N)r   r4   )__name__
__module____qualname__tokenr   r'   r$   r"   r   r     s-        E     r$   r   c	                    t          j        d          du r |fS |It          |t                    s4t          |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}| fd D             }
nt          |          }
i }|
                                D ]B\  }}|D ](}||vr|g||<   ||                             |           )t          |          |
|<   Cd |                                D             }|r||z  }                                 D ]Q\  }}t          |          t           ur6t          |t"          j        t&          f          s|                    |           R|s1|r+t+          d |                                D                       r |
fS                                  }i }g }g }|
j        }|j        }|j        }|j        }|j        }|j        }|j        }|j        }|j        }|j        }|r |            } ||           ||v r||         d         }||v  ||            |||
|         z             	 |d         }||k    rb||
|         z  } | r" ||            |}|d         }||
|         z  } | " |              ||||         |r|gndd	d	d	d|
|         |z
  f           n |             |
|         }!|!|z
  }"|!|"z
  } t9          |           }#|#d	k    rt |            \  }$}%}&}'}(})}*}+t9          |+          },|*|,d	z
  cxk    rdk    rn n|,d	z
  }*|"|+z  }"t9          |"          |,k    }-|-s|*d	z  }*|)|*z   |'z  |k    r|-s|'|k     rt;           |         |$|%          }.|!                    |$           |! ||$          z  }!||$=  ||$           |r&|&                    |           |&||<    ||$d           |r2|-r |||.|&|'|(|)|*|"f           n |||.|&|'d	z   |(|)d	z   |*|"f           n|.||<   n|%||$<    ||$           |rH|*t=          |d	z
            k    rt=          |d	z
            }* ||||         |r|gndd	|(d	|*|"f           nZnhg }&d	}'d}(d}/d})d}*t                      }+d}0||# d         }1||# d= |1D ]U\  }2}2}2}3}4}5}6}7|3d	k    r|/d	z  }/n|3|'k    r|3}'|(|4z  }(|)|5z  })|*|6z  }*t9          |7          |0k    rt9          |7          }0|+|7z  }+Vt9          |+          },|*t?          |#d	z
  tA          d|,|0z
                      z  }*|*|,d	z
  cxk    rdk    rn n|,d	z
  }*|"|+z  }"t9          |"          |,k    }-|-s|*d	z  }*|)|*z   |'z  |k    r|/|k    r|(|k    r|'|k    r|-s|'|k     rǉ |         }.t                      }8|1D ]f}9|9d         }:t;          |.|:|9d	                   }.||:= |8 ||:          z  }8 ||:           |r' ||:d           |&                    |9d                    g|!| z  }!|!|8z  }!|r|&                    |           |&||<   |r |||.|&|'d	z   |(|)d	z   |*|"f           n|.||<   n|1D ]$}9|9d	         ||9d         <    ||9d                    %|rO|(|k    r|}(|*t=          |d	z
            k    rt=          |d	z
            }* ||||         |r|gndd	|(d	|*|"f           nn||         d         }~||rtC          |||
||           |	rL|                                D ]7\  };}< |	|<          }=|=%|=|vr!||;         ||=<   |=||;<   |
|;         |
|=<   |=h|
|;<   8||
fS )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-widthr2   zoptimization.fuse.subgraphszoptimization.fuse.rename-keysTz)rename_keys must be a boolean or callablec                6    i | ]}|t          |d           S r=   r>   r?   s     r"   r@   zfuse.<locals>.<dictcomp><  s+    GGGa#CD999GGGr$   c                >    h | ]\  }}t          |          d k    |S )r2   )r7   )r+   r   valss      r"   r   zfuse.<locals>.<setcomp>I  s'    BBBwq$3t99>>>>>r$   c              3  V   K   | ]$}t          t          |                    d k    V  %dS )r2   N)r7   r   )r+   rD   s     r"   ri   zfuse.<locals>.<genexpr>R  s3      !K!Kq#c!ff++"2!K!K!K!K!K!Kr$   r   r/      )"r   getr   r   r   r   _defaultmathlogr   callabler|   r   rG   r   r3   r6   numbersNumberr4   r   allrm   rn   rI   r   rL   r   r7   r   intminmax_inplace_fuse_subgraphs)>r   r   r   	ave_width	max_width
max_heightmax_depth_new_edgesrM   fuse_subgraphsrW   rQ   rdepsr   r   rD   	reduciblerX   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_poprP   rS   childrendeps_parentedgesnum_children	child_key
child_task
child_keysheightwidth	num_nodesfudgechildren_edgesnum_children_edgesno_new_edgesr]   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     sz   P z,--66L  
4 5 5$%% 	6D74==!! HJ<==	((((XZ >??
))))h&&$j)PQQ"(2222"'#oHJ<==	(((()dhy1}&=&===	!!$ABBX---- !J !L  hj!@AA(****d0			k"" "CDDD!T)KGGGG3GGGL!!E::<<  4 	# 	#A~~3aa""""d))QBB%++--BBBI T			 ! !177%
1w~s6K(L(La    !!K!KELLNN!K!K!KKK
 Dy	BKJNxHMMMM '!oO")^N*1*1'+
 v*f	!!6]1%F 	!! 	f%%%i$v,6777n	*"2&E$tE{2 7))(333"F*2.E(4;6H  7 #"$$$ "!5	#.8DUi/	    #"$$$"6l#i/&."8}}1$$ '((	!""!&),^)<)<&1A5::::::::: 2Q 6^+E#&u::1C#CL' #
"U*f4	AA & B *02E)E)E #3v;	:FF#**9555#xx	':'::yM((333& =&--f5552<K/+OIt<<<) "+ " 1 1(.(+(2(.(-(1(-(-	%&!" !" !" !" !2 1(.(+(2(.
(-(1A(-(-	%&!" !" !" !" *-BvJ!(29((333) "  %s9q='9'999(+IM(:(:--$*$&vJ0;$EVHH$%$)$%$)$)	!"    "!#JFE'($ !IE%(UUN$%M$.}~~$>M"L=>>2 '4 4 	"!%!!%??,1,,'&00%/F*!]2	*y>>M99,/	NNM&)3),^)<)<&S$q(#a1Cm1S*T*T  E 1A5::::::::: 2Q 6^+E#&u::1C#CL' #
"U*f4	AA,	99!Y.."j00 & 1 *02E)E)E "&k(+*7 A AJ(21I"&sIz!}"E"EC "9)XXi-@-@@M,,Y777* A /	4 @ @ @ * 1 1*Q- @ @ @#x/#}4& =&--f5552<K/) "--$*$'$.$*QJ$)$-M$)$)	!"    *-BvJ!*7 < <J0:1Bz!}-,,Z];;;;) "  %y00(1$s9q='9'999(+IM(:(: .-$*$&vJ0;$EVHH$%$)$%$)$)	!"    "vq)]n	*  v*p  JD$[III )$/$5$5$7$7 	) 	) HjK
++E U"__xL5	$8"8nU"'Xt8Or$   c                    i }t                      } D ]|}||         }t          |          dk    }	|D ]\}
||
|v r|                    |
           |
|v r||
= |                    |
           ;|	r|                    |
           S|
|vr|||
<   ]}g }d |                                D             }|r|                                \  }
}|
|g}||v r1|                    |          }||= |                    |           ||v 1|                                 |
|v r1|                    |
          }
||
= |                    |
           |
|v 1d}|D ]7}|t           |                   z  }|dk    r|                    |            n8||D ]} fd|D             }|d         }||d                  x}||<   |dd         D ]}||=  |= 	t          |          }t          |||          f|z    |<   |rOg }|D ]E}|                    |d          }|r|                    |           0|                    |           F|||<   dS )zKSubroutine of fuse.

    Mutates dsk, dependencies, and fused_trees inplacer2   Nc                    i | ]\  }}||	S r'   r'   rC   s      r"   r@   z+_inplace_fuse_subgraphs.<locals>.<dictcomp>  s    :::TQAq:::r$   r   c                "    i | ]}||         S r'   r'   r?   s     r"   r@   z+_inplace_fuse_subgraphs.<locals>.<dictcomp>  s    ---!As1v---r$   r/   F)r   r7   r   rG   rH   rI   r   rJ   r   r6   SubgraphCallabler   )r   r   r   r   rM   rN   rO   rP   rQ   rR   rS   rT   rU   rV   ntasksr^   subgraphoutkey
inkeys_setr   inkeyschain2subchains   `                      r"   r   r   o  s&   
 LI - -F#IIM 		- 		-EETMMe$$$$,&& 'e$$$$" -e$$$$i''&,U#		- F::\%7%7%9%9:::L
 $,,..v$$!%%f--FV$LL    $$ 	|## $$U++EU#LL |##
  	 	CfSX&&&Fzze$$$ !  *  ) )----u---q -9r,CC
\&)qrr 	 	AQA z""'&&AACfLF  	)F % %&??1e44 %MM(++++MM!$$$$"(K/) )r$   c                  B    e Zd ZdZdZddZd Zd Zd Zd Z	d	 Z
d
 ZdS )r   aD  Create a callable object from a dask graph.

    Parameters
    ----------
    dsk : dict
        A dask graph
    outkey : hashable
        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   nameNc                n    || _         || _        || _        |dt          j                     }|| _        d S )Nzsubgraph_callable-)r   r   r   uuiduuid4r   )r   r   r   r   r   s        r"   __init__zSubgraphCallable.__init__  s:    <6
66D			r$   c                    | j         S rb   )r   r   s    r"   r   zSubgraphCallable.__repr__  s
    yr$   c                    t          |           t          |          u oI| j        |j        k    o9| j        |j        k    o)t          | j                  t          |j                  k    S rb   )r3   r   r   r   r   r   others     r"   __eq__zSubgraphCallable.__eq__  s`    JJ$u++% 6	UZ'6u|+6 DK  C$5$55		
r$   c                    | |k     S rb   r'   r  s     r"   __ne__zSubgraphCallable.__ne__  s    EM""r$   c           
     2   t          |          t          | j                  k    s3t          dt          | j                  t          |          fz            t          j        | j        | j        t          t          | j        |                              S )NzExpected %d args, got %d)	r7   r   
ValueErrorr   r   r   r   r   zip)r   argss     r"   __call__zSubgraphCallable.__call__  ss    4yyC,,,,73t{;K;KSQUYY:WWXXXx$+tCT4J4J/K/KLLLr$   c                D    t           | j        | j        | j        | j        ffS rb   )r   r   r   r   r   r   s    r"   
__reduce__zSubgraphCallable.__reduce__  s     48T[$+ty"QRRr$   c                x    t          t          | j        t          | j                  | j        f                    S rb   )r   r6   r   	frozensetr   r   r   s    r"   __hash__zSubgraphCallable.__hash__  s-    E4;	$+(>(>	JKKLLLr$   rb   )r   r   r   __doc__	__slots__r  r   r  r  r  r  r  r'   r$   r"   r   r     s          4I     
 
 
# # #M M M
S S SM M M M Mr$   r   )NNT)NTN)NFN)r   )"
__future__r   r   r   r   enumr   daskr   r   r   	dask.corer   r	   r
   r   r   r   r   r#   r:   r`   rc   rv   r   r   rz   r   r   r   r   r   r   r   r'   r$   r"   <module>r     s    " " " " " "          $ $ $ $ $ $ $ $ $ $                 0 0 0f  N N N Nb  ? ? ? ?F LP8 8 8 8v    >"L "L "L "LN    d    =
 
 h h h hVD) D) D)N0M 0M 0M 0M 0M 0M 0M 0M 0M 0Mr$   