o
    wiF`                     @  s   d Z ddlmZ ddlZddlZddlZddlZddlZddlm	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 dd	lmZ ed
ddZejjZdejej fddZG dd deZG dd dZd$ddZ dd Z!d%d"d#Z"dS )&a9  Sweep controller.

This module implements the sweep controller.

On error an exception is raised:
    ControllerError

Example:
    import wandb

    #
    # create a sweep controller
    #
    # There are three different ways sweeps can be created:
    # (1) create with sweep id from `wandb sweep` command
    sweep_id = 'xyzxyz2'
    tuner = wandb.controller(sweep_id)
    # (2) create with sweep config
    sweep_config = {}
    tuner = wandb.controller()
    tuner.configure(sweep_config)
    tuner.create()
    # (3) create by constructing programmatic sweep configuration
    tuner = wandb.controller()
    tuner.configure_search('random')
    tuner.configure_program('train-dummy.py')
    tuner.configure_parameter('param1', values=[1,2,3])
    tuner.configure_parameter('param2', values=[1,2,3])
    tuner.configure_controller(type="local")
    tuner.create()
    #
    # run the sweep controller
    #
    # There are three different ways sweeps can be executed:
    # (1) run to completion
    tuner.run()
    # (2) run in a simple loop
    while not tuner.done():
        tuner.step()
        tuner.print_status()
    # (3) run in a more complex loop
    while not tuner.done():
        params = tuner.search()
        tuner.schedule(params)
        runs = tuner.stopping()
        if runs:
            tuner.stop_runs(runs)
    )annotationsN)Callableenv)InternalApi)wandb_sweep)handle_sweep_config_violations0sweep_config_err_text_from_jsonschema_violations)
get_modulesweepsz^wandb[sweeps] is required to use the local controller. Please run `pip install wandb[sweeps]`.)required
   c                   s   d  fddt| D S )N c                 3  s    | ]}t  V  qd S N)randomchoice).0_chars J/home/ubuntu/.local/lib/python3.10/site-packages/wandb/wandb_controller.py	<genexpr>W   s    z _id_generator.<locals>.<genexpr>)joinrange)sizer   r   r   r   _id_generatorV   s   r   c                   @  s   e Zd ZdZdS )ControllerErrorzBase class for sweep errors.N)__name__
__module____qualname____doc__r   r   r   r   r   Z   s    r   c                   @  s  e Zd ZdZdiddZdjddZdkddZdlddZdd Zdd Z	dd Z
										dmddZdd Zdd ZednddZedod d!Zdpd#d$Zdqd&d'Zdqd(d)Zdqd*d+Zdqd,d-Zdpd.d/Zdrd2d3Zdsdtd7d8Z	4	9	4	4dudvd>d?ZdwdAdBZdpdCdDZdpdEdFZdGdH ZdpdIdJZdpdKdLZdxdMdNZ dydPdQZ!dydRdSZ"dzdUdVZ#dzdWdXZ$d{dZd[Z%d|d]d^Z&dpd_d`Z'dpdadbZ(dpdcddZ)dpdedfZ*dpdgdhZ+dS )}_WandbControlleraA  Sweep controller class.

    Internal datastructures on the sweep object to coordinate local controller with
    cloud controller.

    Data structures:
        controller: {
            schedule: [
                { id: SCHEDULE_ID
                  data: {param1: val1, param2: val2}},
            ]
            earlystop: [RUN_ID, ...]
        scheduler:
            scheduled: [
                { id: SCHEDULE_ID
                  runid: RUN_ID},
            ]

    `controller` is only updated by the client
    `scheduler` is only updated by the cloud backend

    Protocols:
        Scheduling a run:
        - client controller adds a schedule entry on the controller.schedule list
        - cloud backend notices the new entry and creates a run with the parameters
        - cloud backend adds a scheduled entry on the scheduler.scheduled list
        - client controller notices that the run has been scheduled and removes it from
          controller.schedule list

    Current implementation details:
        - Runs are only schedule if there are no other runs scheduled.

    Nc                 C  sx  d | _ i | _d | _d | _d | _d | _d | _d | _d | _d | _	d | _
d | _d | _d| _d| _d| _d| _d| _g | _g | _tj}|rHtj||d |rQtj||d t|d| _t|tr`|| _ nKt|ttjfrt|| _t ddgdd	gD ]\}}t!|| jv o| j| rt"| || j|  d
| j|< qw| j#dd| _ n|d u rd| _d S t$d| % }|d u rt$d|| _d S )NFr   r   r   )environmethodearly_terminate_custom_search_custom_stoppingcustomT)	from_dictUnhandled sweep controller typezCan not find sweep)&	_sweep_id_creater&   r'   _program_function
_sweep_obj_sweep_config_sweep_metric_sweep_runs_sweep_runs_map
_scheduler_controller_controller_prev_step_started_done_scheduling_defer_sweep_creation_logged_laststatus_log_actions
_log_debugosr#   r   
set_entityset_projectr   _api
isinstancestrdictr   SweepConfigzipcallablesetattrcreater   _sweep_object_read_from_backend)selfsweep_id_or_configentityprojectr#   
config_keycontroller_attr	sweep_objr   r   r   __init__   s`   


