U
    KvfB                     @   s  d Z ddlmZ ddlmZ ddlZdd ZG dd dejZ	d	d
 Z
d\ZZd\ZZdd Zdd Zdd Ze	ejeedddddZe	ejejejdddddZe	ejejejddZG dd dejZG dd  d ejZd!d" ZG d#d$ d$ejZG d%d& d&Ze Zeejejejejej ej!d'd(ej"dd)d*d+Z#eej$ejejejej ej!d'd(ej"dd)d,d+Z%d-d. Zd/d0 Zd1d2 Z d3d4 Z!d5d6 Z&eeje&eee e!d7ej" d(dd8d9d+Z'd:d. Zd;d0 Zd<d2 Z d=d4 Z!d>d? Z(eejej)eee e!d'd(ej"dd@dAd+Z*dS )Ba{   A class for the distribution of a non-linear monotonic transformation of a continuous random variable

simplest usage:
example: create log-gamma distribution, i.e. y = log(x),
            where x is gamma distributed (also available in scipy.stats)
    loggammaexpg = Transf_gen(stats.gamma, np.log, np.exp)

example: what is the distribution of the discount factor y=1/(1+x)
            where interest rate x is normally distributed with N(mux,stdx**2)')?
            (just to come up with a story that implies a nice transformation)
    invnormalg = Transf_gen(stats.norm, inversew, inversew_inv, decr=True, a=-np.inf)

This class does not work well for distributions with difficult shapes,
    e.g. 1/x where x is standard normal, because of the singularity and jump at zero.

Note: I'm working from my version of scipy.stats.distribution.
      But this script runs under scipy 0.6.0 (checked with numpy: 1.2.0rc2 and python 2.4)

This is not yet thoroughly tested, polished or optimized

TODO:
  * numargs handling is not yet working properly, numargs needs to be specified (default = 0 or 1)
  * feeding args and kwargs to underlying distribution is untested and incomplete
  * distinguish args and kwargs for the transformed and the underlying distribution
    - currently all args and no kwargs are transmitted to underlying distribution
    - loc and scale only work for transformed, but not for underlying distribution
    - possible to separate args for transformation and underlying distribution parameters

  * add _rvs as method, will be faster in many cases


Created on Tuesday, October 28, 2008, 12:40:37 PM
Author: josef-pktd
License: BSD

    )stats)distributionsNc                  K   s*   t dd |  D }|dd }||fS )Nc                 s   s.   | ]&\}}| d r|d dd|fV  qdS )Zu_    N)
startswithreplace).0kv r   Q/tmp/pip-unpacked-wheel-2v6byqio/statsmodels/sandbox/distributions/transformed.py	<genexpr>.   s    
z#get_u_argskwargs.<locals>.<genexpr>u_args)dictitemspop)kwargsu_kwargsr   r   r   r   get_u_argskwargs,   s    r   c                       s0   e Zd ZdZ fddZdd Zdd Z  ZS )
Transf_genzUa class for non-linear monotonic transformation of a continuous random variable

    c                    s   || _ || _|dd| _|dd}|dd}|dd }|dtj }	|d	tj}
