B
    ɒ\`                 @   s   d dl 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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)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   b/global/project/projectdirs/dasrepo/etalumis/pyprob_master_mar20/pyprob/distributions/empirical.pyr      s   r   c            
       s  e Zd ZdZ fdd	Zdd Zdd	 Zd
d Zdd Zedd Z	dd Z
d[ddZdd Zdd Zd\ddZd]ddZdd Zdd Zd d! Zd"d# Zd$d% Zd^d&d'Zd(d) Zd*d+ Zd,d- Zd.d/ Zd0d1 Zd_d2d3Zd`d4d5Zed6d7 Zed8d9 Zed:d; Zd<d= Z d>d? Z!ed@dA Z"dBdC Z#dDdE Z$edFdG Z%edHdI Z&dJdK Z'e(dadLdMZ)dNdO Z*dPdQ Z+dRdS Z,dbdXdYZ-  Z.S )c	EmpiricalNF  c                s  t  |
 d| _|| _| jr>tj|s8td|d}nd}|| _	d| _
d | _g | _d| _d| _|d k	sx|	d k	r|d k	rt|tkrt|d tkr|| _qtdntdnTt|	tkrt|	d tkrt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$}
d| _d| _|d krt%j&| _'nh|	d krtd|dkrt(d| j	n:t%j)| _'t*j+| j	|dd| _,|	| j,d< |
| j,d< | j,-  n@|d kr:t%j.| _'g | _/n$t*j+| j	||d| _,d| j,krt%j)| _'| j,d }	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| _| j,d | _0d| _d| _nnt%j1| _'d| j,kr| j,d | _0d| j,krB| j,d | _| j,d | _2t3| j| _nd| _2|| _4| j4| _5| 6  d | _7d | _8d | _9d | _:d | _;d | _$|d k	rt3|dkr| <||| | 6  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>7   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   >   s    )dtype)logitsg      ?r   z.Combined empirical, traces: {:,}, ESS: {:,.2f}TzMExpecting 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namec             S   s   g | ]}t |d dqS )T)r   r   )r   )r   r   r   r   r   r   [   s    c             S   s   g | ]
}|j qS r   )r   )r   r   r   r   r   r   \   s    c             S   s   g | ]}t |jqS r   )r   r   r    )r   r   r   r   r   r   ^   s    log_weightslast_key)=super__init__
_finalized
_read_onlyospathexists
ValueErrorformat
_file_name_closed_categoricalr    _length_uniform_weightstypelistr   _concat_empiricals	TypeErrorstrmapabspathnpcumsum_concat_cum_sizestorchcatdistributionsCategoricalr   r   float64probspowsum_effective_sample_sizer   r   _typeRuntimeErrorr   shelveopen_shelfcloser   _valuesr%   r   _file_last_keylen_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   )r[   r   r   r   	__enter__{   s    zEmpirical.__enter__c             C   s   | j s|   d S )N)r2   rN   )r[   Zexception_typeZexception_value	tracebackr   r   r   __exit__~   s    zEmpirical.__exit__c             C   s   | j s|   d S )N)r2   rN   )r[   r   r   r   __del__   s    zEmpirical.__del__c             C   s   | j S )N)r4   )r[   r   r   r   __len__   s    zEmpirical.__len__c             C   s   | j S )N)r4   )r[   r   r   r   r      s    zEmpirical.lengthc             C   s.   | j tjkr*|   | js*| j  d| _d S )NT)rI   r   r   rT   r2   rM   rN   )r[   r   r   r   rN      s
    
zEmpirical.closec             C   s  |    | jtjkr|d krBtd| j t|  | j	| j
dS td| j| t|| j
d}x,t| jD ]}|j| || j	| d qnW |  |S n`| jtjkr|d krtd t| S td| t| j| j	|| j
dS ntd	t| jd S )
Nz8Copying Empirical(file_name: {}) to Empirical(memory)...)r\   r&   r%   z?Copying Empirical(file_name: {}) to Empirical(file_name: {})...)r   r%   )value
log_weightz1Copying Empirical(memory) to Empirical(memory)...z8Copying Empirical(memory) to Empirical(file_name: {})...)r\   r&   r   r%   zNot implemented for type: {})_check_finalizedrI   r   r   printr0   r1   r   
get_valuesr    r%   ranger4   add
_get_valuerT   r   copyrO   NotImplementedErrorr:   )r[   r   retir   r   r   rl      s$    
zEmpirical.copyc             C   s   t | j| _tjjtj| jtjdd| _	| jdkrTt
| j	j| j	jd  | _nd| _| jtjkr| js| j| jd< | j| jd< | j| jd< | j  d| _d S )	N)r!   )r"   r   Fr%   r&   r'   T)rQ   r    r4   r@   rB   rC   r   r   rD   r3   eqr"   allr5   rI   r   r   r+   r%   rM   rP   syncr*   )r[   r   r   r   rT      s    
 
zEmpirical.finalizec             C   s   | j stdd S )Nz-Empirical not finalized. Call finalize first.)r*   rJ   )r[   r   r   r   rf      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   )r+   rJ   r*   rU   rV   rW   rX   rY   rH   r    appendr   r   r@   logrI   r   r   rP   rM   r:   rS   rT   rR   rO   )r[   rd   re   weightr   r   r   rj      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.)re   )ru   )r+   rJ   ri   rQ   rj   )r[   r\   r&   r]   ro   r   r   r   rZ      s    zEmpirical.add_sequencec             C   s"   || _ | jtjkr| j | jd< | S )Nr%   )r%   rI   r   r   rM   )r[   r%   r   r   r   rename   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   )rI   r   r   rO   r   r4   rM   r:   r?   searchsortedr8   rk   )r[   indexZ	emp_indexr   r   r   rk      s    

zEmpirical._get_valuec             C   s   | j j| S )N)r3   r"   )r[   ry   r   r   r   _get_log_weight   s    zEmpirical._get_log_weightc             C   s   | j j| S )N)r3   rE   )r[   ry   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   )rM   r:   )r   ro   )r[   r   r   r     s    z(Empirical.get_values.<locals>.<listcomp>zNot implemented for type: {})rf   rI   r   r   rO   r   ri   r4   rm   r0   r:   )r[   r   )r[   r   rh      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.)
rf   r5   r4   randomrandintrm   intr3   samplerk   )r[   	min_index	max_indexry   r   r   r   r     s    
zEmpirical.samplec             c   s,   |    xt| jD ]}| |V  qW d S )N)rf   ri   r4   rk   )r[   ro   r   r   r   __iter__  s    zEmpirical.__iter__c             C   s^   |    t|trP| jtjkr:t| j| | j| | j	dS t
dt| jn
| |S d S )N)r\   r&   r%   zNot implemented for type: {})rf   
isinstanceslicerI   r   r   r   rO   r    r%   rm   r0   r:   rk   )r[   ry   r   r   r   __getitem__  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!   )rf   rI   r   r   r5   rG   r;   rO   r4   ri   r   r   r@   rD   r3   rE   r   rM   r:   rk   )r[   funcrn   ro   r   r   r   expectation$  s    04.zEmpirical.expectationc             O   sN   |    g }x&t| jD ]}||| | qW t||| j| jd|S )N)r\   r&   r%   )rf   ri   r4   rs   rk   r   r    r%   )r[   r   argskwargsr\   ro   r   r   r   r;   5  s
    zEmpirical.mapc             O   sz   |    | jdkr| S g }g }x>t| jD ]0}| |}||r*|| || | q*W t|f||| jd|S )Nr   )r&   r%   )	rf   r   ri   r4   rk   rs   rz   r   r%   )r[   r   r   r   Zfiltered_valuesZfiltered_log_weightsro   rd   r   r   r   filter<  s    


zEmpirical.filterc       
      O   s   |    |d krdd }g }d|d kr,dn
dt| |d krBdn
dt| }t||d x2t|D ]&}	t|	 ||| jd d d qhW t	  t
||| jd	|S )
Nc             S   s   | S )Nr   )xr   r   r   <lambda>M  s    z$Empirical.resample.<locals>.<lambda>zResampling{}{}... z, min_index: z, max_index: Samples)r   r   )r\   r%   )rf   r0   r:   r   progress_bar_initri   progress_bar_updaters   r   progress_bar_endr   r%   )
r[   num_samplesmap_funcr   r   r   r   r\   messagero   r   r   r   resampleI  s    4
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||d krpdn
dt| |d krdn
dt| }t	|t
|d	 xJtt
|D ]:}t| |	|| ||  |
| ||  qW t  t||	|
| jd
|S )Nc             S   s   | S )Nr   )r   r   r   r   r   Z  s    z Empirical.thin.<locals>.<lambda>r   r   zThinning, step: {}{}{}...r   z, min_index: z, max_index: r   )r\   r&   r%   )rf   r   maxmathfloorri   r0   r:   r   r   rQ   r   rs   rk   rz   r   r   r%   )r[   r   r   r   r   r   r   stepindicesr\   r&   r   ro   r   r   r   thinW  s&    6
zEmpirical.thinc             C   s    | j d kr| dd | _ | j S )Nc             S   s   | S )Nr   )r   r   r   r   r   o  s    z Empirical.mean.<locals>.<lambda>)rU   r   )r[   r   r   r   meanl  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   v  s    z$Empirical.variance.<locals>.<lambda>)rV   r   r   )r[   r   )r   r   variancer  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   )rf   rW   r5   r   r   r4   rg   r   ri   r   rk   r   sorteditemsr   r    r   r~   )r[   countsro   rd   _r   r   r   r   modey  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   )rf   rk   r   r   r4   ri   r   r   )r[   r   max_valmax_iro   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   )rf   rk   r   r   r4   ri   r   r   )r[   r   min_valZmin_iro   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   )rf   rH   r3   rE   rF   rG   )r[   r]   r   r   r   effective_sample_size  s
    
zEmpirical.effective_sample_sizec             O   s"   |    t||  | jd|S )N)r\   r%   )rf   r   rh   r%   )r[   r   r   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   r;   floatrh   rX   rY   rJ   )r[   Zsorted_valuesr   r   r   _find_min_max  s    
zEmpirical._find_min_maxc             C   s   | j d kr|   | j S )N)rX   r   )r[   r   r   r   min  s    
zEmpirical.minc             C   s   | j d kr|   | j S )N)rY   r   )r[   r   r   r   r     s    
zEmpirical.maxc          	   O   s  |    | jtjkrtt}t| j	d }|rxt
| jD ]z}d}xX| D ]L\}}tt|t| j	| rPtjt|| j| fdd||< d}qPW |s>| j| || j	| < q>W t| }	t| }
t||	|
| jd|S tdntdt| jd S )Nr   F)dimT)r\   r&   r%   z^The values in this Empirical as not hashable. Combining of duplicates not currently supported.zNot implemented for type: {})rf   rI   r   r   collectionsdefaultdictr   r   is_hashablerO   ri   r   r   r@   equalr   	logsumexpstackr    r7   keysr\   r   r%   rJ   rm   r0   r:   )r[   r   r   distributionZhashablero   foundr   rd   r\   r&   r   r   r   combine_duplicates  s$    
"
zEmpirical.combine_duplicatesc       	      C   s,  | d j }x:| D ]2}|j |kr0td||j t|tstdqW |tjkr|d kr`tdt|d}x>| D ]6}x0t|j	D ]"}|j
|jt| |j| d qW qpW |  |S |tjkrg }g }| d j}x2| D ]*}|j|krtd||j7 }||j7 }qW t|||dS td	t|d S )
Nr   zTExpecting all Empirical distributions to be of the same type. Encountered: {} and {}z>Combination is only supported between Empirical distributions.z8Expecting a target file_name for the combined Empirical.)r   )rd   re   zNCombination is only supported between Empirical distributions of equal length.)r\   r&   r   zNot implemented for type: {})rI   rJ   r0   r   r   r9   r   r   ri   r4   rj   rM   r:   r    rT   r   r   rO   rm   )	Zempirical_distributionsr   Zempirical_typedistrn   ro   r\   r&   r   r   r   r   combine  s4    