z_WandbController.__init__searchZstr | Callable[[dict | sweeps.SweepConfig, list[sweeps.SweepRun]], sweeps.SweepRun | None]c                 C  sD   |    t|tr|| jd< d S t|rd| jd< || _d S td)Nr$   r(   zUnhandled search type.)_configure_checkrA   rB   r,   rF   r&   r   )rJ   rR   r   r   r   configure_search   s   


z!_WandbController.configure_searchstoppingYstr | Callable[[dict | sweeps.SweepConfig, list[sweeps.SweepRun]], list[sweeps.SweepRun]]c                 K  s   |    t|tr)| jdi  || jd d< | D ]\}}|| jd |< qd S t|rB||| _| jdi  d| jd d< d S td)Nr%   typer(   zUnhandled stopping type.)	rT   rA   rB   r,   
setdefaultitemsrF   r'   r   )rJ   rV   kwargskvr   r   r   configure_stopping   s   

z#_WandbController.configure_stoppingc                 C  s>   |    | jdi  || jd d< |r|| jd d< d S d S )NmetricnamegoalrT   r,   rY   )rJ   r_   ra   r   r   r   configure_metric  s   z!_WandbController.configure_metricc                 C  sH   |    t|tr|| jd< d S t|r d| jd< || _tdtd)Nprogram__callable__z'Program functions are not supported yetzUnhandled sweep program type)rT   rA   rB   r,   rF   r-   r   )rJ   rd   r   r   r   configure_program	  s   

