o
    8VaBT                     @   sP  d dl mZmZmZmZmZmZ d dlmZm	Z	 d dl
mZmZmZmZmZmZmZmZmZ d dlmZmZmZmZmZmZmZ d dlmZ G dd deZdd	 ZG d
d dZ G dd dZ!G dd dZ"e e"e!dZ#G dd deeZ$G dd de$Z%dd Z&G dd de$Z'dd Z(G dd de$Z)dd Z*G dd  d e$Z+d!d" Z,d#S )$    )SBasicexp
multigammapiprod)sympify_sympify)	ImmutableMatrixInverseTraceDeterminantMatrixSymbol
MatrixBase	Transpose	MatrixSetmatrix2numpy)_value_checkRandomMatrixSymbolNamedArgsMixinPSpace_symbol_converterMatrixDomainDistribution)import_modulec                   @   sf   e Zd ZdZdd Zedd Zedd Zedd Zed	d
 Z	edd Z
dd ZdddZdS )MatrixPSpacezD
    Represents probability space for
    Matrix Distributions.
    c                 C   s@   t |}t|t|}}|jr|jstdt| ||||S )NzDimensions should be integers)r   r	   
is_integer
ValueErrorr   __new__)clsZsymdistributionZdim_nZdim_m r!   B/usr/lib/python3/dist-packages/sympy/stats/matrix_distributions.pyr      s
   zMatrixPSpace.__new__c                 C   
   | j d S )N   argsselfr!   r!   r"   <lambda>      
 zMatrixPSpace.<lambda>c                 C   r#   Nr   r%   r'   r!   r!   r"   r)      r*   c                 C   s   t | j| jjS N)r   symbolr    setr'   r!   r!   r"   domain   s   zMatrixPSpace.domainc                 C   s   t | j| jd | jd | S )N      )r   r-   r&   r'   r!   r!   r"   value!   s   zMatrixPSpace.valuec                 C   s   | j hS r,   )r2   r'   r!   r!   r"   values%      zMatrixPSpace.valuesc                 G   s4   | t}t|dkst|tstd| j|S )Nr$   ztCurrently, no algorithm has been implemented to handle general expressions containing multiple matrix distributions.)Zatomsr   len
isinstanceNotImplementedErrorr    pdf)r(   exprr&   Zrmsr!   r!   r"   compute_density)   s   
zMatrixPSpace.compute_densityr!   scipyNc                 C   s   | j | jj|||diS )zu
        Internal sample method

        Returns dictionary mapping RandomMatrixSymbol to realization value.
        )libraryseed)r2   r    sample)r(   sizer<   r=   r!   r!   r"   r>   1   s   zMatrixPSpace.sampler!   r;   N)__name__
__module____qualname____doc__r   propertyr    r-   r/   r2   r3   r:   r>   r!   r!   r!   r"   r      s    


r   c                 C   sB   t tt|}|| }|j|  |j}t| ||d |d }|jS )Nr   r$   )listmapr   check	dimensionr   r2   )r-   r   r&   distZdimZpspacer!   r!   r"   rv:   s   
rK   c                   @   &   e Zd ZdZdddZedd ZdS )SampleMatrixScipyz7Returns the sample from scipy of the given distributionNc                 C      |  |||S r,   )_sample_scipyr   rJ   r?   r=   r!   r!   r"   r   E      zSampleMatrixScipy.__new__c           
         s   ddl m  ddl} fdd fddd}dd d	d d}| }|jj|vr,dS |du s5t|tr=|jj	|d
}n|}||jj |t
||}	|	|||jj | S )zSample from SciPy.r   )statsNc                    s     j jt| jt| jt|dS )N)ZdfZscaler?   )Zwishartrvsintnr   scale_matrixfloatrJ   r?   
rand_stateZscipy_statsr!   r"   r)   O   s    z1SampleMatrixScipy._sample_scipy.<locals>.<lambda>c                    s.    j jt| jtt| jtt| jt||dS )N)Zmeanrowcovcolcovr?   Zrandom_state)Zmatrix_normalrS   r   location_matrixrW   scale_matrix_1scale_matrix_2rX   rZ   r!   r"   r)   Q   s
    