|d
d| _tf |\| _| _	|| _
tt| j|	|
||j|d d S )Nnumargsr   name
transfdistlongname#Non-linear transformed distributionextradocabdecrFr   r   r   shapesr   )funcfuncinvr   r   npinfr   r   r   r   klssuperr   __init__r    )selfr%   r!   r"   argsr   r   r   r   r   r   	__class__r   r   r'   9   s    zTransf_gen.__init__c                 O   sB   | j s | jj| |f||S d| jj| |f|| S d S N      ?)r   r%   _cdfr"   r(   xr)   r   r   r   r   r.   V   s    zTransf_gen._cdfc                 O   sB   | j s | | jj|f||S | | jjd| f||S d S )Nr   )r   r!   r%   _ppf)r(   qr)   r   r   r   r   r1   ^   s    zTransf_gen._ppf__name__
__module____qualname____doc__r'   r.   r1   __classcell__r   r   r*   r   r   4   s   r   c                 C   s   t d| S r,   )r#   divider0   r   r   r   inversee   s    r;   )g?g?)g      "@r-   c                 C   s   ddt  | t   S )Nr-   r   muxstdxr:   r   r   r   inversewm   s    r?   c                 C   s   d|  d t  t S r,   r<   r:   r   r   r   inversew_invq   s    r@   c                 C   s   | S Nr   r:   r   r   r   identitu   s    rB   TZdiscfznormal-based discount factor)r   r   r   r      ZlnnormzExp transformed normal)r   r   r   r   r   )r   c                       s0   e Zd ZdZ fddZdd Zdd Z  ZS )ExpTransf_genDistribution based on log/exp transformation

    the constructor can be called with a distribution class
    and generates the distribution of the transformed random variable

    c                    sd   d|kr|d | _ nd| _ d|kr,|d }nd}d|krB|d }nd}tt| j||d || _d S Nr   r   r   zLog transformed distributionr   r   r   r   )r   r&   rD   r'   r%   r(   r%   r)   r   r   r   r*   r   r   r'      s    

zExpTransf_gen.__init__c                 G   s   | j jt|f| S rA   )r%   r.   r#   logr(   r0   r)   r   r   r   r.      s    zExpTransf_gen._cdfc                 G   s   t | jj|f| S rA   )r#   expr%   r1   r(   r2   r)   r   r   r   r1      s    zExpTransf_gen._ppfr3   r   r   r*   r   rD      s   rD   c                       s0   e Zd ZdZ fddZdd Zdd Z  ZS )LogTransf_genrE   c                    sd   d|kr|d | _ nd| _ d|kr,|d }nd}d|krB|d }nd}tt| j||d || _d S rF   )r   r&   rM   r'   r%   rH   r*   r   r   r'      s    

zLogTransf_gen.__init__c                 G   s   | j jt|f| S rA   )r%   r.   r#   rK   rJ   r   r   r   r.      s    zLogTransf_gen._cdfc                 G   s   t | jj|f| S rA   )r#   rI   r%   r1   rL   r   r   r   r1      s    zLogTransf_gen._ppfr3   r   r   r*   r   rM      s   rM   c                  C   s  t d ttjddd} t | d t tjdd t |   t tjd t | jdd t d ttj}t |	dd	 t tj
dd	 t |	d
d t tj
d
d t d ttj}t |	d
d	 t tjd
d	 ttj}t |	d
d	 d S )NzResults for lognormalr   zLog transformed normal generalrG   r      )sizezResults for expgamma
   rC      zResults for loglaplace)printrD   r   normZcdfZlognormZrvsrM   gammar.   ZloggammaZlaplaceZ
loglaplace)
lognormalgloggammaexpgZloglaplacegZloglaplaceexpgr   r   r   examples_transf   s&    


rW   c                       sH   e Zd ZdZ fddZdd Zdd Zdd	 Zd
d Zdd Z	  Z
S )TransfTwo_genaO  Distribution based on a non-monotonic (u- or hump-shaped transformation)

    the constructor can be called with a distribution class, and functions
    that define the non-linear transformation.
    and generates the distribution of the transformed random variable

    Note: the transformation, it's inverse and derivatives need to be fully
    specified: func, funcinvplus, funcinvminus, derivplus,  derivminus.
    Currently no numerical derivatives or inverse are calculated

    This can be used to generate distribution instances similar to the
    distributions in scipy.stats.

    c                    s   || _ || _|| _|| _|| _|dd| _|dd}	|dd}
