B
    ]@p                 @   s   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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mZ ddlmZ G dd	 d	ejZG d
d deZdS )    N)OrderedDict)colored   )Distribution   )utilc               @   s   e Zd ZdZdZdZdZdS )EmpiricalTyper   r         N)__name__
__module____qualname__MEMORYFILECONCAT_MEMORYCONCAT_FILE r   r   c/global/project/projectdirs/dasrepo/etalumis/pyprob_bucket_switch/pyprob/distributions/empirical.pyr      s   r   c            
       s  e Zd Zd^ fdd	Zdd Zdd	 Zd
d Zdd Zedd Z	edd Z
dd Zdd Zd_ddZdd Zdd Zd`ddZdaddZd d! Zd"d# Zd$d% Zd&d' Zd(d) Zdbd*d+Zd,d- Zd.d/ Zd0d1 Zd2d3 Zd4d5 Zdcd6d7Zddd8d9Zed:d; Zed<d= Z ed>d? Z!d@dA Z"dBdC Z#edDdE Z$dFdG Z%dHdI Z&edJdK Z'edLdM Z(dNdO Z)dPdQ Z*dRdS Z+dTdU Z,dedZd[Z-d\d] Z.  Z/S )f	EmpiricalNF   c                s<  t  |
 d| _|| _| jr>tj|s8td|d}nd}|| _	d| _
d | _g | _d| _d| _d | _t | _|d k	s|	d k	rh|d k	rt|tkrt|d tkr|| _qtdntdnVt|	tkrt|	d tkr
tttjj|	}	dd |	D | _ntd	ntd	td
d | jD | _| jd | _tdd | jD | _tjj t!j"| jtj#dd| _| jj$}d|%d&  | _'d| j| j'}
| j(dt)| jdd | jD d | *|
 d| _d| _|d krt+j,| _nv|	d kr td|dkrt-d| j	nHt+j.| _t/j0| j	|dd| _1|	| j1d< | j2| j1d< | j| j1d< | j13  np|d krt+j4| _g | _5nTt/j0| j	||d| _1d| j1krRt+j.| _| j1d }	dd |	D | _tdd | jD | _| jd | _tdd | jD | _tjj t!j"| jtj#dd| _| j1d | _2d| j1krD| j1d | _d| _d| _nt+j6| _d| j1krr| j1d | _2d| j1kr| j1d | _d| j1kr| j1d | _| j1d  | _7t)| j| _nd| _7|| _8| j8| _9| :  d | _;d | _<d | _=d | _>d | _?d | _'| j(| j2d! |d k	r8t)|dkr8| @||| | :  d S )"NFzFile not found: {}rcr   z7Expecting concat_empiricals to be a list of Empiricals.c             S   s   g | ]}t |d dqS )T)	file_namefile_read_only)r   ).0fr   r   r   
<listcomp>;   s    z&Empirical.__init__.<locals>.<listcomp>zAExpecting concat_empirical_file_names to be a list of file names.c             S   s   g | ]
}|j qS r   )length)r   empr   r   r   r   @   s    c             S   s   g | ]}t |jqS r   )r   	to_tensor_log_weights)r   r   r   r   r   r   B   s    )dtype)logitsg      ?r   z2Concatenated empirical, length: {:,}, ESS: {:,.2f}concatc             S   s   g | ]
}|j qS r   )	_metadata)r   r   r   r   r   r   M   s    )opZnum_empiricalsZmetadata_empiricalsTzMExpecting concat_empirical_file_names to write a concatenated empirical file.zJEmpirical file already exists, cannot write new concatenated Empirical: {})flagZ	writebackconcat_empirical_file_namesnamemetadatac             S   s   g | ]}t |d dqS )T)r   r   )r   )r   r   r   r   r   r   h   s    c             S   s   g | ]
}|j qS r   )r   )r   r   r   r   r   r   i   s    c             S   s   g | ]}t |jqS r   )r   r    r!   )r   r   r   r   r   r   k   s    log_weightslast_key)r)   )Asuper__init__
_finalized
_read_onlyospathexists
ValueErrorformat
_file_name_closed_categoricalr!   _length_uniform_weights_typer   r%   typelistr   _concat_empiricals	TypeErrorstrmapabspathnpcumsum_concat_cum_sizestorchcatdistributionsCategoricalr   r    float64probspowsum_effective_sample_sizeadd_metadatalenrenamer   r   RuntimeErrorr   shelveopen_shelfr)   closer   _valuesr   _file_last_key_file_sync_timeout_file_sync_countdownfinalize_mean	_variance_mode_min_maxadd_sequence)selfvaluesr+   weightsr   r   Zfile_sync_timeoutZfile_writebackZconcat_empiricalsr(   r)   Z
shelf_flag)	__class__r   r   r.      s    


"









zEmpirical.__init__c             C   s   | S )Nr   )rb   r   r   r   	__enter__   s    zEmpirical.__enter__c             C   s   | j s|   d S )N)r7   rV   )rb   Zexception_typeZexception_value	tracebackr   r   r   __exit__   s    zEmpirical.__exit__c             C   s   | j s|   d S )N)r7   rV   )rb   r   r   r   __del__   s    zEmpirical.__del__c             C   s   | j S )N)r9   )rb   r   r   r   __len__   s    zEmpirical.__len__c             C   s   | j S )N)r9   )rb   r   r   r   r      s    zEmpirical.lengthc             C   s   | j S )N)r%   )rb   r   r   r   r*      s    zEmpirical.metadatac             K   s   || j dt| j < d S )Nz{})r%   r5   rP   )rb   kwargsr   r   r   rO      s    zEmpirical.add_metadatac             C   s.   | j tjkr*|   | js*| j  d| _d S )NT)r;   r   r   r[   r7   rU   rV   )rb   r   r   r   rV      s
    
zEmpirical.closec             C   s  |    | jtjkr|d krpd| j}t| t|  | j	| j
d}t| j|_|jdd| jdd |S d| j|}t| t|| j
d}x,t| jD ]}|j| || j	| d	 qW |  t| j|_|jdd| jd|d |S n| jtjkr|d krLd
}t| t| }t| j|_|jdddd |S d|}t| t| j| j	|| j
d}t| j|_|jddd|d |S ntdt| jd S )Nz2Copy Empirical(file_name: {}) to Empirical(memory))rc   r+   r)   copyzEmpirical(file_name: {})zEmpirical(memory))r&   sourcetargetz9Copy Empirical(file_name: {}) to Empirical(file_name: {}))r   r)   )value
log_weightz+Copy Empirical(memory) to Empirical(memory)z2Copy Empirical(memory) to Empirical(file_name: {}))rc   r+   r   r)   zNot implemented for type: {})_check_finalizedr;   r   r   r5   r6   printr   
get_valuesr!   r)   rl   deepcopyr%   rO   ranger9   add
_get_valuer[   r   rW   NotImplementedErrorr@   )rb   r   statusretir   r   r   rl      sB    


zEmpirical.copyc             C   s   t | j| _tjjtj| jtjdd| _	| j
d| jd | jdkrdt| j	j| j	jd  | _nd| _| jtjkr| js| j| jd< | j| jd< | j| jd	< | j| jd
< | j  d| _d S )N)r"   )r#   r[   )r&   r   r   Fr)   r*   r+   r,   T)rP   r!   r9   rF   rH   rI   r   r    rJ   r8   rO   eqr#   allr:   r;   r   r   r0   r)   rU   r%   rX   syncr/   )rb   r   r   r   r[      s    
 
zEmpirical.finalizec             C   s   | j stdd S )Nz-Empirical not finalized. Call finalize first.)r/   rR   )rb   r   r   r   rq      s    zEmpirical._check_finalizedc             C   s   | j rtdd| _d | _d | _d | _d | _d | _d | _|d k	rT| j	
t| n4|d k	rv| j	
tt| n| j	
td | jtjkr|  jd7  _|| jt| j< |  jd8  _| jdkr|   | j| _n| j
| d S )NzEmpirical is read-only.Fg        r   r   )r0   rR   r/   r\   r]   r^   r_   r`   rN   r!   appendr   r    rF   logr;   r   r   rX   rU   r@   rZ   r[   rY   rW   )rb   ro   rp   weightr   r   r   rv      s,    