z"_WandbController.configure_programc                 C     |    || jd< d S )Nr`   rT   r,   )rJ   r`   r   r   r   configure_name     z_WandbController.configure_namec                 C  rg   )Ndescriptionrh   )rJ   rk   r   r   r   configure_description  rj   z&_WandbController.configure_descriptionc                 C  sJ  |    | jdi |i  |d us#|d u r,|d u r,|d u r,|d u r,|| jd | d< |d ur9|| jd | d< |d urF|| jd | d< |d urS|| jd | d< |d ur`|| jd | d< |d urm|| jd | d< |d urz|| jd | d< |	d ur|	| jd | d	< |
d ur|
| jd | d
< |d ur|| jd | d< d S d S )N
parametersvaluevaluesdistributionminmaxmusigmaqabrb   )rJ   r`   ro   rn   rp   rq   rr   rs   rt   ru   rv   rw   r   r   r   configure_parameter  s0    z$_WandbController.configure_parameterc                 C  s,   |    | jdi  | jd d| dS )z1Configure controller to local if type == 'local'.
controllerrX   Nrb   )rJ   rX   r   r   r   configure_controllerC  s   z%_WandbController.configure_controllerc                 C  sL   |    | jrtdt|tr|| _d S t|tr"t|| _d S td)NzAlready configured.r*   )rT   r,   r   rA   rC   rB   yaml	safe_load)rJ   sweep_dict_or_configr   r   r   	configureI  s   


z_WandbController.configurereturndict | sweeps.SweepConfigc                 C     | j S r   )r/   rJ   r   r   r   sweep_configT     z_WandbController.sweep_configrB   c                 C  r   r   )r+   r   r   r   r   sweep_idX  r   z_WandbController.sweep_idNonec                 C  s   |  j d7  _ d S )N   )r9   r   r   r   r   _log\  s   z_WandbController._logsc                 C     t d| |   d S )NzERROR:printr   rJ   r   r   r   r   _error_     
z_WandbController._errorc                 C  r   )NzWARN:r   r   r   r   r   _warnc  r   z_WandbController._warnc                 C  r   )NzINFO:r   r   r   r   r   _infog  r   z_WandbController._infoc                 C  r   )NzDEBUG:r   r   r   r   r   _debugk  r   z_WandbController._debugc                 C  s   | j rtdd S )Nz/Can not configure after sweep has been started.)r6   r   r   r   r   r   rT   o  s   z!_WandbController._configure_checkconfigrC   c                 C  s*   t |}t|dkrt|}|S d}|S )Nr   r   )r   &schema_violations_from_proposed_configlenr	   )rJ   r   
violationsmsgr   r   r   	_validates  s   
z_WandbController._validateFr)   boolc                 C  s   | j rtd| js|std| jstdt| j| _| j| j\}}t| t	d| t
| j|}|r>t	d| || _d| _|S )Nz,Can not create after sweep has been started.z,Can not use create on already created sweep.z#Must configure sweep before create.zCreate sweep with ID:z
Sweep URL:F)r6   r   r8   r,   r   rD   r@   upsert_sweepr   r   r   _get_sweep_urlr+   )rJ   r)   r   warnings	sweep_urlr   r   r   rH   |  s    


z_WandbController.createTverboseprint_statusprint_actionsprint_debugc                 C  sf   |rd}d}d}|    |  s1|r|   |   |r |   |r&|   td |  rd S d S )NT   )_start_if_not_starteddoner   stepr   r   timesleep)rJ   r   r   r   r   r   r   r   run  s   
z_WandbController.rundict | Nonec           
      C  s  i }| j rdg}|| j  |dd}t|}| j| j|}|s$d S || _t	|d | _
| j
di d| _ g }|d D ]h}| }d|v rW|d rWt|d |d< d|vr_td	t|d |d< d
|v rt|d
 trdd |d
 D |d
< n	td|d
 d|v rg }|d D ]}	||	7 }q||d< |tjdi | q@|| _dd | jD | _t|dpd| _t|dpd| _| j | _|S )N_stepi )keyssamplesr   r_   r`   runssummaryMetricszsweep object is missing confighistoryc                 S  s   g | ]}t |qS r   )jsonloads)r   dr   r   r   