&



zEmpirical.combinec          	   C   sT   |    yt|    S    yt|  S    tdY nX Y nX d S )NzCannot convert values to numpy.)	rf   r@   r   rh   cpunumpyr=   arrayrJ   )r[   r   r   r   values_numpy  s    zEmpirical.values_numpyc             C   s   |    t| jjS )N)rf   r   to_numpyr3   rE   )r[   r   r   r   weights_numpy  s    zEmpirical.weights_numpyc             C   s   |    t| jjS )N)rf   r   r   r3   r"   )r[   r   r   r   log_weights_numpy  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)r]   densityrt   clip)Znonposy)mplrcParamspltswitch_backendfigurer   r   histZxscaleZyscalexticksr%   xlabelylabeltight_layoutsavefigshow)r[   r   r   r   r   ZyticksZ
log_xscaleZ
log_yscaler   r   r   r   r   figr\   r]   r   r   r   plot_histogram  s0    







zEmpirical.plot_histogram)
NNNNFr   FNNr   )N)NN)NN)NN)NNN)NNN)N)
r   Nr   NNFFNTr   )/r
   r   r   r)   r_   ra   rb   rc   propertyr   rN   rl   rT   rf   rj   rZ   rv   rk   rz   r{   rh   r   r   r   r   r;   r   r   r   r   r   r   r   r   r   r   r   r   r   r   staticmethodr   r   r   r   r   __classcell__r   r   )r^   r   r      sT   a


	





r   )r@   r   r=   rl   rK   r   
matplotlibr   matplotlib.pyplotpyplotr   r|   r   r,   enum	termcolorr   r   r   r   Enumr   r   r   r   r   r   <module>   s   