WishartDistributionMatrixNormalDistributionc                 S      | j jS r,   rV   shaperJ   r!   r!   r"   r)   X       c                 S   rc   r,   r]   re   rf   r!   r!   r"   r)   Y   rg   r=   )r;   rR   numpykeys	__class__rA   r6   rT   randomdefault_rngr   reshape)
r   rJ   r?   r=   rj   Zscipy_rv_mapsample_shape	dist_listrY   sampr!   rZ   r"   rO   H   s    


zSampleMatrixScipy._sample_scipyr,   )rA   rB   rC   rD   r   classmethodrO   r!   r!   r!   r"   rM   C   s
    
rM   c                   @   rL   )SampleMatrixNumpyz7Returns the sample from numpy of the given distributionNc                 C   rN   r,   )_sample_numpyrP   r!   r!   r"   r   m   rQ   zSampleMatrixNumpy.__new__c           
      C   s   i }i }|  }|jj|vrdS ddl}|du st|tr%|jj|d}n|}||jj |t||}	|		|||jj | S )zSample from NumPy.Nr   ri   )
rk   rl   rA   rj   r6   rT   rm   rn   r   ro   )
r   rJ   r?   r=   Znumpy_rv_maprp   rq   rj   rY   rr   r!   r!   r"   ru   p   s   zSampleMatrixNumpy._sample_numpyr,   )rA   rB   rC   rD   r   rs   ru   r!   r!   r!   r"   rt   i   s
    
rt   c                   @   rL   )SampleMatrixPymcz7Returns the sample from pymc3 of the given distributionNc                 C   rN   r,   )_sample_pymc3rP   r!   r!   r"   r      rQ   zSampleMatrixPymc.__new__c           	   	      s   ddl   fdd fddd}dd dd d	}| }|jj|vr&dS ddl}|d
|j    ||jj |  j	t
|dd|dddd }W d   n1 sYw   Y  ||||jj | S )zSample from PyMC3.r   Nc                    s0    j dt| jtt| jtt| jt| jjdS )NX)Zmur[   r\   re   )MatrixNormalr   r]   rW   r^   r_   re   rf   pymc3r!   r"   r)      s    


z0SampleMatrixPymc._sample_pymc3.<locals>.<lambda>c                    s    j dt| jt| jtdS )Nrx   )nur   )ZWishartBartlettrT   rU   r   rV   rW   rf   rz   r!   r"   r)      s    )rb   ra   c                 S   rc   r,   rd   rf   r!   r!   r"   r)      rg   c                 S   rc   r,   rh   rf   r!   r!   r"   r)      rg   r`   r{   r$   F)ZdrawsZchainsZprogressbarZrandom_seedZreturn_inferencedataZcompute_convergence_checksrx   )r{   rk   rl   rA   loggingZ	getLoggerZsetLevelZERRORZModelr>   r   ro   )	r   rJ   r?   r=   Zpymc3_rv_maprp   rq   r}   sampsr!   rz   r"   rw      s"   


 zSampleMatrixPymc._sample_pymc3r,   )rA   rB   rC   rD   r   rs   rw   r!   r!   r!   r"   rv      s
    