<listcomp>      zD_WandbController._sweep_object_read_from_backend.<locals>.<listcomp>z8Invalid history value: expected list of json strings: {}sampledHistoryc                 S  s   i | ]}|j |qS r   r`   r   rr   r   r   
<dictcomp>      zD_WandbController._sweep_object_read_from_backend.<locals>.<dictcomp>ry   z{}	schedulerr   )r0   appendr   dumpsr@   sweepr+   r.   r{   r|   r/   getcopyr   
ValueErrorrA   listformatr   SweepRunr1   r2   r4   r3   r5   )
rJ   
specs_jsonr\   specsrP   r1   r   rrsampled_historyhistoryDictListr   r   r   rI     sP   


z0_WandbController._sweep_object_read_from_backendc                 C  sV   | j | jkrd S | jd }t| j }| jj| j||d\}}t| | j 	 | _d S )Nid)ry   obj_id)
r4   r5   r.   r   r   r@   r   r/   r   r   )rJ   sweep_obj_idry   r   r   r   r   r   _sweep_object_sync_to_backend  s   

z._WandbController._sweep_object_sync_to_backendc                 C  sd   | j rd S | jrtd|  }|sd S | jdi ddk}|s&tdd| _ i | _|   d S )Nz9Must specify or create a sweep before running controller.ry   rX   localz<Only sweeps with a local controller are currently supported.T)r6   r8   r   rI   r/   r   r4   r   )rJ   objis_localr   r   r   r     s"   z&_WandbController._start_if_not_startedc           
      C  s   | j dpg }g }g }g }|D ]7}|d}|d}| j|}|s%q|jr-|| |j}	|jtkr8|	s8q|| |jdkrG|| q|||fS )N	scheduledrunidr   running)r3   r   r2   stoppedr   summary_metricsstateSWEEP_INITIAL_RUN_STATE)
rJ   scheduled_liststarted_idsstopped_runs	done_runsr   r   objidr   summaryr   r   r   _parse_scheduled  s(   






z!_WandbController._parse_scheduledc                   s   |    |   |  \ | jdg }fdd|D }|| jd< | jdg } fdd|D }|| jd< g | _g | _d S )Nschedulec                   s   g | ]}| d  vr|qS )r   )r   r   r   )r   r   r   r         z*_WandbController._step.<locals>.<listcomp>	earlystopc                   s    g | ]}|vr| vr|qS r   r   r   )r   r   r   r   r     s    )r   rI   r   r4   r   r;   r<   )rJ   schedule_listnew_schedule_listearlystop_listnew_earlystop_listr   )r   r   r   r   r     s   


z_WandbController._stepc                 C  s@   |    |  }| | |  }t|dkr| | d S d S Nr   )r   rR   r   rV   r   	stop_runs)rJ   
suggestionto_stopr   r   r   r   $  s   
z_WandbController.stepc                 C  s:   |    | jd}|dd tjjjtjtjjjfD vS )Nr   c                 S  s   g | ]}|  qS r   )upperr   r   r   r   r   /  s    z)_WandbController.done.<locals>.<listcomp>)	r   r.   r   r   RunState
preemptingrn   r   r   )rJ   r   r   r   r   r   ,  s   z_WandbController.donesweeps.SweepRun | Nonec                 C  s0   | j ptj}|| j| jpg }|d u rd| _|S )NT)r&   r   next_runr/   r1   r7   )rJ   rR   r   r   r   r   _search8  s
   z_WandbController._searchc                 C  s   |    |  }|S r   )r   r   )rJ   r   r   r   r   rR   ?  s   z_WandbController.searchlist[sweeps.SweepRun]c                 C  sP   d| j vrg S | jptj}|| j| jpg }dd |D }|r&|  j|7  _|S )Nr%   c                 S  s0   g | ]}|j d urddd |j  D qS )N c                 S  s   g | ]\}}| d | qS )=r   r   r\   r]   r   r   r   r   K  r   z9_WandbController._stopping.<locals>.<listcomp>.<listcomp>)early_terminate_infor   rZ   r   r   r   r   r   r   J  s
    
z._WandbController._stopping.<locals>.<listcomp>)r   r'   r   r   r/   r1   r<   )rJ   stopperr   debug_linesr   r   r   	_stoppingD  s   
z_WandbController._stoppingc                 C  s   |    |  S r   )r   r   r   r   r   r   rV   T  s   z_WandbController.stoppingr   c                 C  s   |    | jr| jdrd S t }|d u r|dd idg}n dd t|j D }| jdd	|f |d|jidg}|| jd< | 
  d S )Nr   args)r   datac                 S  s"   g | ]\}}d  ||dqS )z{}={}rn   )r   r   r   r   r   r   r   d  s    z-_WandbController.schedule.<locals>.<listcomp>,)r   r4   r   r   sortedr   rZ   r;   r   r   r   )rJ   r   schedule_idr   
param_listr   r   r   r   X  s   
z_WandbController.scheduler   c                 C  s>   t dd |D }| jdd|f || jd< |   d S )Nc                 S  s   h | ]}|j qS r   r   r   r   r   r   	<setcomp>p  s    z-_WandbController.stop_runs.<locals>.<setcomp>stopr   r   )r   r;   r   r   r4   r   )rJ   r   r   r   r   r   r   o  s   
z_WandbController.stop_runsc                 C  s:   t | j| j| j}| j|ks| jrt| || _d| _d S r   )_sweep_statusr.   r/   r1   r:   r9   r   )rJ   statusr   r   r   r   u  s
   
z_WandbController.print_statusc                 C  s4   | j D ]\}}| |  d| d qg | _ d S )N ())r;   r   
capitalize)rJ   actionliner   r   r   r   |  s   
z_WandbController.print_actionsc                 C  s    | j D ]}| | qg | _ d S r   )r<   r   )rJ   r  r   r   r   r     s   

z_WandbController.print_debugc                 C     |  d d S NzMethod not implemented yet.r   r   r   r   r   print_space     z_WandbController.print_spacec                 C  r	  r
  r  r   r   r   r   print_summary  r  z_WandbController.print_summary)NNN)rR   rS   )rV   rW   r   )
NNNNNNNNNN)r   r   )r   rB   )r   r   )r   rB   r   r   )r   rC   r   rB   )F)r)   r   r   rB   )FTFF)
r   r   r   r   r   r   r   r   r   r   )r   r   )r   r   )r   r   )r   r   )r   r   r   r   )r   r   r   r   ),r   r   r    r!   rQ   rU   r^   rc   rf   ri   rl   rx   rz   r~   propertyr   r   r   r   r   r   r   rT   r   rH   r   rI   r   r   r   r   r   r   r   rR   r   rV   r   r   r   r   r   r  r  r   r   r   r   r"   ^   sr    
"
\


'






	

/













r"   r   r   r   dict[str, int]c                 C  sn   i }dd t jj D dg }| D ]"}|j}d}|D ]
}||kr%|} nq||d ||  d7  < q|S )Nc                 S     g | ]\}}|qS r   r   r   r`   r   r   r   r   r     r   z#_get_run_counts.<locals>.<listcomp>unknownr   r   )r   r   __members__rZ   r   rY   )r   metrics
categoriesr   r   foundcr   r   r   _get_run_counts  s   r  c                 C  s`   dd t jj D dg }g }|D ]}| |sq||  d| |   qd|}|S )Nc                 S  r  r   r   r  r   r   r   r     r   z$_get_runs_status.<locals>.<listcomp>r  z: z, )r   r   r  rZ   r   r   r  r   )r  r  mlistr  r   r   r   r   _get_runs_status  s   

r  rP   rC   
sweep_confr   
sweep_runsrB   c                 C  s"  | d }| d }t |}t|}t dd |D }t dd |D }d}	|s(|r7d| }	|r7|	d| d	7 }	t|}
|d
d}|dd }g }|| |rY||dd d|}g }|d| d| d	 |
r{|d| d|
 d	 n|d|  |	r||	 d|}|S )Nr`   r   c                 S     g | ]}|j r|qS r   )r   r   r   r   r   r     r   z!_sweep_status.<locals>.<listcomp>c                 S  r  r   )should_stopr   r   r   r   r     r   r   z	Stopped: z (Stopping: r  r$   r  r%   rX   r   zSweep: r  zRuns: z | )r   r  r  r   r   r   )rP   r  r  r   r   	run_countrun_type_countsr   rV   stopstrruns_statusr$   sweep_optionssectionsr   r   r   r    s8   




r  )r   r   r   r  )rP   rC   r  r   r  r   r   rB   )#r!   
__future__r   r   r=   r   stringr   typingr   r{   wandbr   
wandb.apisr   	wandb.sdkr   wandb.sdk.launch.sweeps.utilsr   r	   
wandb.utilr
   r   r   pendingr   ascii_lowercasedigitsr   	Exceptionr   r"   r  r  r  r   r   r   r   <module>   s:    1    
3