o
    2wi                   
   @   s   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 deZ	ddedeje dedeje fddZeG dd dZG dd dZ ej!e gdf Z"G dd dZ#dS )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                   @   s   e Zd ZdS )ProcessExceptionN)__name__
__module____qualname__ r   r   I/home/ubuntu/sommelier/.venv/lib/python3.10/site-packages/dora/explore.pyr      s    r   shepherdargvslurmjob_array_indexc              
   C   s8   z	|  |||fW S  ty } ztt|d }~ww N)get_sheep_from_argv	Exceptionr   repr)r   r   r   r   excr   r   r   _process"   s   r   c                
   @   s   e Zd ZU dZeedZeje	e
f ed< eedZeje	ef ed< eedZejeje	  ed< eedZeje ed< dZejd ed	< d
d Z	ddedeje	 dedeje fddZ	dde
dedeje fddZdS )Herdz7Represents a herd of sheeps ready to be scheduled.
    )default_factorysheepsslurm_configs
job_arrays	_pendingsNLauncher_job_array_launcherc                 C   s<   | j r| j d}| \}}}| ||| | j sdS dS )z@Complete all pending sheep evaluations and add them to the herd.r   N)r#   popresult
_add_sheep)selffuturesheepr   r   r   r   r   complete7   s
   zHerd.completer   r   r   poolc              	   C   sb   | j d u r| jg  t| jd }|d u r"| |||| d S | j|t|||| d S )Nr
   )	r%   r"   appendlenr(   r   r#   submitr   )r)   r   r   r   r-   r   r   r   r   	add_sheep>   s   
zHerd.add_sheepr+   r   c                 C   sR   |j j| jv r	d S || j|j j< || j|j j< |d ur'| j| |j j d S d S r   )xpsigr    r!   r"   r.   )r)   r+   r   r   r   r   r   r(   H   s   zHerd._add_sheepr   )r   r   r   __doc__r   r   r    tpDictstrr   __annotations__dictr!   r   listr"   Listr#   r   r%   Optionalr,   r   r   r1   intr(   r   r   r   r   r   *   s    
 
r   c                   @   s|   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d	Zd
d Zdd Zdd Zdd Zdd Zdd Zedd ZdS )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   r-   c                 C   s4   || _ | j j| _|| _t|| _t|| _|| _d S r   )		_shepherdmain_main_herdr   _slurmr:   _argv_pool)r)   r   r   r>   r   r-   r   r   r   __init__`   s   



zLauncher.__init__c                 C   s   t | j| j| j| j| jS r   )r$   r?   rC   rB   rD   rE   r)   r   r   r   _copyi   s   zLauncher._copyc                 O   s   |   }|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")
        )rH   bind_)r)   argskwargsnewr   r   r   bindl   s   zLauncher.bindc                 O   s:   |D ]}|  j | j|7  _ q|  j | j|7  _ | S )z8
        In-place version of `Launcher.bind()`.
        )rD   rA   value_to_argv)r)   rJ   rK   argr   r   r   rI      s   zLauncher.bind_c                 K   s   |   }|jdi |S )z
        Return a new `Launcher` with different default Slurm parameters.

        For instance

            sub_launcher = launcher.slurm(cpus_per_task=20)

        Nr   )rH   slurm_)r)   rK   rL   r   r   r   r      s   
zLauncher.slurmc                 K   s>   |  D ]\}}t| j|std| t| j|| q| S )z9
        In-place version of `Launcher.slurm()`.
        zInvalid Slurm config )itemshasattrrC   AttributeErrorsetattr)r)   rK   keyvaluer   r   r   rP      s
   zLauncher.slurm_c                 O   sR   | j |i |}| jj}|dur|j|jksJ d| j| j|j|j| j dS )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.)rM   rB   r%   rC   r1   r?   rD   rE   )r)   rJ   rK   launcherarray_launcherr   r   r   __call__   s   zLauncher.__call__c                 c   sP    | j jdu sJ d|  | j _| j jg  z
dV  W d| j _dS d| j _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)rB   r%   rH   r"   r.   rG   r   r   r   	job_array   s   zLauncher.job_array)r   r   r   r4   r   r   r   r5   r;   r7   r<   r   rF   rH   rM   rI   r   rP   rY   r   rZ   r   r   r   r   r$   R   s     
		
r$   c                   @   s   e Zd ZdefddZdefddZdeje	 fdd	Z
deje	 fd
dZdd Zdedeje defddZdeje defddZdS )Explorerexplorec                 C   s
   || _ d S r   r\   )r)   r\   r   r   r   rF      s   
zExplorer.__init__rW   c                 C   s   |  | d S r   r]   )r)   rW   r   r   r   rY      s   zExplorer.__call__returnc                 C   s   g S )zKReturn the metrics that should be displayed in the tracking table.
        r   rG   r   r   r   get_grid_metrics   s   zExplorer.get_grid_metricsc                 C   s8   t jdddt dt dt jdddt jdddgS )zIReturns the list of Meta information to display for each XP/job.
        index>)alignnamestater3   sid)ttleafrG   r   r   r   get_grid_meta   s   zExplorer.get_grid_metac                 C   s   ddgS )N0z38;5;245r   rG   r   r   r   
get_colors   s   zExplorer.get_colorsr+   historyc                 C   s   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)   r+   rk   r   r   r   process_sheep   s   
zExplorer.process_sheepc                 C   s$   dt |i}|D ]}|| q|S )zProcess history to return a dict (with possibly nested dict inside)
        matching the schema given by `get_grid_metrics`.
        epoch)r/   update)r)   rk   outmetricsr   r   r   process_history   s
   zExplorer.process_historyN)r   r   r   ExplorerF   r$   rY   r5   r;   r	   r_   rh   rj   r   r9   rm   rr   r   r   r   r   r[      s    r[   r   )$r4   collectionsr   copyr   concurrent.futuresr   r   
contextlibr   dataclassesr   r   typingr5   treetable.tabler	   	treetablerf   confr   shepr   r   RuntimeErrorr   r;   r7   r<   r=   r   r   r$   Callablers   r[   r   r   r   r   <module>   s*   	
'm