
    bi~                        d dl mZ d dlZd dlZd dlmZ d dlmZmZ d dl	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fdZy)    )annotationsN)Enum)configutils)	GraphNode)flattenget_dependencies
ishashableistaskreverse_dictsubstoposortc                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
             L/home/cdr/jupyterlab/.venv/lib/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_renamerr2   G   s    
tAw-C
cz-1%1R%[9#99T!Wxx	#d1g,*z$q'!*c/J-1%1R%[9#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	   r.   r   r   mapreverseditemspopitempopr   reverser2   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_linearrP   V   s   ` 
4 5$%6D74=!KNOa+CDAAO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   )r0   s    r"   	_flat_setrS      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rR   )r
   r   ).0r   rF   r   r   s      r"   	<genexpr>zinline.<locals>.<genexpr>  s7      
11!s(LOFSTI 
s   .1)r   )r   nextitervaluesr   r6   r   rS   r	   r:   r   r   copy)r   r   inline_constantsr   r   rF   replaceorderkeysubsrN   rM   depreplacedsk2items   `  `          r"   inlinerc      s   2 
4\-@-@-B(C#DdK.:.@.@.BCda3q6	CT?D=@A+C33A 
		
 	
  -qAHCF-LL G #h,s++ 	*Cg~!#,c(sC)C	*  <<>DIIK Sd?|C00 53gdm45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rR   r   r   )rV   r!   r   s     r"   rW   z6inline_functions.<locals>.inlinable.<locals>.<genexpr>a  s#      K67Js1vy1K    TF)r   r   r   functions_ofissubsetany	TypeError)rN   task
dependentsr   fast_functionsoutputs     r"   	inlinablez#inline_functions.<locals>.inlinableY  sw    4+t6!3%..~>s K;Ec?K H     s   1A 	A'&A')r\   r   )r   r	   r   r6   rc   )
r   rp   ro   r\   r   r   rq   rF   r   rn   s
   ```      @r"   inline_functionsrr   3  s    6 
[F(N=@A+C33AAl+J  ))+9$!Q1aA9D9(8|
  	AA	J7 B& :s   B!B3Bc                P    t        | d      r| j                  } t        | d      r| S )Nfunc)hasattrrt   )rt   s    r"   unwrap_partialrv   t  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   r-   r)   r   r   rv   extend)rm   funcsr   sequence_typesr   s        r"   ri   ri   z  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 )Nr0      r'   )r.   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)r5   rX   r)   r*   r   r+   discardsortedr   r,   r-   r.   r   )
r   r   it	first_keyr/   r   
first_namer   r1   concatenated_names
    `        r"   default_fused_keys_renamerr     sL    
$BRI
y/C! cz__Y/
-/0#00j!uYHHUO%&788	#i.1,IaL#1N__Y/
-/0#0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)returnr*   )__name__
__module____qualname__tokenr   r   r$   r"   r   r     s    Er$   r   c                    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   }|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$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}/||" d }0||" d= |0D ]J  \  }1}1}1}2}3}4}5}6|2d	k(  r|.d	z  }.n|2|&kD  r|2}&|'|3z  }'|(|4z  }(|)|5z  })t        |6      |/kD  rt        |6      }/|*|6z  }*L t        |*      }+|)tA        |"d	z
  tC        d|+|/z
              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               }7|0D ]M  }8|8d   }9t=        |-|9|8d	         }-||9= |7 ||9      z  }7 ||9       |s1 ||9d       |%j;                  |8d          O | |z  } | |7z  } |r|%j                  |       |%||<   |r |||-|%|&d	z   |'|(d	z   |)|!f       ne|-||<   ni|0D ]  }8|8d	   ||8d   <    ||8d           |r?|'|kD  r|}'|)t?        |d	z
        kD  rt?        |d	z
        }) ||||   |r|gndd	|'d	|)|!f       nn
||   d   }|r|rC|j                         D ]0  \  }:}; ||;      }<|<|<|vs||:   ||<<   |<||:<   |
|:   |
|<<   |<h|
|:<   2 ||
fS c c}	w c c}}	w )a
  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``

    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.rename-keysTz)rename_keys must be a boolean or callabler   r   c              3  D   K   | ]  }t        |   t                y wrR   rg   )rV   rF   r   s     r"   rW   zfuse.<locals>.<genexpr>O  s     D!
3q695Drh   c              3  J   K   | ]  }t        t        |            d k7    yw)r(   N)r.   r   )rV   rF   s     r"   rW   zfuse.<locals>.<genexpr>S  s     G1c#a&kQ.Gs   !#r   r&   c              3  D   K   | ]  }t        |   t                y wrR   rg   )rV   	child_keyr   s     r"   rW   zfuse.<locals>.<genexpr>%  s$      ($- !+3y>9 E(rh      )"r   getr   r   r   r   _defaultmathlogr   callablerl   r	   r6   r   r.   r   r)   r-   numbersNumberr*   rk   r   allrZ   r[   r8   r;   rx   r   intminmax)=r   r   r   	ave_width	max_width
max_heightmax_depth_new_edgesr<   rG   r   r@   rF   rdepsvals	reduciblerH   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_popr?   rB   childrendeps_parentedgesnum_childrenr   
child_task
child_keysheightwidth	num_nodesfudgechildren_edgesnum_children_edgesno_new_edgesrM   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     s/
   D zz,-6L  
4 5$%6D74=! HJJ<=	(((XZZ >?
)))h&$jj)PQ"(222"'#oHJJ<=	((()dhhy1}&===	JL  hjj!@A(***d0		k"CDD!T)KCFGa#CD99G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!	 #GGG 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 '4 	"!%!!%?,1,'&0%/F*!]2	*y>M9,/	NM&)3'4* *-^)<&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(+*7 AJ(21I"&sIz!}"EC "9)Xi-@@M,Y7* /	4 @ * 1 1*Q- @A $x/#}4&&--f52<K/)-$*$'$.$*QJ$)$-M$)$)	!" *-BvJ!*7 <J0:1Bz!}-,Z];< *  %y0(1$s9q='99(+IM(: .$*$&vJ0;VH$%$)$%$)$)	!" "vq){  N $/$5$5$7 	) Hj
+E U"_xL5	$8"8nU"'X	) t8OC
 H
s   <_3(+_8)NNT)NTN)NFN)x   ) 
__future__r   r   r   enumr   daskr   r   dask._task_specr   	dask.corer   r	   r
   r   r   r   r   r#   r2   rP   rS   rc   rr   rv   ri   r   r   r   r   r   r   r$   r"   <module>r      s    "     %  0fNb?F LP>B>"LNd  ==
 
 nr$   