zEmpirical.addc             C   s   | j rtd|d k	rDxtt|D ]}| j|| || d q$W nZ|d k	rzxPtt|D ]}| j|| || d qZW n$x"tt|D ]}| ||  qW d S )NzEmpirical is read-only.)rp   )r   )r0   rR   ru   rP   rv   )rb   rc   r+   rd   r{   r   r   r   ra     s    zEmpirical.add_sequencec             C   s0   | j d|d || _| jtjkr,| j| jd< | S )NrQ   )r&   r)   r)   )rO   r)   r;   r   r   rU   )rb   r)   r   r   r   rQ     s
    zEmpirical.renamec             C   s~   | j tjkr| j| S | j tjkrB|dk r4| j| }| jt| S | j	|d}|dkrj|| j|d   }| j
| |S d S )Nr   rightr   )r;   r   r   rW   r   r9   rU   r@   rE   searchsortedr>   rw   )rb   indexZ	emp_indexr   r   r   rw     s    

zEmpirical._get_valuec             C   s   | j j| S )N)r8   r#   )rb   r   r   r   r   _get_log_weight#  s    zEmpirical._get_log_weightc             C   s   | j j| S )N)r8   rK   )rb   r   r   r   r   _get_weight&  s    zEmpirical._get_weightc                sV        jtjkr jS  jtjkr> fddt jD S td	t
 jd S )Nc                s   g | ]} j t| qS r   )rU   r@   )r   r{   )rb   r   r   r   .  s    z(Empirical.get_values.<locals>.<listcomp>zNot implemented for type: {})rq   r;   r   r   rW   r   ru   r9   rx   r5   r@   )rb   r   )rb   r   rs   )  s    zEmpirical.get_valuesc             C   sj   |    | jr:|d krd}|d kr,| jd }t||}n&|d k	sJ|d k	rRtdt| j }| 	|S )Nr   r   z^Sample with min_index and/or max_index not implemented for Empirical with non-uniform weights.)
