
    mi               
       T   d Z ddlm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 ddlZddlmZ ddlZd	d
lmZ d	dlmZmZ  G d de      Z	 ddedej4                  e   dedej8                  e   fdZe G d d             Z G d d      Z ejB                  e gdf   Z" G d d      Z#y)a  
Classes used to define a grid search.

`Launcher`: a launcher is passed to each grid search explore function,
and can be called repeatidly to schedule XPs.

`Explorer`: defines some metadata, in particular the metrics to display
with the `dora grid` command.
    )OrderedDict)deepcopy)ProcessPoolExecutorFuture)contextmanager)	dataclassfieldN)_Node   )SlurmConfig)ShepherdSheepc                       e Zd Zy)ProcessExceptionN)__name__
__module____qualname__     F/var/www/stems/demucs_env/lib/python3.12/site-packages/dora/explore.pyr   r      s    r   r   shepherdargvslurmjob_array_indexc                 v    	 | j                  |      ||fS # t        $ r}t        t        |            d }~ww xY wN)get_sheep_from_argv	Exceptionr   repr)r   r   r   r   excs        r   _processr!   "   s>    *,,T2E?KK *tCy))*s    	838c            
          e Zd ZU dZ ee      Zej                  e	e
f   ed<    ee      Zej                  e	ef   ed<    ee      Zej"                  ej"                  e	      ed<    ee      Zej"                  e   ed<   dZej*                  d   ed	<   d
 Z	 ddedej"                  e	   dedej*                  e   fdZ	 dde
dedej*                  e   fdZy)Herdz7Represents a herd of sheeps ready to be scheduled.
    )default_factorysheepsslurm_configs
job_arrays	_pendingsNLauncher_job_array_launcherc                     | j                   rP| j                   j                  d      }|j                         \  }}}| j                  |||       | j                   rOyy)z@Complete all pending sheep evaluations and add them to the herd.r   N)r(   popresult
_add_sheep)selffuturesheepr   r   s        r   completezHerd.complete7   sH    nn^^''*F,2MMO)E5/OOE5/: nnr   r   r   r   poolc           	      0   | j                   | j                  j                  g        t        | j                        dz
  }|#| j	                  |j                  |      ||       y | j                  j                  |j                  t        ||||             y )Nr   )	r*   r'   appendlenr.   r   r(   submitr!   )r/   r   r   r   r3   r   s         r   	add_sheepzHerd.add_sheep>   sv    ##+OO""2&doo.2<OOH88>WNN!!$++h$"_`r   r1   r   c                 @   |j                   j                  | j                  v ry || j                  |j                   j                  <   || j                  |j                   j                  <   |3| j                  |   j                  |j                   j                         y y r   )xpsigr%   r&   r'   r5   )r/   r1   r   r   s       r   r.   zHerd._add_sheepH   sq    88<<4;;&$)EHHLL!+0588<<(&OOO,33EHHLLA 'r   r   )r   r   r   __doc__r	   r   r%   tpDictstrr   __annotations__dictr&   r   listr'   Listr(   r   r*   Optionalr2   r   r   r8   intr.   r   r   r   r#   r#   *   s    "'"DFBGGCJD/4T/JM2773+,J(-d(CJ%C "'t!<Irwwv<37Z07; <@a( a"''#, a{ a$78a 8<B Bk B$&KK$4Br   r#   c                       e Zd ZdZg dfdedededej                  e	   dej                  e   f