rv   )r;   r{   rj   c                   @   s6   e Zd ZdZdd Zedd Zdd ZdddZd
S )MatrixDistributionz1
    Abstract class for Matrix Distribution.
    c                 G   s    t tt|}tj| g|R  S r,   )rF   rG   r   r   r   )r   r&   r!   r!   r"   r      s   zMatrixDistribution.__new__c                  G   s   d S r,   r!   r%   r!   r!   r"   rH      s   zMatrixDistribution.checkc                 C   s   t |tr	t|}| |S r,   )r6   rF   r
   r8   )r(   r9   r!   r!   r"   __call__   s   

zMatrixDistribution.__call__r!   r;   Nc                 C   sd   g d}||vrt dt| t|std| t| | ||}|dur(|S t d| jj|f )zo
        Internal sample method

        Returns dictionary mapping RandomSymbol to realization value.
        )r;   rj   r{   z&Sampling from %s is not supported yet.zFailed to import %sNz4Sampling for %s is not currently implemented from %s)r7   strr   r   _get_sample_class_matrixrvrl   rA   )r(   r?   r<   r=   Z	librariesr~   r!   r!   r"   r>      s   
zMatrixDistribution.sampler@   )	rA   rB   rC   rD   r   staticmethodrH   r   r>   r!   r!   r!   r"   r      s    
r   c                   @   <   e Zd ZdZedd Zedd Zedd Zdd	 Z	d
S )MatrixGammaDistributionalphabetarV   c                 C   s>   t |tst|jd t|jd t| jd t|jd d S )N+The shape matrix must be positive definite.Should be square matrix#Shape parameter should be positive.z#Scale parameter should be positive.r6   r   r   is_positive_definite	is_squareis_positiver   r!   r!   r"   rH      s
   
zMatrixGammaDistribution.checkc                 C      | j jd }t||tjS r+   rV   re   r   r   Realsr(   kr!   r!   r"   r.         zMatrixGammaDistribution.setc                 C   rc   r,   rd   r'   r!   r!   r"   rI      r4   z!MatrixGammaDistribution.dimensionc           
      C   s   | j | j| j}}}|jd }t|trt|}t|ttfs(t	dt
| t| | | }tt||||  t||  }t||  }t||t|d d   }	|| |	 S )Nr   4%s should be an isinstance of Matrix or MatrixSymbolr$   r0   )r   r   rV   re   r6   rF   r
   r   r   r   r   r   r   r   r   r   r   )
r(   xr   r   rV   psigma_inv_xterm1term2term3r!   r!   r"   r8      s   

"zMatrixGammaDistribution.pdfN
rA   rB   rC   Z	_argnamesr   rH   rE   r.   rI   r8   r!   r!   r!   r"   r      s    
	

r   c                 C   s$   t |tr	t|}t| t|||fS )a  
    Creates a random variable with Matrix Gamma Distribution.

    The density of the said distribution can be found at [1].

    Parameters
    ==========

    alpha: Positive Real number
        Shape Parameter
    beta: Positive Real number
        Scale Parameter
    scale_matrix: Positive definite real square matrix
        Scale Matrix

    Returns
    =======

    RandomSymbol

    Examples
    ========

    >>> from sympy.stats import density, MatrixGamma
    >>> from sympy import MatrixSymbol, symbols
    >>> a, b = symbols('a b', positive=True)
    >>> M = MatrixGamma('M', a, b, [[2, 1], [1, 2]])
    >>> X = MatrixSymbol('X', 2, 2)
    >>> density(M)(X).doit()
    exp(Trace(Matrix([
    [-2/3,  1/3],
    [ 1/3, -2/3]])*X)/b)*Determinant(X)**(a - 3/2)/(3**a*sqrt(pi)*b**(2*a)*gamma(a)*gamma(a - 1/2))
    >>> density(M)([[1, 0], [0, 1]]).doit()
    exp(-4/(3*b))/(3**a*sqrt(pi)*b**(2*a)*gamma(a)*gamma(a - 1/2))


    References
    ==========

    .. [1] https://en.wikipedia.org/wiki/Matrix_gamma_distribution

    )r6   rF   r
   rK   r   )r-   r   r   rV   r!   r!   r"   MatrixGamma  s   