rq   r:   r9   randomrandintrx   intr8   samplerw   )rb   	min_index	max_indexr   r   r   r   r   2  s    
zEmpirical.samplec             c   s,   |    xt| jD ]}| |V  qW d S )N)rq   ru   r9   rw   )rb   r{   r   r   r   __iter__@  s    zEmpirical.__iter__c             C   s   |    t|trv| jtjkr`t| j| | j| | j	d}t
| j|_|jdd|d |S tdt| jn
| |S d S )N)rc   r+   r)   slicez{})r&   r   zNot implemented for type: {})rq   
isinstancer   r;   r   r   r   rW   r!   r)   rl   rt   r%   rO   r5   rx   r@   rw   )rb   r   rz   r   r   r   __getitem__E  s    
zEmpirical.__getitem__c             C   s  |    d}| jtjkrv| jr6tt|| j| j }n>xt	| jD ].}|t
j|| j| tjd| jj|  7 }qBW n| jtjkrxt	| jD ]2}|t
j|| jt| tjd| jj|  7 }qW n>x<t	| jD ].}|t
j|| |tjd| jj|  7 }qW t
|S )Ng        )r"   )rq   r;   r   r   r:   rM   rA   rW   r9   ru   r   r    rF   rJ   r8   rK   r   rU   r@   rw   )rb   funcrz   r{   r   r   r   expectationR  s    04.zEmpirical.expectationc             O   sz   |    g }x&t| jD ]}||| | qW t||| j| jd|}t	| j
|_
|jdt| t|d |S )N)rc   r+   r)   rA   )r&   r   r   )rq   ru   r9   r   rw   r   r!   r)   rl   rt   r%   rO   rP   r   
get_source)rb   r   argsrk   rc   r{   rz   r   r   r   rA   c  s    zEmpirical.mapc       	      O   s   |    | jdkr| S g }g }x>t| jD ]0}| |}||r*|| || | q*W t|f||| jd|}t	
| j|_|jdt| t|t|d |S )Nr   )r+   r)   filter)r&   r   Zlength_afterr   )rq   r   ru   r9   rw   r   r   r   r)   rl   rt   r%   rO   rP   r   r   )	rb   r   r   rk   Zfiltered_valuesZfiltered_log_weightsr{   ro   rz   r   r   r   r   m  s    


 zEmpirical.filterc             O   s   |    |d krdd }|d kr$d}|d kr2| j}g }d|||}t||d x2t|D ]&}	t|	 ||| jd d d q\W t	  t
||| jd|}
t| j|
_|
jdt| t|t|t|d	 |
S )
Nc             S   s   | S )Nr   )xr   r   r   <lambda>  s    z$Empirical.resample.<locals>.<lambda>r   z7Resample, num_samples: {}, min_index: {}, max_index: {}Samples)r   r   )rc   r)   resample)r&   r   num_samplesr   r   )rq   r   r5   r   progress_bar_initru   progress_bar_updater   r   progress_bar_endr   r)   rl   rt   r%   rO   rP   r   )rb   r   map_funcr   r   r   rk   rc   ry   r{   rz   r   r   r   r   }  s$    
$zEmpirical.resamplec             O   s(  |    |d krdd }|d kr$d}|d kr2| j}tdt|| | }t|||}g }	g }
d||||}t|t	|d xJtt	|D ]:}t
| |	|| ||  |
| ||  qW t  t||	|
| jd|}t| j|_|jdt	| t|t|t|t|d	 |S )
Nc             S   s   | S )Nr   )r   r   r   r   r     s    z Empirical.thin.<locals>.<lambda>r   r   z=Thin, num_samples: {}, step: {}, min_index: {}, max_index: {}r   )rc   r+   r)   thin)r&   r   r   stepr   r   )rq   r   maxmathfloorru   r5   r   r   rP   r   r   rw   r   r   r   r)   rl   rt   r%   rO   r   )rb   r   r   r   r   r   rk   r   indicesrc   r+   ry   r{   rz   r   r   r   r     s,    
*zEmpirical.thinc             C   s    | j d kr| dd | _ | j S )Nc             S   s   | S )Nr   )r   r   r   r   r     s    z Empirical.mean.<locals>.<lambda>)r\   r   )rb   r   r   r   mean  s    
zEmpirical.meanc                s*   | j d kr$| j |  fdd| _ | j S )Nc                s   |   d S )Nr   r   )r   )r   r   r   r     s    z$Empirical.variance.<locals>.<lambda>)r]   r   r   )rb   r   )r   r   variance  s    
zEmpirical.variancec             C   s   |    | jd kr| jri }td| jd ttdddgd xHt| jD ]:}t	| | 
|}||kr~||  d7  < qLd||< qLW t  t| dd	 d
dd d | _n&t| jd\}}| 
t|| _| jS )NzComputing mode...ValueszYWarning: weights are uniform and mode is correct only if values in Empirical are hashableredbold)attrsr   c             S   s   | d S )Nr   r   )r   r   r   r   r     s    z Empirical.mode.<locals>.<lambda>T)keyreverser   r   )rq   r^   r:   r   r   r9   rr   r   ru   r   rw   r   sorteditemsr    r!   r   r   )rb   countsr{   ro   _r   r   r   r   mode  s"    


"zEmpirical.modec             C   sx   |    || d}d}td| jd x:t| jD ],}t| || |}||kr6|}|}q6W t  | |S )Nr   zComputing arg_max...r   )rq   rw   r   r   r9   ru   r   r   )rb   r   max_valmax_ir{   valr   r   r   arg_max  s    
zEmpirical.arg_maxc             C   sx   |    || d}d}td| jd x:t| jD ],}t| || |}||kr6|}|}q6W t  | |S )Nr   zComputing arg_min...r   )rq   rw   r   r   r9   ru   r   r   )rb   r   min_valZmin_ir{   r   r   r   r   arg_min  s    
zEmpirical.arg_minc             C   s4   |    | jd kr.| jj}d|d  | _| jS )Ng      ?r   )rq   rN   r8   rK   rL   rM   )rb   rd   r   r   r   effective_sample_size  s
    
zEmpirical.effective_sample_sizec             O   s@   |    t||  | jd|}t| j|_|jdd |S )N)rc   r)   Zdiscard_weights)r&   )rq   r   rs   r)   rl   rt   r%   rO   )rb   r   rk   rz   r   r   r   
unweighted  s
    zEmpirical.unweightedc             C   sD   y*t tt|  }|d | _|d | _W n   tdY nX d S )Nr   r   zCannot compute the minimum and maximum of values in this Empirical. Make sure the distribution is over values that are scalar or castable to scalar, e.g., a PyTorch tensor of one element.)r   rA   floatrs   r_   r`   rR   )rb   Zsorted_valuesr   r   r   _find_min_max  s    