|dd }|dtj }|d	tj}|d
d| _	t
f |\| _| _|| _tt| j|||	|j|
d d S )Nr   r   r   r   r   r   r   r   r   shapeFr   )r!   funcinvplusfuncinvminus	derivplus
derivminusr   r   r#   r$   rY   r   r   r   r%   r&   rX   r'   r    )r(   r%   r!   rZ   r[   r\   r]   r)   r   r   r   r   r   r   r*   r   r   r'   3  s&    zTransfTwo_gen.__init__c                 G   s   | j | j_ | | jj| S rA   )_sizer%   r!   _rvs)r(   r)   r   r   r   r_   U  s    
zTransfTwo_gen._rvsc                 O   st   | j dkrd}n| j dkr d}ntd|| || jj| |f|| | || jj| |f||   S )Nur   humpzshape can only be `u` or `hump`)rY   
ValueErrorr\   r%   _pdfrZ   r]   r[   )r(   r0   r)   r   Zsignpdfr   r   r   rd   Y  s    

$zTransfTwo_gen._pdfc                 O   sX   | j dkr>| jj| |f||| jj| |f|| S d| j|f|| S d S )Nr`   r-   )rY   r%   r.   rZ   r[   _sfr/   r   r   r   r.   g  s
    
zTransfTwo_gen._cdfc                 O   sX   | j dkr>| jj| |f||| jj| |f|| S d| j|f|| S d S )Nra   r-   )rY   r%   r.   rZ   r[   r/   r   r   r   re   p  s
    
zTransfTwo_gen._sfc                 O   s   | j |f| S rA   )Z_mom0_sc)r(   nr)   r   r   r   r   _munpy  s    zTransfTwo_gen._munp)r4   r5   r6   r7   r'   r_   rd   r.   re   rg   r8   r   r   r*   r   rX   "  s   "		rX   c                   @   s8   e Zd ZdZdd Zdd Zdd Zdd	 Zd
d ZdS )
SquareFunczclass to hold quadratic function with inverse function and derivative

    using instance methods instead of class methods, if we want extension
    to parametrized function
    c                 C   s
   t |S rA   r#   sqrtr(   r0   r   r   r   inverseplus  s    zSquareFunc.inverseplusc                 C   s   dt | S N        ri   rk   r   r   r   inverseminus  s    zSquareFunc.inverseminusc                 C   s   dt | S N      ?ri   rk   r   r   r   r\     s    zSquareFunc.derivplusc                 C   s   ddt |  S Nrn   rq   ri   rk   r   r   r   r]     s    zSquareFunc.derivminusc                 C   s   t |dS NrC   r#   powerrk   r   r   r   
squarefunc  s    zSquareFunc.squarefuncN)	r4   r5   r6   r7   rl   ro   r\   r]   rv   r   r   r   r   rh     s   rh   r`   rn   Z
squarenormzsquared normal distribution)rY   r   r   r   r   r   zsquared t distributionc                 C   s   t |  S rA   ri   r:   r   r   r   rl     s    rl   c                 C   s   dt |   S rm   ri   r:   r   r   r   ro     s    ro   c                 C   s   ddt |    S rr   ri   r:   r   r   r   r\     s    r\   c                 C   s   dt |   S rp   ri   r:   r   r   r   r]     s    r]   c                 C   s   t | d S rs   rt   r:   r   r   r   negsquarefunc  s    rw   ra   Znegsquarenormz$negative squared normal distributionc                 C   s   | S rA   r   r:   r   r   r   rl     s    c                 C   s   d|  S rm   r   r:   r   r   r   ro     s    c                 C   s   dS r,   r   r:   r   r   r   r\     s    c                 C   s   dS )Ng      r   r:   r   r   r   r]     s    c                 C   s
   t | S rA   )r#   absr:   r   r   r   absfunc  s    ry   Zabsnormzabsolute of normal distribution)+r7   Zscipyr   Zscipy.statsr   Znumpyr#   r   Zrv_continuousr   r;   r=   r>   r?   r@   rB   rS   ZinvdnormalgrK   rI   rU   rT   rV   rD   rM   rW   rX   rh   Zsqfuncrv   rl   ro   r\   r]   r$   ZsquarenormalgtZsquaretgrw   Znegsquarenormalgry   rx   Z
absnormalgr   r   r   r   <module>   s   $1    
#"Ne            	           