+r   c                   @   r   )ra   rU   rV   c                 C   s2   t |tst|jd t|jd t| jd d S )Nr   r   r   r   r   r!   r!   r"   rH   A  s   
zWishartDistribution.checkc                 C   r   r+   r   r   r!   r!   r"   r.   J  r   zWishartDistribution.setc                 C   rc   r,   rd   r'   r!   r!   r"   rI   O  r4   zWishartDistribution.dimensionc           	      C   s   | j | j}}|jd }t|trt|}t|ttfs$tdt	| t
| | td }tt|d|| td  t|td |  }t|| td  }t|t|| d d  }|| | S )Nr   r   r0   r$   )rU   rV   re   r6   rF   r
   r   r   r   r   r   r   r   r   r   r   )	r(   r   rU   rV   r   r   r   r   r   r!   r!   r"   r8   S  s   

2zWishartDistribution.pdfNr   r!   r!   r!   r"   ra   =  s    


ra   c                 C   s"   t |tr	t|}t| t||fS )a  
    Creates a random variable with Wishart Distribution.

    The density of the said distribution can be found at [1].

    Parameters
    ==========

    n: Positive Real number
        Represents degrees of freedom
    scale_matrix: Positive definite real square matrix
        Scale Matrix

    Returns
    =======

    RandomSymbol

    Examples
    ========

    >>> from sympy.stats import density, Wishart
    >>> from sympy import MatrixSymbol, symbols
    >>> n = symbols('n', positive=True)
    >>> W = Wishart('W', n, [[2, 1], [1, 2]])
    >>> X = MatrixSymbol('X', 2, 2)
    >>> density(W)(X).doit()
    exp(Trace(Matrix([
    [-1/3,  1/6],
    [ 1/6, -1/3]])*X))*Determinant(X)**(n/2 - 3/2)/(2**n*3**(n/2)*sqrt(pi)*gamma(n/2)*gamma(n/2 - 1/2))
    >>> density(W)([[1, 0], [0, 1]]).doit()
    exp(-2/3)/(2**n*3**(n/2)*sqrt(pi)*gamma(n/2)*gamma(n/2 - 1/2))

    References
    ==========

    .. [1] https://en.wikipedia.org/wiki/Wishart_distribution

    )r6   rF   r
   rK   ra   )r-   rU   rV   r!   r!   r"   Wisharta  s   
(r   c                   @   r   )rb   )r]   r^   r_   c                 C   s   t |tst|jd t |tst|jd t|jd t|jd | jd }| jd }t|jd |kdt|t|f  t|jd |kdt|t|f  d S )Nr   )Scale matrix 1 should be be square matrix)Scale matrix 2 should be be square matrixr   r$   )Scale matrix 1 should be of shape %s x %s)Scale matrix 2 should be of shape %s x %s)r6   r   r   r   r   re   r   )r]   r^   r_   rU   r   r!   r!   r"   rH     s   




zMatrixNormalDistribution.checkc                 C      | j j\}}t||tjS r,   r]   re   r   r   r   r(   rU   r   r!   r!   r"   r.     r   zMatrixNormalDistribution.setc                 C   rc   r,   rh   r'   r!   r!   r"   rI     r4   z"MatrixNormalDistribution.dimensionc           
      C   s   | j | j| j}}}|j\}}t|trt|}t|ttfs(t	dt
| t|t||  t| ||  }tt| td }dt t|| d  t|t|  d t|t|  d }	||	 S )Nr   r0   )r]   r^   r_   re   r6   rF   r
   r   r   r   r   r   r   r   r   r   r   r   )
r(   r   MUVrU   r   r   ZnumZdenr!   r!   r"   r8     s   

$@zMatrixNormalDistribution.pdfNr   r!   r!   r!   r"   rb     s    


rb   c                 C   sL   t |tr	t|}t |trt|}t |trt|}|||f}t| t|S )a  
    Creates a random variable with Matrix Normal Distribution.

    The density of the said distribution can be found at [1].

    Parameters
    ==========

    location_matrix: Real ``n x p`` matrix
        Represents degrees of freedom
    scale_matrix_1: Positive definite matrix
        Scale Matrix of shape ``n x n``
    scale_matrix_2: Positive definite matrix
        Scale Matrix of shape ``p x p``

    Returns
    =======

    RandomSymbol

    Examples
    ========

    >>> from sympy import MatrixSymbol
    >>> from sympy.stats import density, MatrixNormal
    >>> M = MatrixNormal('M', [[1, 2]], [1], [[1, 0], [0, 1]])
    >>> X = MatrixSymbol('X', 1, 2)
    >>> density(M)(X).doit()
    2*exp(-Trace((Matrix([
    [-1],
    [-2]]) + X.T)*(Matrix([[-1, -2]]) + X))/2)/pi
    >>> density(M)([[3, 4]]).doit()
    2*exp(-4)/pi

    References
    ==========

    .. [1] https://en.wikipedia.org/wiki/Matrix_normal_distribution

    )r6   rF   r
   rK   rb   )r-   r]   r^   r_   r&   r!   r!   r"   ry     s   
)