dZd	 Zd
 Zd Zd Zd Zd Zed        Zy)r)   a9  
    A launcher is passed to the explore function and can be called repeatidly
    to schedule experiments.

    For instance:

        launcher(epochs=40)
        launcher(bs=64)

    A call to `launcher()` will schedule a new experiments, and all arguments
    have the same effect as in `Launcher.bind()`.
    Nr   r   herdr   r3   c                     || _         | j                   j                  | _        || _        t	        |      | _        t        |      | _        || _        y r   )		_shepherdmain_main_herdr   _slurmrB   _argv_pool)r/   r   r   rG   r   r3   s         r   __init__zLauncher.__init__`   s>    !^^((

uo$Z

r   c                     t        | j                  | j                  | j                  | j                  | j
                        S r   )r)   rI   rM   rL   rN   rO   r/   s    r   _copyzLauncher._copyi   s)    TZZTZZXXr   c                 F    | j                         } |j                  |i |S )a  
        Returns a new `Launcher` with different default XP parameters when scheduling experiments.

        Each entry in `*args` can be itself a list of dict or strings,
        or a string or a dict.

        Any string arg is considered directly as something to append to the list
        of *argv*, i.e. the command line arguments passed to the training scripts.

        A dictionary will be converted to a list of `argv`, with the specific syntax
        defined by the `main` function. For an argparse based script, a key
        value pair will be converted to `--key=value`, with some special rules
        (if the value is True, then it is converted to just `--key`).

        A list containing strings or dicts will be the concatenation
        of the argv obtained from each of its entries.

        For instance

            sub_launcher = launcher.bind(["--some_flag=5"], other_flag="test")
        )rS   bind_)r/   argskwargsnews       r   bindzLauncher.bindl   s%    , jjlsyy$)&))r   c                     |D ]0  }| xj                   | j                  j                  |      z  c_         2 | xj                   | j                  j                  |      z  c_         | S )z8
        In-place version of `Launcher.bind()`.
        )rN   rK   value_to_argv)r/   rV   rW   args       r   rU   zLauncher.bind_   sR      	8CJJ$**22377J	8

djj..v66
r   c                 F    | j                         } |j                  di |S )z
        Return a new `Launcher` with different default Slurm parameters.

        For instance

            sub_launcher = launcher.slurm(cpus_per_task=20)

        r   )rS   slurm_)r/   rW   rX   s      r   r   zLauncher.slurm   s#     jjlszz#F##r   c                     |j                         D ]@  \  }}t        | j                  |      st        d|       t	        | j                  ||       B | S )z9
        In-place version of `Launcher.slurm()`.
        zInvalid Slurm config )itemshasattrrM   AttributeErrorsetattr)r/   rW   keyvalues       r   r^   zLauncher.slurm_   sU     !,,. 	-JC4;;,$'<SE%BCCDKKe,	- r   c                 $    | j                   |i |}| j                  j                  }| |j                  |j                  k(  sJ d       | j                  j	                  | j
                  |j                  |j                  | j                         y)z
        Schedule an XP with the current default training hyper-parameters
        and Slurm config. You can also provide extra overrides like in `bind()`.
        Nz,cannot change slurm config inside job array.)rY   rL   r*   rM   r8   rI   rN   rO   )r/   rV   rW   launcherarray_launchers        r   __call__zLauncher.__call__   sx    
 499d-f-77%!((HOO; ?>?;

T^^X^^X__djjYr   c              #   &  K   | j                   j                  J d       | j                         | j                   _        | j                   j                  j	                  g        	 d d| j                   _        y# d| j                   _        w xY ww)zContext manager to indicate that you wish to launch all the included
        XPs using a single job array with the current Slurm parameters.
        NzCannot stack job arrays)rL   r*   rS   r'   r5   rR   s    r   	job_arrayzLauncher.job_array   sn     
 zz--5P7PP5)-

&

$$R(	2-1DJJ*TDJJ*s   A"B%A; )B;BB)r   r   r   r<   r   r   r#   r=   rC   r?   rD   r   rP   rS   rY   rU   r   r^   ri   r   rk   r   r   r   r)   r)   R   s     ')SW + T wws|02<O0PY*2$
Z 
2 
2r   r)   c                       e Zd ZdefdZdefdZdej                  e	   fdZ
dej                  e	   fdZd Zd	ed
ej                  e   defdZd
ej                  e   defdZy)Explorerexplorec                     || _         y r   rn   )r/   rn   s     r   rP   zExplorer.__init__   s	    r   rg   c                 &    | j                  |       y r   rp   )r/   rg   s     r   ri   zExplorer.__call__   s    Xr   returnc                     g S )zKReturn the metrics that should be displayed in the tracking table.
        r   rR   s    r   get_grid_metricszExplorer.get_grid_metrics   s	     	r   c                     t        j                  dd      t        j                  d      t        j                  d      t        j                  dd      t        j                  dd      gS )zIReturns the list of Meta information to display for each XP/job.
        index>)alignnamestater;   sid)ttleafrR   s    r   get_grid_metazExplorer.get_grid_meta   sO     GGG3'GGFOGGGGGE%GGE%
 	
r   c                 
    ddgS )N0z38;5;245r   rR   s    r   
get_colorszExplorer.get_colors   s    Z  r   r1   historyc                     t               )a   Process a sheep to return a dict (with possibly nested dict inside)
        matching the schema given by `get_grid_metrics`.
        This gives more possiblities than `process_history`, which is kept for compatibility,
        as one has access to the XP config here.
        If this is implemented, it will always be called, otherwise, `process_history` is used.

        One should use the history provided here, rather than the one in `sheep.xp.link.history`,
        as it has possibly been shortened to align multiple experiments.
        )NotImplementedError)r/   r1   r   s      r   process_sheepzExplorer.process_sheep   s     "##r   c                 P    dt        |      i}|D ]  }|j                  |        |S )zProcess history to return a dict (with possibly nested dict inside)
        matching the schema given by `get_grid_metrics`.
        epoch)r6   update)r/   r   outmetricss       r   process_historyzExplorer.process_history   s6    
 S\
  	 GJJw	 
r   N)r   r   r   ExplorerP   r)   ri   r=   rC   r
   rt   r~   r   r   rA   r   r   r   r   r   rm   rm      s      "''%. 
	
rwwu~ 	
!
$5 
$2774= 
$T 
$	rwwt} 	 	r   rm   r   )$r<   collectionsr   copyr   concurrent.futuresr   r   
contextlibr   dataclassesr   r	   typingr=   treetable.tabler
   	treetabler|   confr   shepr   r   RuntimeErrorr   rC   r?   rD   rE   r!   r#   r)   Callabler   rm   r   r   r   <module>r      s    $  : % (  !   !	| 	
 26*x *rwws| *K * kk#.* $B $B $BNj2 j2Z ++xj$&
'/ /r   