zEmpirical._find_min_maxc             C   s   | j d kr|   | j S )N)r_   r   )rb   r   r   r   min  s    
zEmpirical.minc             C   s   | j d kr|   | j S )N)r`   r   )rb   r   r   r   r     s    
zEmpirical.maxc          	   O   s0  |    | jtjkrtt}t| j	d }|rxt
| jD ]z}d}xX| D ]L\}}tt|t| j	| rTtjt|| j| fdd||< d}qTW |sB| j| || j	| < qBW t| }	t| }
t||	|
| jd|}t| j|_|jdd |S tdntd	t| jd S )
Nr   F)dimT)rc   r+   r)   combine_duplicates)r&   z^The values in this Empirical as not hashable. Combining of duplicates not currently supported.zNot implemented for type: {}) rq   r;   r   r   collectionsdefaultdictr   r   is_hashablerW   ru   r   r   rF   equalr    	logsumexpstackr!   r=   keysrc   r   r)   rl   rt   r%   rO   rR   rx   r5   r@   )rb   r   rk   distributionZhashabler{   foundr   ro   rc   r+   rz   r   r   r   r     s*    
"
zEmpirical.combine_duplicatesc          	   C   sT   |    yt|    S    yt|  S    tdY nX Y nX d S )NzCannot convert values to numpy.)	rq   rF   r   rs   cpunumpyrC   arrayrR   )rb   r   r   r   values_numpyI  s    zEmpirical.values_numpyc             C   s   |    t| jjS )N)rq   r   to_numpyr8   rK   )rb   r   r   r   weights_numpyS  s    zEmpirical.weights_numpyc             C   s   |    t| jjS )N)rq   r   r   r8   r#   )rb   r   r   r   log_weights_numpyW  s    zEmpirical.log_weights_numpy
      	FrequencyTr   c             O   s   |	sdt jd< td tj|d}|  }|  }tj|f|||
d| |r^td |rptj	ddd |d k	rt
| |d k	rt
| |d kr| j}t| t| |  |d k	rt| |	rt  d S )	NFzaxes.unicode_minusagg)figsize)rd   densityr   clip)Znonposy)mplrcParamspltswitch_backendfigurer   r   histZxscaleZyscalexticksr)   xlabelylabeltight_layoutsavefigshow)rb   r   r   r   r   ZyticksZ
log_xscaleZ
log_yscaler   r   r   r   rk   figrc   rd   r   r   r   plot_histogram[  s0    







zEmpirical.plot_histogramc          	   C   s,   t |d}|t| j W d Q R X d S )Nw)rT   writeyamldumpr%   )rb   r   filer   r   r   save_metadatau  s    zEmpirical.save_metadata)
NNNNFr   FNNr   )N)NN)NN)NN)NNN)NNN)
r   Nr   NNFFNTr   )0r   r   r   r.   rf   rh   ri   rj   propertyr   r*   rO   rV   rl   r[   rq   rv   ra   rQ   rw   r   r   rs   r   r   r   r   rA   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   __classcell__r   r   )re   r   r      sV   q
&

	




;

r   )rF   r   rC   rl   rS   r   r   
matplotlibr   matplotlib.pyplotpyplotr   r   r   r1   enumr   	termcolorr    r   r   Enumr   r   r   r   r   r   <module>   s"   