ry   c                   @   r   )MatrixStudentTDistribution)r|   r]   r^   r_   c                 C   s   t |tst|jdkd t |tst|jdkd t|jdkd t|jdkd |jd }|jd }t|jd |kdt|t|f  t|jd |kdt|t|f  t| jdkd	 d S )
NFr   r   r   r   r$   r   r   z#Degrees of freedom must be positive)r6   r   r   r   r   re   r   r   )r|   r]   r^   r_   rU   r   r!   r!   r"   rH     s   



z MatrixStudentTDistribution.checkc                 C   r   r,   r   r   r!   r!   r"   r.   
  r   zMatrixStudentTDistribution.setc                 C   rc   r,   rh   r'   r!   r!   r"   rI     r4   z$MatrixStudentTDistribution.dimensionc           
      C   s  ddl m} t|trt|}t|ttfstdt| | j	| j
| j| jf\}}}}|j\}}t|| | d d |t|| d   t|| d   t|| d  t|| d d |  }	|	t||t|||  t| t||   || | d  d   S )Nr   )eyer   r$   r0   )sympyr   r6   rF   r
   r   r   r   r   r|   r]   r^   r_   re   r   r   r   r   r   )
r(   r   r   r|   r   ZOmegaZSigmarU   r   Kr!   r!   r"   r8     s   

<$0zMatrixStudentTDistribution.pdfNr   r!   r!   r!   r"   r     s    


r   c                 C   sN   t |tr	t|}t |trt|}t |trt|}||||f}t| t|S )a  
    Creates a random variable with Matrix Gamma Distribution.

    The density of the said distribution can be found at [1].

    Parameters
    ==========

    nu: Positive Real number
        degrees of freedom
    location_matrix: Positive definite real square matrix
        Location Matrix of shape ``n x p``
    scale_matrix_1: Positive definite real square matrix
        Scale Matrix of shape ``p x p``
    scale_matrix_2: Positive definite real square matrix
        Scale Matrix of shape ``n x n``

    Returns
    =======

    RandomSymbol

    Examples
    ========

    >>> from sympy import MatrixSymbol,symbols
    >>> from sympy.stats import density, MatrixStudentT
    >>> v = symbols('v',positive=True)
    >>> M = MatrixStudentT('M', v, [[1, 2]], [[1, 0], [0, 1]], [1])
    >>> X = MatrixSymbol('X', 1, 2)
    >>> density(M)(X)
    gamma(v/2 + 1)*Determinant((Matrix([[-1, -2]]) + X)*(Matrix([
    [-1],
    [-2]]) + X.T) + Matrix([[1]]))**(-v/2 - 1)/(pi**1.0*gamma(v/2)*Determinant(Matrix([[1]]))**1.0*Determinant(Matrix([
    [1, 0],
    [0, 1]]))**0.5)

    References
    ==========

    .. [1] https://en.wikipedia.org/wiki/Matrix_t-distribution

    )r6   rF   r
   rK   r   )r-   r|   r]   r^   r_   r&   r!   r!   r"   MatrixStudentT$  s   
,

r   N)-r   r   r   r   r   r   r   Zsympy.core.sympifyr   r	   Zsympy.matricesr
   r   r   r   r   r   r   r   r   Zsympy.stats.rvr   r   r   r   r   r   r   Zsympy.externalr   r   rK   rM   rt   rv   r   r   r   r   ra   r   rb   ry   r   r   r!   r!   r!   r"   <module>   s.     ,$,	&&
/%2$/-52